1

У меня есть два контейнера, A & B

Они должны существовать во вновь созданной докерной (частной) мостовой сети так, чтобы:

  • A может общаться с миром за пределами моста, но только через указанный шлюз IP
  • B не может общаться вне моста, только с A через определенный порт ip+
  • Предпочитают не требовать использования правил iptables на хосте.
  • Предпочитают не требовать --privileged на A или B , но конкретное --device может быть в порядке
  • Я в порядке с использованием --cap-drop на B для достижения желаемой изоляции

Я немного поэкспериментировал с docker network create bridge private-bridge и различными комбинациями docker run -net=private-bridge но не могу получить нужное мне поведение.

Есть ли способ:

  • сделать это с помощью сети Docker bridge ?, или
  • сделать это с другим стандартным типом сети?, или
  • я должен посмотреть на написание собственного плагина Docker Network?

1 ответ1

1

Похоже, что требуется какой- то SDN, но https://github.com/jpetazzo/pipework было намного проще, чем другие, такие как Contiv и т.д.

Никаких дополнительных привилегий контейнера не требовалось, и контейнеры (даже как root) не могли манипулировать мостом или своими собственными интерфейсами с привилегиями контейнера докера по умолчанию.

Во-первых, установить pipework и brctl

sudo curl https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework \
          > /usr/local/bin/pipework
sudo chmod u+x /usr/local/bin/pipework
sudo apt-get install bridge-utils

Прежде чем мы начнем, проверьте интерфейсы и мосты, определенные в настоящее время:

brctl show | tail -n+2 | awk '{ print $1 }' | xargs echo 
# docker0

ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# eth0 docker0 lo

Для этой демонстрации я создам образ net-tester с основными функциями тестирования сети:

docker run -itd --name=jtest debian:jessie
docker exec -it jtest apt-get update
docker exec -it jtest apt-get install -y traceroute curl dnsutils \
                                         netcat-openbsd jq nmap \
                                         net-tools isc-dhcp-client telnet
docker exec -it jtest apt-get clean
docker commit -p jtest net-tester
docker stop jtest && docker rm jtest

Запустите два контейнера в стандартной сети Docker none :

docker run -itd --net=none --name=node-a net-tester
docker run -itd --net=none --name=node-b net-tester

docker exec -it node-a ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# lo

docker exec -it node-b ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# lo

Создайте мост br0 и и добавьте интерфейсы на br0 для node-a и node-b .

sudo pipework br0 node-a 192.168.10.1/24
sudo pipework br0 node-b 192.168.10.2/24

docker exec -it node-a ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# eth1 lo

docker exec -it node-b ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# eth1 lo

Интерфейс eth1 (с неявным именем) создан в обоих контейнерах.

Давайте теперь посмотрим на хост-мосты и интерфейсы:

brctl show | tail -n+2 | awk '{ print $1 }' | xargs echo
# br0 veth1pl31667 docker0

ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# br0 docker0 eth0 lo veth1pl31645 veth1pl31667

Давайте посмотрим на маршрутизацию на этих контейнерах:

docker exec -it node-a route -n
# Kernel IP routing table
# Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
# 192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

docker exec -it node-b route -n
# Kernel IP routing table
# Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
# 192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

Наконец, мы добавляем интерфейс eth0 к node-b в подсети хоста.

В моем случае: eth0 10.0.0.0/24 gw 10.0.0.1.

sudo pipework eth0 -i eth0 node-b 10.0.0.99/24@10.0.0.1

По-видимому, это также можно сделать с помощью dhcp.

Теперь проверка интерфейсов на node-b дает:

docker exec -it node-b ifconfig | grep encap | awk '{ print $1 }' | xargs echo
# eth0 eth1 lo

Маршрутизация выглядит так:

docker exec -it node-b route -n
# Kernel IP routing table
# Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
# 0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
# 10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
# 192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

Проверить соединение node-a:

docker exec -it node-a ping -c 3 192.168.10.2
# PING 192.168.10.2 (192.168.10.2): 56 data bytes
# 64 bytes from 192.168.10.2: icmp_seq=0 ttl=64 time=0.124 ms
# 64 bytes from 192.168.10.2: icmp_seq=1 ttl=64 time=0.101 ms
# 64 bytes from 192.168.10.2: icmp_seq=2 ttl=64 time=0.092 ms
# --- 192.168.10.2 ping statistics ---
# 3 packets transmitted, 3 packets received, 0% packet loss
# round-trip min/avg/max/stddev = 0.092/0.106/0.124/0.000 ms

docker exec -it node-a ping -c 3 10.0.0.1
# PING 10.0.0.1 (10.0.0.1): 56 data bytes
# ping: sending packet: Network is unreachable

docker exec -it node-a ping -c 3 8.8.8.8
# PING 8.8.8.8 (8.8.8.8): 56 data bytes
# ping: sending packet: Network is unreachable

Проверьте связность node-b:

docker exec -it node-b ping -c 3 192.168.10.1
# PING 192.168.10.1 (192.168.10.1): 56 data bytes
# 64 bytes from 192.168.10.1: icmp_seq=0 ttl=64 time=0.102 ms
# 64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=0.086 ms
# 64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=0.087 ms
# --- 192.168.10.1 ping statistics ---
# 3 packets transmitted, 3 packets received, 0% packet loss
# round-trip min/avg/max/stddev = 0.086/0.092/0.102/0.000 ms

docker exec -it node-b ping -c 3 10.0.0.1
# PING 10.0.0.1 (10.0.0.1): 56 data bytes
# 64 bytes from 10.0.0.1: icmp_seq=0 ttl=64 time=0.312 ms
# 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.314 ms
# 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.289 ms
# --- 10.0.0.1 ping statistics ---
# 3 packets transmitted, 3 packets received, 0% packet loss
# round-trip min/avg/max/stddev = 0.289/0.305/0.314/0.000 ms

docker exec -it node-b ping -c 3 8.8.8.8
# PING 8.8.8.8 (8.8.8.8): 56 data bytes
# 64 bytes from 8.8.8.8: icmp_seq=0 ttl=56 time=19.309 ms
# 64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=18.279 ms
# 64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=19.827 ms
# --- 8.8.8.8 ping statistics ---
# 3 packets transmitted, 3 packets received, 0% packet loss
# round-trip min/avg/max/stddev = 18.279/19.138/19.827/0.643 ms

Любопытно, что хотя node-b может пропинговать другие IP-адреса в подсети Ethernet хоста, он не может пропинговать сам IP-адрес хоста eth0 . Это на самом деле то, что я хотел, поэтому я не беспокоюсь.

Когда оба контейнера остановлены, мы можем очистить мост:

sudo ifconfig br0 down
sudo brctl delbr br0

Для моего конкретного сценария, если я привяжу некоторый демон к 0.0.0.0 на node-b который будет виден всем в локальной сети хоста (через 10.0.0.99), поэтому я должен был быть осторожен, чтобы привязаться конкретно к 192.168.10.2 .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .