Routing dari wadah buruh pelabuhan menggunakan antarmuka jaringan fisik yang berbeda dan gateway default

13

Informasi latar belakang

Saya memiliki server dengan dua antarmuka jaringan yang menjalankan Docker. Docker, seperti beberapa alat virtualisasi, menciptakan antarmuka jembatan Linux yang disebut docker0. Antarmuka ini dikonfigurasi secara default dengan IP 172.17.42.1dan semua wadah Docker berkomunikasi dengan antarmuka ini sebagai gateway mereka dan diberi alamat IP dalam /16kisaran yang sama . Seperti yang saya pahami, semua lalu lintas jaringan ke / dari kontainer melewati NAT, jadi keluar sepertinya berasal 172.17.42.1, dan masuk itu akan dikirim ke 172.17.42.1.

Pengaturan saya terlihat seperti ini:

                                          +------------+        /
                                          |            |       |
                            +-------------+ Gateway 1  +-------
                            |             | 10.1.1.1   |     /
                     +------+-------+     +------------+    |
                     |     eth0     |                      /
                     |   10.1.1.2   |                      |
                     |              |                      |
                     | DOCKER HOST  |                      |
                     |              |                      | Internet
                     |   docker0    |                      |
                     |   (bridge)   |                      |
                     |  172.17.42.1 |                      |
                     |              |                      |
                     |     eth1     |                      |
                     |  192.168.1.2 |                      \
                     +------+-------+     +------------+    |
                            |             |            |     \
                            +-------------+ Gateway 2  +-------
                                          | 192.168.1.1|       |
                                          +------------+            

Masalah

Saya ingin merutekan semua lalu lintas dari / ke wadah Docker apa pun dari eth1 192.168.1.2antarmuka kedua ke gateway default 192.168.1.1, sementara semua lalu lintas dari / ke mesin host keluar eth0 10.1.1.2antarmuka ke gateway default 10.1.1.1. Saya sudah mencoba berbagai hal sejauh ini tidak berhasil tetapi satu hal yang saya pikir paling dekat dengan yang benar adalah dengan menggunakan iproute2 seperti:

# Create a new routing table just for docker
echo "1 docker" >> /etc/iproute2/rt_tables

# Add a rule stating any traffic from the docker0 bridge interface should use 
# the newly added docker routing table
ip rule add from 172.17.42.1 table docker

# Add a route to the newly added docker routing table that dictates all traffic
# go out the 192.168.1.2 interface on eth1
ip route add default via 192.168.1.2 dev eth1 table docker

# Flush the route cache
ip route flush cache

# Restart the Docker daemon so it uses the correct network settings
# Note, I do this as I found Docker containers often won't be able
# to connect out if any changes to the network are made while it's     
# running
/etc/init.d/docker restart

Ketika saya membawa wadah saya tidak bisa keluar sama sekali setelah melakukan ini. Saya tidak yakin apakah antarmuka jembatan ditangani dengan cara yang sama dengan antarmuka fisik untuk jenis perutean ini, dan hanya ingin pemeriksaan kewarasan serta tips tentang cara menyelesaikan tugas yang tampaknya sederhana ini.


sumber
Komentar Anda tentang NAT tidak benar. Ini diatur untuk menyamar di alamat sumber 172.17.0.0/16 di mana antarmuka output tidak docker0. yaitu -P POSTROUTING -s 172.17.0.0/16! -o docker0 -j MASQUERADE. Yang berarti jika paket yang berasal dari wadah buruh pelabuhan keluar melalui eth0 atau eth1 akan mengambil alamat IP antarmuka itu, bukan IP 172.17.xx.
Matt
Terima kasih atas komentar Anda. Jadi itu akan mengubah pendekatan saya untuk perutean dari antarmuka tertentu, benar? Apakah Anda tahu bagaimana saya bisa menyelesaikan ini? Docker tampaknya hanya menggunakan gateway default dari sistem host, dan ini bukan perilaku yang diinginkan. Saya ingin semua hal Docker untuk keluar dari antarmuka tertentu.
Saya tidak yakin mengapa apa yang saya sarankan tidak berfungsi. Tetapi opsi lain bisa menggunakan pipework. github.com/jpetazzo/pipework Juga bagian jaringan lanjutan dari bantuan buruh pelabuhan mungkin berguna untuk dibaca. docs.docker.com/articles/networking
Matt
@Matt Saya berterima kasih atas saran Anda tentang ini. Dari apa yang saya baca, kerja pipa memerlukan perintah tambahan setelah sebuah wadah mulai mendapatkan akses ke gateway yang benar yang tampaknya seperti kerentanan keamanan. Awalnya dibuat untuk menghubungkan wadah bersama di beberapa host, yang sebenarnya bukan tujuan saya di sini. Sedangkan untuk Dokumentasi jaringan lanjutan Docker, saya akan memeriksanya lagi, tetapi sejauh ini belum membantu dalam situasi ini (saya telah membacanya sebelum memposting di sini). Saya akan memposting tautan ke posting ini pada halaman docker Github Issues dan melihat bagaimana hasilnya dari sana.
Berikut ini tautan kembali ke Masalah Github: github.com/docker/docker/issues/13762

Jawaban:

1

