Aturan-aturan Iptables sehingga wadah buruh pelabuhan dapat mengakses layanan pada IP host

18

Saya mengalami kesulitan mengakses antarmuka pribadi host (ip) dari wadah buruh pelabuhan. Saya cukup yakin bahwa itu terkait dengan aturan Iptables saya (atau mungkin perutean). Ketika saya menambahkan --net=hostbendera docker run, semuanya berfungsi seperti yang diharapkan. Demikian pula ketika saya menentukan bahwa kebijakan INPUT mengikuti liberal -P INPUT ACCEPT, hal-hal juga berfungsi seperti yang saya harapkan. Namun ini adalah opsi yang tidak diinginkan dan tidak aman yang ingin saya hindari.

Karena ini tidak khusus untuk layanan saya (DNS), saya mengecualikannya dari masalah, karena mencari itu dalam kombinasi dengan hasil buruh pelabuhan di area masalah (populer) yang berbeda, menambahkan suara ke hasil pencarian.

Juga menautkan wadah Docker bukan opsi yang layak, karena wadah tertentu perlu dijalankan dengan opsi --net = host, mencegah penautan dan saya ingin membuat situasi yang konsisten jika memungkinkan.

Saya memiliki aturan Iptables berikut. Kombinasi CoreOS, Digital Ocean, dan Docker, saya kira.

-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

Antarmuka host (relevan) saya:

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

Dan saya menjalankan wadah buruh pelabuhan:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

Pada titik ini saya ingin dapat menggunakan layanan lokal, terikat pada 10.129.112.210:53. Sehingga yang berikut harus menghasilkan balasan:

$ ping google.com
^C
$ ping user.skydns.local
^C

Ketika saya menjalankan perintah yang sama dari host saya:

$ 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

Resolv.conf saya

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

Intinya di sini bukan untuk mengakses host publik, tetapi yang internal, menggunakan layanan DNS lokal yang tersedia di host (melalui instance buruh pelabuhan lain).

Untuk mengilustrasikannya lebih jauh (Keahlian desain ascii art saya melampaui iptables fu saya, sehingga harus dikatakan cukup pada titik ini):

 ______________________________________________
|  __________________________           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)

Saya telah mencari, membaca, dan menerapkan berbagai contoh konfigurasi Iptables, tetapi saya tahu terlalu sedikit tentang aturan Iptables yang lebih "canggih" untuk memahami apa yang terjadi dan dengan demikian mendapatkan hasil yang diinginkan.

Output dari 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

Output dari cat /proc/sys/net/ipv4/ip_forward:

1
Dynom
sumber
Bisakah Anda memposting output iptables -t nat -nL? Apakah Anda melakukan analisis paket, katakan lakukan ping dari wadah sumber dan gunakan tcpdump untuk menangkap paket di host.
Daniel t.
Tentu saja, terima kasih telah membantu sejauh ini: pastebin.com/TAaT73nk (Tidak sesuai dengan komentar ..) - edit -> Memperbarui tautan ke pastebin yang tidak kedaluwarsa.
Dynom
Mungkin saya tidak mengerti dengan benar masalah Anda, tetapi saya tidak melihat aturan apa pun untuk mengizinkan permintaan DNS di host. Juga, apakah ip_forward diaktifkan?
Laurentiu Roescu
Hai @LaurentiuRoescu. $ cat /proc/sys/net/ipv4/ip_forward -> 1dan -A INPUT -i eth1 -j ACCEPTmenerima semua koneksi pada antarmuka pribadi . Aturan apa yang Anda lewatkan?
Dynom
2
Saya pikir paket dari wadah berasal dari antarmuka docker0, bukan eth1. coba-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu

Jawaban:

14

Container berkomunikasi dengan host menggunakan docker0antarmuka. Untuk mengizinkan lalu lintas dari wadah, tambahkan:

-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu
sumber
2
Dynom, pelajaran yang mungkin ingin Anda ambil dari ini adalah bahwa mencatat semua penolakan Anda berguna, misalnya dengan iptables -A INPUT -j LOG. Cap IN=docker0akan sangat berguna dalam menentukan aturan tweak apa yang dibutuhkan. Tidak mengambil dari pekerjaan Laurentiu, yang sangat bagus - +1 dari saya!
MadHatter mendukung Monica
5
Bagi orang yang menggunakan UFW, inilah yang saya lakukan untuk memungkinkan semua komunikasi dari wadah Docker menjadi tuan rumah: ufw izinkan masuk pada docker0
Ali Ok
0

Saya telah mengalami situasi yang sangat mirip tetapi menambahkan -A INPUT -i docker0 -j ACCEPTakan membuka semua akses melalui antarmuka eth0 saya dari host docker ke kontainer yang sama sekali tidak seperti yang saya maksudkan.

Dan karena saya perhatikan bahwa kontainer saya hanya memiliki akses terbatas (katakan saja port 22) ke antarmuka host daripada benar-benar dimatikan dari jaringan host, saya meninjau aturan iptables saya dan menemukan aturan dalam rantai IN_public_allow yang harus bertanggung jawab untuk ini. Aturannya adalah -A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT. Jadi saya menambahkan aturan serupa untuk memungkinkan wadah saya mengakses port host lain yang diinginkan, yang menurut saya bisa menjadi cara yang lebih tepat untuk membuka akses jaringan host ke kontainer.

L3w1s
sumber
-i docker0harus memastikan bahwa ini tidak akan mempengaruhi lalu lintas yang tidak datang melalui jaringan docker0. Tata bahasamu tidak jelas. Mungkin Anda mengatakan bahwa akses keluar dari host buruh pelabuhan via eth0 diaktifkan, yang mungkin benar. Saya setuju bahwa aturan yang lebih bertarget dimungkinkan untuk dibuka hanya sebanyak yang Anda butuhkan.
mc0e