Comme demandé par MP, voici ce que j'ai mis en place dans ma boîte.
Pour commencer, une petite description de la topologie réseau.
En fait tout repose sur une passerelle qui réalise le partage des connexions internet pour le réseau privé grâce au NAT.
Il te faut, pour simplifier, trois interfaces réseau avec trois plan d'adressage.
Pour l'exemple, eth0 est reliée au réseau privé (192.168.0.0),
eth1 est reliée au premier routeur sur le sous-réseau 192.168.1.0
et eth2 est reliée au deuxième routeur sur le sous-réseau 192.168.2.0.
Pour info, on peut bien sûr se contenter d'une seule interface avec un seul sous-réseau pour les deux routeurs, voire même d'une seule interface en tout, mais autant commencer par faire simple. 😉
Une fois la configuration matérielle mise en place, passons à la configuration logicielle.
J'utilise deux scripts : le premier pour configurer iptables et les tables de routage statiques. Il prend un paramètre qui spécifie si on utilise le premier routeur, le deuxième, les deux, ou aucun.
Le deuxième script est lancé automatiquement au démarrage et il sert à monitorer les deux liens. En cas de changement d'état, il lance le script de configuration avec le paramètre qui convient.
- script config-gateway :
#!/bin/sh
PRIVATE_NETWORK=192.168.0.0/24 # Private network
PRIVATE_NETWORK_ODD_IPS=192.168.0.1/255.255.255.1 # Odd IPs to be routed via Internet access #1
PRIVATE_NETWORK_EVEN_IPS=192.168.0.2/255.255.255.1 # Even IPs to be routed via Internet access #2
PRIVATE_IP=192.168.0.254 # IP associated to the private interface
PRIVATE_INTERFACE=eth0 # Interface connected to the private network
PUBLIC_NETWORK_1=192.168.1.0/24 # Public network associated to the Internet link #1
PUBLIC_IP_1=192.168.1.254 # IP associated to the public interface #1
PUBLIC_INTERFACE_1=eth1 # Interface connected to the public network #1
PUBLIC_ROUTER_1=192.168.1.253 # IP of the router connected to Internet link #1
MARK_1=4 # Mark associated to packets to forward them to router 1
PUBLIC_NETWORK_2=192.168.2.0/24 # Public network associated to the Internet link #2
PUBLIC_IP_2=192.168.2.254 # IP associated to the public interface #2
PUBLIC_INTERFACE_2=eth2 # Interface connected to the public network #2
PUBLIC_ROUTER_2=192.168.2.253 # IP of the router connected to Internet link #2
MARK_2=5 # Mark associated to packets to forward them to router 2
MODE=$1 # The mode to use (--load-balance | --router-1 | --router-2 | --off)
LOG_FILE=[i]/path/to/log[/i]
# Check the mode provided is correct
case "$MODE" in
--load-balance)
echo
echo "Setting the gateway to split traffic over the 2 routers :"
echo "`date +%x` `date +%T` : Configure gateway to balance traffic" >> $LOG_FILE
;;
--router-1)
echo
echo "Setting the gateway to route all traffic to router #1 :"
echo "`date +%x` `date +%T` : Configure gateway to route traffic to router #1" >> $LOG_FILE
;;
--router-2)
echo
echo "Setting the gateway to route all traffic to router #2 :"
echo "`date +%x` `date +%T` : Configure gateway to route traffic to router #2" >> $LOG_FILE
;;
--off)
echo 0 > /proc/sys/net/ipv4/ip_forward
# Flush all firewall rules
iptables -t filter -F
iptables -t nat -F
iptables -t mangle -F
# Set default policies to DROP all packets
iptables -t filter -P INPUT DROP
iptables -t filter -P OUTPUT DROP
iptables -t filter -P FORWARD DROP
# Accept ICMP traffic
iptables -t filter -A INPUT -p icmp -j ACCEPT # Accept ICMP input (e.g. PING requests)
iptables -t filter -A OUTPUT -p icmp -j ACCEPT # Accept ICMP output (e.g. PING replies)
# Accept VNC connections from the inner network
iptables -t filter -A INPUT -s $PRIVATE_NETWORK -i $PRIVATE_INTERFACE -d $PRIVATE_IP -p tcp --dport 5900 -j ACCEPT # Accept VNC packets from the inner network
iptables -t filter -A OUTPUT -s $PRIVATE_IP -d $PRIVATE_NETWORK -o $PRIVATE_INTERFACE -p tcp --sport 5900 -j ACCEPT # Accept VNC packets to the inner network
echo "Gateway disabled"
echo "`date +%x` `date +%T` : Gateway disabled" >> $LOG_FILE
exit 0
;;
*)
echo "Usage: $0 {--load-balance|--router-1|--router-2|--off}"
exit 1
esac
###################################################################################################
### Setting the firewall rules ###
###################################################################################################
echo
echo " *** Setting up iptables rules ***"
echo
# Allow to forward packets to another interface
echo 1 > /proc/sys/net/ipv4/ip_forward
# Restart the service to make sure it is started
service iptables restart
# Flush all firewall rules
iptables -t filter -F
iptables -t nat -F
iptables -t mangle -F
# Set default policies to DROP all packets
iptables -t filter -P INPUT DROP
iptables -t filter -P OUTPUT DROP
iptables -t filter -P FORWARD DROP
# Source NAT packets from the private network to public IPs of the firewall
iptables -t nat -A POSTROUTING -s $PRIVATE_NETWORK -o $PUBLIC_INTERFACE_1 -j SNAT --to-source $PUBLIC_IP_1
iptables -t nat -A POSTROUTING -s $PRIVATE_NETWORK -o $PUBLIC_INTERFACE_2 -j SNAT --to-source $PUBLIC_IP_2
# Mark packets so as to route them according to the mode given as parameter
case "$MODE" in
--load-balance)
# Route the packets to the 2 routers depending on their source IP address
iptables -t mangle -A PREROUTING -s $PRIVATE_NETWORK_ODD_IPS -i $PRIVATE_INTERFACE -j MARK --set-mark $MARK_1
iptables -t mangle -A PREROUTING -s $PRIVATE_NETWORK_EVEN_IPS -i $PRIVATE_INTERFACE -j MARK --set-mark $MARK_2
;;
--router-1)
# Route all packets to the router #1 (e.g. in case of router #2 failure)
iptables -t mangle -A PREROUTING -s $PRIVATE_NETWORK -i $PRIVATE_INTERFACE -j MARK --set-mark $MARK_1
;;
--router-2)
# Route all packets to the router #2 (e.g. in case of router #1 failure)
iptables -t mangle -A PREROUTING -s $PRIVATE_NETWORK -i $PRIVATE_INTERFACE -j MARK --set-mark $MARK_2
;;
esac
###################################################################################################
### Setting up the routing rules ###
###################################################################################################
echo
echo " *** Setting up routing rules ***"
echo
# Flush tables that will be used later
ip rule del fwmark $MARK_1
ip rule del fwmark $MARK_2
ip route flush table $MARK_1
ip route flush table $MARK_2
# Populate the 2 tables with the main routes
ip route show table main | grep -Ev ^default | while read ROUTE ; do
ip route add table $MARK_1 $ROUTE
ip route add table $MARK_2 $ROUTE
done
# Add the default route for each table
ip route add table $MARK_1 default via $PUBLIC_ROUTER_1
ip route add table $MARK_2 default via $PUBLIC_ROUTER_2
# Associate the firewall marks to the tables
ip rule add fwmark $MARK_1 table $MARK_1
ip rule add fwmark $MARK_2 table $MARK_2
# Flush the cache
ip route flush cache
- script internet-link-monitor :
#!/bin/sh
# The time to wait between two ping sessions
SLEEP_TIME=2
# The addresses to ping to make sure the links are available
ADDRESS_ROUTER_1=192.168.1.253
ADDRESS_ROUTER_2=192.168.2.253
# The script to launch if one link fails or comes back to life
SCRIPT_FILE=[i]/path/to/config-gateway[/i]
# Options to provide to the config-gateway script
BOTH_ROUTERS_OPTION=--load-balance
ROUTER_1_OPTION=--router-1
ROUTER_2_OPTION=--router-2
NO_ROUTER_OPTION=--off
# Status of the Internet links
STATUS_LINK_1=unknown
STATUS_LINK_2=unknown
while true; do
# New status right after ping
NEW_STATUS_LINK_1=up
NEW_STATUS_LINK_2=up
ping -c 5 $ADDRESS_ROUTER_1 > /dev/null
if [ $? != 0 ]; then
NEW_STATUS_LINK_1=down
fi
ping -c 5 $ADDRESS_ROUTER_2 > /dev/null
if [ $? != 0 ]; then
NEW_STATUS_LINK_2=down
fi
if [ $NEW_STATUS_LINK_1 != $STATUS_LINK_1 ] || [ $NEW_STATUS_LINK_2 != $STATUS_LINK_2 ]; then
# At least one status has changed
if [ $NEW_STATUS_LINK_1 = $NEW_STATUS_LINK_2 ]; then
if [ $NEW_STATUS_LINK_1 = up ]; then
# Both routers are up
$SCRIPT_FILE $BOTH_ROUTERS_OPTION
else
# Both routers are down
$SCRIPT_FILE $NO_ROUTER_OPTION
fi
elif [ $NEW_STATUS_LINK_1 = up ]; then
# Router #1 is up and router #2 is down
$SCRIPT_FILE $ROUTER_1_OPTION
elif [ $NEW_STATUS_LINK_2 = up ]; then
# Router #1 is down and router #2 is up
$SCRIPT_FILE $ROUTER_2_OPTION
fi
STATUS_LINK_1=$NEW_STATUS_LINK_1
STATUS_LINK_2=$NEW_STATUS_LINK_2
fi
sleep $SLEEP_TIME
done
Je te laisse prendre connaissance de ces deux scripts.
Si tu as besoin de plus d'explications, n'hésite pas.
Tout ce que tu as à faire, c'est de rajouter toutes les règles d'iptables que tu utilises dans le script config-gateway pour qu'elles soient rechargées à chaque fois et de lancer la commande suivante pour que le script internet-link-monitor soit lancé au démarrage de la passerelle :
echo "/path/to/internet-link-monitor &" >> /etc/rc.d/rc.local
Bon courage et n'hésitez pas à me faire part de vos commentaires.