This is an old revision of the document!
Afin de mettre en place du routage dynamique, nous avons besoin d'un système permettant facilement de pouvoir router les paquets, avec quelque chose comme ip route. Comme nous avons pu le voir a la fin de la partie précédente, IPsec nécessite beaucoup de configuration des deux cotés pour router quelque chose en plus. Afin d'eviter ce genre de problèmes, nous allons mettre en place des tunnels IP sur nos tunnels IPsec.
Les tunnels gre ou ipip permettent dans un cas comme dans l'autre de faire un tunnel ip over ip, et ainsi de pouvoir router nos paquets.
La première fois que j'ai mis cette solution en place avec un tunnel ipip, cela a rapidement fonctionné. Malheuresement, peu après, un petit problème technique est apparu chez un ami avec ipip sous NetBSD, et nous sommes donc passé à des tunnels gre.
En fait, sous Linux, pour ce que j'en utilise ici, il suffit de changer le mot clef indiquant le nom du tunnel! La configuration étant tellement similaire, je vais donc mettre en place du ipip entre les deux premiers serveurs, et du gre entre ces serveurs et le troisième.
Comme nous avons vu précédement, nous avons pris des adresses IP dédiée pour les différents peer IPsec, nous allons de la même manière prendre des IP dédiée pour les peers de ces tunnels.
srv1: 172.16.1.1/32 srv2: 172.16.1.2/32 srv3: 172.16.1.3/32
La mise en place du tunnel se fait simplement avec les commandes suivantes :
ip tunnel add ipiptun2 mode ipip local 172.16.0.1 remote 172.16.0.2 ttl 64 ip addr add dev ipiptun2 172.16.1.1 peer 172.16.1.2 ip link set dev ipiptun2 up
et sur le serveur 2 :
ip tunnel add ipiptun1 mode ipip local 172.16.0.2 remote 172.16.0.1 ttl 64 ip addr add dev ipiptun1 172.16.1.2 peer 172.16.1.1 ip link set dev ipiptun1 up
Note: sous linux, il est possible de donner le nom que l'on souhaite aux interfaces réseaux, afin de facilité la reconnaissance des interfaces, je les appel ici avec le nom du protocol (ipip ici), puis 'tun' pour tunnel, et le numéro du serveur vers lequel il va.
et hop, aussi simplement que cela, ca fonctionne !
srv1# ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_req=1 ttl=64 time=1.07 ms
Bon, maintenant, pour les avoir au démarrage, il va falloir modifier le fichier /etc/network/interfaces.
A défaut de trouver un helper permettant facilement de mettre en place des tunnels, il faut indiquer l'ensemble des commandes à la main :
auto ipiptun2 iface ipiptun2 inet manual up ip tunnel add ipiptun2 mode ipip local 172.16.0.1 remote 172.16.0.2 ttl 64 up ip addr add dev ipiptun2 172.16.1.1 peer 172.16.1.2 up ip link set dev ipiptun2 up down ip tunnel del ipiptun2
Bon, maintenant, une solution, c'est également de se faire un helper (en attachement sur cette page), afin de se simplifier la vie :
auto ipiptun2 iface ipiptun2 inet manual tunnel_mode ipip direct_peers 172.16.0.1 172.16.0.2 tunnel_peers 172.16.1.1 172.16.1.2
Que je trouve beaucoup plus convivial, surtout lorsque l'on commence a en avoir plusieurs…
Maintenant que nous avons des tunnels dans nos tunnels, nous allons pouvoir y faire passer des routes automagiquement avec du BGP !
Pour faire du BGP, nous allons installer quagga.
# apt-get install quagga
On commence par activer zebra (le routeur principal de quagga), et le module bgpd, dans /etc/quagga/daemons :
zebra=yes bgpd=yes
Puis on configure zebra de facon light :
hostname srv1 log file /var/log/quagga/zebra.log line vty
Et viens la configuration de bgdp. Celle-ci nécessite la configuration d'un numéro d'AS (Autonomous System). Evidement, vu que l'on souhaite propager des routes privées, il ne s'agit nullement d'avoir des AS public… de la même facon qu'il existe des adresses IP privées, il y a également des numéros d'AS privé : de 64512 à 65535 (soit 1024, ce qui devrait être largement suffisant pour faire mumuse). Ici, nous allons prendre 65000 + le numéro du serveur.
/etc/quagga/bgpd.conf :
hostname srv1 log file /var/log/quagga/bgpd.log debug bgp updates router bgp 65001 bgp router-id 172.16.1.1 redistribute static redistribute kernel redistribute connected neighbor 172.16.1.2 remote-as 65002 neighbor 172.16.1.2 distribute-list filter in neighbor 172.16.1.2 distribute-list filter out neighbor 172.16.1.3 remote-as 65003 neighbor 172.16.1.3 distribute-list filter in neighbor 172.16.1.3 distribute-list filter out access-list filter deny 172.16.0.0/12 access-list filter deny 10.0.0.0/8 access-list filter permit 192.168.0.0/16 access-list filter deny 1.1.1.0/24 access-list filter permit any line vty
Par convention, pour le router-id
, on utilise une IP du routeur bgp.
La, ils ont tous une IP direct avec laquelle ils se connectent les uns
aux autres, c'est donc logiquement que j'utilise cette IP là.
L'option redistribute
permet ici de signaler que l'on souhaite
respectivement redistribuer les routes correspondant aux sous-réseaux
directement connecté (généralement, ceux sur lesquels on a une IP), les
routes ajoutés explicitement de facon externe (route add par exemple),
ainsi que les routes fournis statiquement au niveau du routeur (que l'on
pourrait ajouter dans la configuration zebra).
Les neighbor peer distribute-list
permette de placer une acl en
entrée en en sortie sur les routes que l'on accepte de recevoir et
d'envoyer. Ici, j'appel l'acl filter
, et j'utilise la même pour
tout. Pas de raison de trop compliquer les choses.
172.16/12
que nous avons actuellement sont des IP direct pour nos tunnels, et nous n'y avons rien d'autre. Aucune raison de vouloir les transmettre en bgp. 10/8
ne sont pas encore utilisées. Plus tard, je les utiliserais pour les tunnels vpn “externe”, et n'auront donc absolument aucun but d'être transmit en bgp. 192.168/16
sont les plages qui nous intéresse. Il est important de les partager !1.1.1.0/24
(à modifier sur les autres) est la plage publique dans laquelle il se trouve, contenant entre autre l'IP d'interco publique des tunnels IPsec. Si l'on transmet cette route via bgp, on va juste tenter d'envoyer nos paquets IPsec via le tunnel ipip qui passe sur IPsec, qui passe sur ipip, qui passe… Il ne faut pas. Vraiment.
Note: certaines versions peuvent avoir besoin de
neighbor peer update-source
, ou neighbor peer default-originate
pour partager les routes par defaut… dixit la doc.
On met tout ca en place, on lance quagga
# /etc/init.d/quagga start Loading capability module if not yet done. Starting Quagga daemons (prio:10): zebra bgpd.
On attend un peu… et hop, des routes apparaissent !
# ip route | grep zebra 192.168.3.1 via 172.16.1.3 dev gretun3 proto zebra metric 1 192.168.2.0/24 via 172.16.1.2 dev ipiptun2 proto zebra metric 1
Bon, ca marche presque. Si l'on coupe un tunnel, on aura bien les routes qui se mettent en place pour passer par le troisième. Donc, par exemple, si l'on coupe le tunnel entre srv1 et srv2, les routes pour le sous-réseau passeront via srv3.
MAIS, si l'on tente de ping depuis srv1, on communiquera de base avec une adresse 172.16.1.1, qui n'est *pas* routé (et qui ne doit pas, vu que c'est l'ip des peers de tunnels direct).
Deux solutions. Soit l'on passe nos tunnels avec des IPs différentes pour chacun de nos peers, et donc on saura toujours par ou passer, soit l'on SNAT les paquets sortant provenant des IPs tunnels n'étant pas a destination d'un autre peer de tunnel.
Bien évidement, je prend la deuxième solution. On ajoute donc dans la configuration du firewall :
# SNAT what we send through a tunnel, if not directly to a peer. # BGP does it works so it knows how to get back :) $iptables -t nat -N snat_tun $iptables -t nat -A POSTROUTING -s 172.16.1.1 -j snat_tun $iptables -t nat -A snat_tun -d 172.16.1.0/24 -j RETURN $iptables -t nat -A snat_tun -j SNAT --to-source 192.168.1.1
Note: pour srv3, attendu qu'il n'a pas de sous-réseau, et donc d'ip
propre, nous ajoutons également l'adresse 192.168.3.1/32
a son
interface dummy0:
up ip addr add 192.168.3.1/32 dev dummy0 down ip addr del 192.168.3.1/32 dev dummy0 || true
Voilà. Tout est en place. Si un lien tombe, cela passera par un autre tunnel… et avec une IP dont la route de retour est transmise via bgp.