User Tools

Site Tools


system:tunnelling:bgp

Contexte

BGP

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.

IPIP ou GRE ?

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…

quagga

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.

  • Les IPs 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.
  • Les adresses 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.
  • Les plages en 192.168/16 sont les plages qui nous intéresse. Il est important de les partager !
  • Finalement, sur le premier serveur, la plage 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.
  • Et finalement, on autorise le reste… ca permettra de pouvoir faire passer les default route plus tard. (en fait, elles vont deja passer… mais elles ne sont juste pas etre prise en compte, parce que l'on a deja une route par defaut… on verra plus tard comment mind trick'er notre système sur ce point)

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 

petit trick pour les serveurs

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.

system/tunnelling/bgp.txt · Last modified: 2011/08/28 19:52 by ze