У мене є проблеми з доступом до приватного інтерфейсу хоста (ip) з контейнера докера. Я досить впевнений, що це пов'язано з моїми правилами Iptables (або, можливо, маршрутизацією). Коли я додаю --net=host
прапор docker run
, все працює так, як очікувалося. Точно так само, коли я уточнюю, що політика INPUT слідує за лібералом -P INPUT ACCEPT
, все також працює так, як я б очікував. Однак це небажані та небезпечні варіанти, яких я хотів би уникати.
Оскільки це не характерно для моїх служб (DNS), я виключив це з проблеми, оскільки пошук цього в поєднанні з докером дає результати в іншій (популярній) проблемній області, додаючи шум результатам пошуку.
Також зв'язування контейнерів Docker не є життєздатним варіантом, тому що певні контейнери потрібно запускати з опцією --net = хост, запобігаючи посиланням, і я хочу створити послідовну ситуацію, де це можливо.
У мене є такі правила Iptables. Я вважаю, що комбінація CoreOS, Digital Ocean та Docker.
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
Мій (відповідний) хост-інтерфейс:
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
І запускаю докер-контейнер:
$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.
У цей момент я хочу мати можливість користуватися локальним сервісом, прив’язаним до 10.129.112.210:53. Так що відповідь має отримати:
$ ping google.com
^C
$ ping user.skydns.local
^C
Коли я запускаю ту саму команду від свого хоста:
$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C
Моя резолюція.conf
$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
Сенс у цьому полягає не в доступі до публічних хостів, а до внутрішніх, використовуючи локальну службу DNS, доступну на хості (через інший екземпляр докера).
Щоб проілюструвати це ще більше (Мої навички дизайну мистецтва ascii перевершують мою iptables fu, так що цього могло б сказати досить):
______________________________________________
| __________________________ Host |
| | Docker DNS container | |
| ``````````````````````|``` |
| | |
| ,----------,---( private n. interface ) |
| | | |
| | | ( public n. interface )---
| | | |
| | | ( loopbck n. interface ) |
| | | |
| | | |
| | __|_______________________ |
| | | Docker service container | |
| | `````````````````````````` |
| | |
| | |
| [ Local host service using DNS. ] |
| |
|______________________________________________|
private (host) network interface: eth1 (10.129.0.0/16)
Docker network interface: docker0 (172.17.0.0/16)
Я шукав, читав і застосовував різні приклади конфігурацій Iptables, але я знаю занадто мало про "просунутіші" правила Iptables, щоб зрозуміти, що відбувається, і, таким чином, отримати бажаний результат.
Вихід iptables -t nat -nL
:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
Вихід cat /proc/sys/net/ipv4/ip_forward
:
1
$ cat /proc/sys/net/ipv4/ip_forward -> 1
і -A INPUT -i eth1 -j ACCEPT
приймає всі з'єднання в приватному інтерфейсі. Які правила вам не вистачає?
-A INPUT -i docker0 -j ACCEPT
iptables -t nat -nL
? Ви робили якийсь аналіз пакетів, скажімо, зробіть ping з вихідного контейнера та використовуйте tcpdump для захоплення пакетів на хості.