3 votes

Autoriser les conteneurs Docker à utiliser le VPN IPSEC sur l'hôte

J'ai Docker et un tunnel VPN IPSEC sur mon poste de travail, mais les conteneurs ne peuvent pas accéder aux hôtes derrière le VPN. Y a-t-il quelque chose que je puisse faire, par exemple avec IPTables ou des routes pour permettre l'accès ? [Note : Je suis actuellement en train d'exécuter ces tests à partir d'une VM hébergée par libvirt, alors le pont libvirt a l'adresse 192.168.122.1].

Ma configuration réseau ressemble à ceci :

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:0f:f2:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.87/24 brd 192.168.122.255 scope global dynamic ens3
       valid_lft 3490sec preferred_lft 3490sec
    inet6 fe80::5054:ff:fe0f:f2bb/64 scope link 
       valid_lft forever preferred_lft forever
3: tap0: <BROADCAST,UP,LOWER_UP> mtu 1380 qdisc pfifo_fast state UNKNOWN qlen 500
    link/ether d6:2b:f6:24:c5:1c brd ff:ff:ff:ff:ff:ff
    inet 172.20.1.29/24 brd 172.20.1.255 scope global tap0
       valid_lft forever preferred_lft forever
    inet6 fe80::d42b:f6ff:fe24:c51c/64 scope link 
       valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:24:7f:6a:1a brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:24ff:fe7f:6a1a/64 scope link 
       valid_lft forever preferred_lft forever

Mes routes ressemblent à ceci (l'IP de l'extrémité du VPN est masquée) :

default via 192.168.122.1 dev ens3  proto static  metric 100 
10.0.0.0/8 via 172.20.1.29 dev tap0  proto static 
10.11.12.13 via 192.168.122.1 dev ens3  proto static 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 
172.20.1.0/24 dev tap0  proto kernel  scope link  src 172.20.1.29 
192.168.122.0/24 dev ens3  proto kernel  scope link  src 192.168.122.87  metric 100

Je peux voir certaines règles masq existantes, le compteur de paquets de la première règle s'incrémente lorsque j'envoie des pings de test à partir d'un conteneur :

[robin@rhel72 ~]$ sudo iptables -t nat -L -n -v --line-numbers | sed -n '/^Chain POSTROUTING /,/^$/ p'
Chain POSTROUTING (policy ACCEPT 4 packets, 534 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       63  4290 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
2      473 30282 POSTROUTING_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
3      473 30282 POSTROUTING_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
4      473 30282 POSTROUTING_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Enfin, je peux voir ce qui ressemble à une réponse partielle quand je tcpdump la connexion tout en exécutant ping -c1 de l'intérieur du conteneur :

[robin@rhel72 ~]$ sudo tcpdump -i any -n 'icmp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
09:55:01.919214 IP 172.17.0.2 > 10.60.1.201: ICMP echo request, id 27, seq 1, length 64
09:55:01.919214 IP 172.17.0.2 > 10.60.1.201: ICMP echo request, id 27, seq 1, length 64
09:55:01.940613 IP 10.60.1.201 > 172.20.1.29: ICMP echo reply, id 27, seq 1, length 64

EDIT 1

La table de routage à l'intérieur du conteneur Docker est :

[root@451c1c9c708c /]# ip route
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.2

Il est intéressant de noter que j'exécute le démon Docker en utilisant la commande --icc=false pour isoler les conteneurs.

7voto

Alex Points 1

J'ai écrit un programme Python pour envelopper ipsec qui installe des entrées iptables pour permettre aux conteneurs docker de parler au tunnel VPN :

https://github.com/cbrichford/docker-ipsec

Au lieu de faire : ipsec up

Vous le faites : docker-ipsec up

Ce script pourrait avoir besoin d'un peu de travail pour être utilisé avec les dernières fonctionnalités de mise en réseau de docker, mais il fonctionnait avec l'ancienne valeur par défaut. docker0 pont.

Si vous ne voulez pas utiliser mon script pour éditer iptables voici comment construire la commande iptables :

  1. Déterminez l'adresse IP virtuelle de l'hôte dans le VPN. Appelez cette adresse IP virtuelle.
  2. Déterminer le bloc CIDR pour l'adresse IP dans le VPN. Si les adresses IP dans le VPN sont toujours de la forme 10.10.X.X, alors votre bloc CIDR sera 10.10.0.0/16. Appelez cela vpnSubnet
  3. Trouvez l'interface de la route par défaut. Ce sera quelque chose comme "eth0". Voici la commande que j'utilise pour la trouver : sudo ip route show | grep -e "^default" | awk -- "{ print \$5 }" . Appelez cette interface defaultRouteInterface
  4. Déterminez le bloc CIDR du réseau Docker auquel vous voulez accorder l'accès à votre VPN. Cette commande permet de le trouver : sudo ip route show | grep -e "[[:space:]]dev[[:space:]]docker" | awk -- "{ print \$1 }" . Appelez cela dockerSubnet.

La commande iptables que vous devez exécuter est : sudo \ iptables \ -j SNAT \ -t nat \ -I POSTROUTING 1 \ -o ${defaultRouteInterface} \ -d "${vpnSubnet}" \ -s "${dockerSubnet}" \ --to-source "${virtualIP}"

0voto

CodeMedic Points 304

En me basant sur la réponse de @ChristopherBrichford, j'ai réussi à réduire la formule à la commande ci-dessous. Ceci est basé sur ma compréhension limitée des différentes parties mobiles impliquées.

sudo iptables -j SNAT -t nat -I POSTROUTING 1 \
    -o $(ip route show | grep -e "^default" | awk -- "{ print \$5 }") \
    -d $(ip route list table 220 | grep -o '^[0-9.]*/[0-9]*') \
    -s $(ip route show | grep -e ":space:dev:space:docker" | awk -- "{ print \$1 }") \
    --to-source $(ifconfig | grep -o 'P-t-P:[^ ]*' | cut -d: -f2)

Une version plus utilisable et mise à jour est disponible en tant que gist .

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X