Due connessioni a internet per un solo host
Questa configurazione permette a un host di avere due connessioni internet sempre attive. L'host e` accessibile da tutte e due le connessioni indistintamente, e le usa tutte e due in modo bilanciato per il traffico uscente. Usando uno script apposito (ho scopiazzato orrendamente, lo ammetto) e` possibile avere un controllo sulla connettivita` delle due connessioni e provvedere a smettere di usare quella che per qualche motivo dovesse andare offline. Questo ovviamente non impatta le connessioni entranti, ma solo quelle uscenti.
Attenzione: questa configurazione non e` stata provata come sistema per dare connettivita` a degli host nattati dietro a una terza interfaccia. Potrebbe funzionare (con due regole di nat) ma anche no.
Configurazione statica
Questa configurazione definisce le regole necessarie per il routing verso due gateway diversi. E` necessario avere due schede di rete, una per connessione.
- Installare, se non c'e`, il pacchetto iproute2. Nelle nuove installazioni c'e` per default.
Modificare il file /etc/iproute2/rt_tables aggiungendo le nostre due tabelle di routing con nomi a nostro piacere:
200 Fastweb 201 Ehiweb
Modificare il file /etc/network/interfaces in modo da creare tutte le regole necessarie al routing per ogni interfaccia
# prima connessione: subnet 93.33.25.248/29, gw 249, il mio host e` il 253 auto ens18 iface ens18 inet static address 93.33.25.253/29 post-up ip route add 93.33.25.248/29 dev ens18 src 93.33.25.253 table Fastweb post-up ip route add default via 93.33.25.249 table Fastweb post-up ip rule add from 93.33.25.253 table Fastweb post-down ip rule del from 93.33.25.253 table Fastweb # seconda connessione: subnet 109.23.6.48/29, gw 49, il mio host e` il 53 auto ens19 iface ens19 inet static address 109.23.6.53/29 post-up ip route add 109.23.6.48/29 dev ens19 src 109.23.6.53 table Ehiweb post-up ip route add default via 109.23.6.49 table Ehiweb post-up ip rule add from 109.23.6.53 table Ehiweb post-down ip rule del from 109.23.6.53 table Ehiweb
A questo punto abbiamo due interfacce ma nessun default routing. Per stabilire un routing di default statico, possiamo aggiungerlo come post-up all'ultima delle due interfacce, in questo modo:
# sotto alla interfaccia ens19, come ultima riga: post-up p route add default scope global nexthop via 93.33.25.249 dev ens18 weight 1 nexthop via 109.23.6.49 dev ens19 weight 1
Se vogliamo che il traffico uscente eviti di usare una interfaccia che non funziona, occorre, INVECE del routing statico, usare uno script che effettui un controllo costante e cambi le regole di conseguenza.
Script per il controllo del gateway morto
Questo script puo` essere usato per il controllo delle due connettivita`. Provvede a cambiare il default gateway a seconda di quale connessione funziona e quale no. Questo script e` stato copiato, non e` mio. L'autore e` Steve Buzonas e questo e` il link alla versione originale: https://github.com/sbuzonas/multiwan
Installazione
Creare lo script /usr/local/sbin/multiwan contenente quanto segue:
#!/usr/bin/env bash source /etc/multiwan.conf STARTUP=1 CHECK_INTERVAL=1 # IP address of each WAN interface WAN_NET1="$(ip addr show $WAN_IF1 | grep "inet " | tr -s [:space:] | cut -d ' ' -f3)" WAN_NET2="$(ip addr show $WAN_IF2 | grep "inet " | tr -s [:space:] | cut -d ' ' -f3)" WAN_IP1="$(echo $WAN_NET1 | cut -d '/' -f1)" WAN_IP2="$(echo $WAN_NET2 | cut -d '/' -f1)" # Last link status. Defaults to down to force check of both on first run. LLS1=1 LLS2=1 # Last ping status. LPS1=1 LPS2=1 # Current ping status. CPS1=1 CPS2=1 # Change link status. CLS1=1 CLS2=1 # Count of consecutive status checks COUNT1=0 COUNT2=0 function link_status() { case $1 in 0) echo "Up" ;; 1) echo "Down" ;; *) echo "Unknown" ;; esac } # check_link $IP $TIMEOUT function check_link() { ping -W $2 -I $1 -c 1 $PING_TARGET > /dev/null 2>&1 RETVAL=$? if [ $RETVAL -ne 0 ] ; then STATE=1 else STATE=0 fi link_status $STATE return $STATE } while : ; do LINK_STATE="$(check_link $WAN_IP1 $PING_TIMEOUT)" CPS1=$? if [ $LPS1 -ne $CPS1 ] ; then logger -p local6.notice -t MULTIWAN[$$] "Ping state changed for $WAN_TABLE1 from $(link_status $LPS1) to $(link_status $CPS1)" COUNT1=1 else if [ $LPS1 -ne $LLS1 ] ; then COUNT1=`expr $COUNT1 + 1` fi fi if [[ $COUNT1 -ge $SUCCESS_COUNT || ($LLS1 -eq 0 && $COUNT1 -ge $FAILURE_COUNT) ]]; then CLS1=0 COUNT1=0 if [ $LLS1 -eq 1 ] ; then LLS1=0 else LLS1=1 fi logger -p local6.notice -t MULTIWAN[$$] "Link state for $WAN_TABLE1 is $(link_status $LLS1)" else CLS1=1 fi LPS1=$CPS1 LINK_STATE="$(check_link $WAN_IP2 $PING_TIMEOUT)" CPS2=$? if [ $LPS2 -ne $CPS2 ] ; then logger -p local6.notice -t MULTIWAN[$$] "Ping state changed for $WAN_TABLE2 from $(link_status $LPS2) to $(link_status $CPS2)" COUNT2=1 else if [ $LPS2 -ne $LLS2 ] ; then COUNT2=`expr $COUNT2 + 1` fi fi if [[ $COUNT2 -ge $SUCCESS_COUNT || ($LLS2 -eq 0 && $COUNT2 -ge $FAILURE_COUNT) ]]; then CLS2=0 COUNT2=0 if [ $LLS2 -eq 1 ]; then LLS2=0 else LLS2=1 fi logger -p local6.notice -t MULTIWAN[$$] "Link state for $WAN_TABLE2 is $(link_status $LLS2)" else CLS2=1 fi LPS2=$CPS2 if [[ $CLS1 -eq 0 || $CLS2 -eq 0 ]] ; then if [[ $STARTUP -eq 1 ]] ; then STARTUP=0 CHECK_INTERVAL=15 fi if [[ $LLS1 -eq 1 && $LLS2 -eq 0 ]] ; then logger -p local6.notice -t MULTIWAN[$$] "Applying $WAN_TABLE2 only route." ip route change default scope global via $WAN_GW2 dev $WAN_IF2 elif [[ $LLS1 -eq 0 && $LLS2 -eq 1 ]] ; then logger -p local6.notice -t MULTIWAN[$$] "Applying $WAN_TABLE1 only route." ip route change default scope global via $WAN_GW1 dev $WAN_IF1 elif [[ $LLS1 -eq 0 && $LLS2 -eq 0 ]] ; then logger -p local6.notice -t MULTIWAN[$$] "Applying multiwan load balancing route." ip route replace default scope global nexthop via $WAN_GW1 dev $WAN_IF1 weight $WAN_WEIGHT1 nexthop via $WAN_GW2 dev $WAN_IF2 weight $WAN_WEIGHT2 fi fi sleep $CHECK_INTERVAL done
- Rendere eseguibile il suddetto script
Creare lo script di init /etc/init.d/multiwan (si suppone che non usiate quella ciofeca di systemd!)
### BEGIN INIT INFO # Provides: multiwan # Required-Start: $network $local_fs $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Monitor internet connection links and modify route depending upon link state # Description: This is a startup script for multiwan. Multiwan monitors multiple internet connections # to provide failover routes depending upon link state. ### END INIT INFO # Author: Steve Buzonas <steve@fancyguy.com> # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC=multiwan # Introduce a short description here NAME=multiwan # Introduce the short server's name here DAEMON=/usr/local/sbin/multiwan # Introduce the server's location here DAEMON_ARGS="" # Arguments to run the daemon with PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x $DAEMON ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet -b -m --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet -b -m --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; restart|force-reload) log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac :
- Rendere eseguibile il suddetto script
Creare la configurazione in /etc/multiwan.conf avendo cura di adattarla ai vostri nomi, interfacce e indirizzi IP
PING_TARGET="8.8.8.8" PING_TIMEOUT=2 SUCCESS_COUNT=4 FAILURE_COUNT=1 WAN_IF1="ens18" WAN_IF2="ens19" WAN_GW1="93.33.25.249" WAN_GW2="109.23.6.49" WAN_TABLE1="Fastweb" WAN_TABLE2="Ehiweb" WAN_WEIGHT1=1 WAN_WEIGHT2=1
- Fare eseguire lo script multiwan al boot, rendendolo attivo come demone, usando il comando:
insserv multiwan
A questo punto, riavviando la macchina (ce l'avete una console che funzioni anche SENZA LA RETE, vero? Se abbiamo sbagliato qualcosa, addio connessione di rete, ci siamo chiusi fuori per sempre!) dovremmo avere due interfacce di rete attive, e nel syslog vedremo anche le righe relative allo script multiwan che ci dice quali interfacce sta usando e come.
Test
La macchina dovrebbe essere raggiungibile da fuori a tutti e due i suoi indirizzi pubblici. Staccando una delle due linee l'altra dovrebbe rimanere totalmente funzionante, e la macchina dovrebbe (dopo qualche secondo) usare sempre la connessione funzionante, saltando dall'una all'altra automaticamente.