Anda mungkin harus melihat lebih jauh pada pengaturan iptables juga. Docker menyamarkan semua lalu lintas yang berasal dari subnet wadah, katakan 172.17.0.0/16, ke 0.0.0.0. Jika Anda menjalankan iptables -L -n -t nat, Anda dapat melihat rantai POSTROUTING di bawah tabel nat yang melakukan ini -

Chain POSTROUTING (ACCEPT kebijakan)
target sumber tujuan opt opt
MASQUERADE semua - 172.17.0.0/16 0.0.0.0/0

Sekarang, Anda dapat menghapus aturan ini dan menggantinya dengan aturan yang menyamarkan semua lalu lintas yang berasal dari subnet wadah ke IP antarmuka kedua Anda - 192.168.1.2, karena itulah yang Anda inginkan. Aturan penghapusan akan, dengan asumsi bahwa itu adalah aturan pertama di bawah rantai POSTROUTING -

iptables -t nat -D POSTROUTING 1

Kemudian Anda menambahkan aturan khusus ini -

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --ke-sumber 192.168.1.2
Daniel t.
sumber
Sebenarnya itu menyamarkannya ke antarmuka output. Bagian tujuan itu hanya mengatakan bahwa lalu lintas yang berasal dari sumber subnet ke tujuan apa pun akan disamarkan.
Matt
Sayangnya ini tidak berhasil. Proses lengkap saya adalah untuk menjalankan: ip rule add from 172.17.0.0/16 table docker ip route add default via 192.168.1.2 dev eth1 table docker ip route flush cache iptables -t nat -D POSTROUTING 1 iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --to-source 192.168.1.2 /etc/init.d/docker restart. Kemudian saya mencoba menjalankan ping dan traceroute dari sebuah wadah, dan tidak dapat mencapai apa pun.
Saya memiliki persyaratan yang sama, host memiliki pengaturan ip sekunder untuk menjangkau IP publik. Dan saya ingin buruh pelabuhan mengikuti juga. Ini bekerja dalam kasus itu: "iptables -t nat -Saya POSTROUTING 1 -s 172.17.0.0/16 -d PUBIP / 32 -j SNAT - to-source SECONDARYIP"
Ram
1

Seorang teman dan saya mengalami masalah persis di mana kami ingin memiliki buruh pelabuhan mendukung beberapa permintaan antarmuka jaringan melayani. Kami secara khusus bekerja dengan layanan AWS EC2 di mana kami juga melampirkan / mengkonfigurasi / memunculkan antarmuka tambahan. Dalam proyek ini , ada lebih dari apa yang Anda butuhkan jadi saya akan mencoba untuk hanya memasukkan apa yang Anda butuhkan di sini.

Pertama, yang kami lakukan adalah membuat tabel rute terpisah untuk eth1:

ip route add default via 192.168.1.2 dev eth1 table 1001

Selanjutnya kita mengonfigurasi tabel mangle untuk menetapkan beberapa tanda koneksi yang masuk eth1:

iptables -t mangle -A PREROUTING -i eth1 -j MARK --set-xmark 0x1001/0xffffffff
iptables -t mangle -A PREROUTING -i eth1 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff

Akhirnya kami menambahkan aturan ini untuk semua fwmarkuntuk menggunakan tabel baru yang kami buat.

ip rule add from all fwmark 0x1001 lookup 1001

iptablesPerintah di bawah ini akan mengembalikan tanda koneksi dan kemudian memungkinkan aturan routing menggunakan tabel routing yang benar.

iptables -w -t mangle -A PREROUTING -i docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff

Saya percaya ini semua yang diperlukan dari contoh kami yang lebih kompleks di mana (seperti saya katakan) proyek kami melampirkan / mengkonfigurasi / membuka eth1antarmuka pada saat boot.

Sekarang contoh ini tidak akan menghentikan koneksi dari eth0melayani permintaan hingga docker0tetapi saya yakin Anda bisa menambahkan aturan routing untuk mencegahnya.

williamsbdev
sumber
@stuntmachine hanya ingin tahu apakah Anda memiliki kesempatan untuk mencoba ini? Jika Anda sudah menemukan sesuatu sendiri, apakah Anda dapat membagikan solusi Anda?
williamsbdev
Hai @williamsbdev - posting lama dan jauh, tetapi apakah Anda pikir solusi ini juga akan bekerja untuk masalah saya pada SO? stackoverflow.com/questions/51312310/...
Jolly Roger
2
Jolly Roger - Saya yakin ini akan menyelesaikan masalah Anda. Saya baru-baru ini meminta tim lain untuk bertanya tentang posting blog ini (pada dasarnya solusi yang sama seperti di sini) dan mereka mengatakan itu bekerja dengan baik. williamsbdev.com/posts/docker-connection-marking
williamsbdev
0

Masquerade bukan dari 172.17.42.1 melainkan

 -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

Yang berarti aturan ini tidak akan berfungsi dengan baik.

ip rule add from 172.17.42.1 table docker

Coba saja

ip rule add from 172.17.0.0/16 table docker
Mat
sumber
Sayangnya ini tidak berhasil. Kontainer saya masih merutekan ke gateway default yang sama dengan host. Inilah yang saya berlari: ip rule add from 172.17.0.0/16 table docker ip route add default via 192.168.1.2 dev eth1 table docker ip route flush cache /etc/init.d/docker restart Dari dalam wadah saya berlari traceroute dan hop pertama adalah 10.1.1.1 padahal seharusnya 192.168.1.1