Betulkan Trafik Docker dan WSL yang Mengabaikan VPN Hos
Kontena dan WSL menyimpan laluan, penyelesai dan laluan penghantaran sendiri, jadi terowong hos yang berfungsi meninggalkan mereka dengan DNS lapuk atau tanpa jalan keluar. Betulkan setiap lapisan.
Saya menghabiskan sebahagian besar pagi musim bunga ini mengejar kontena yang tidak dapat menyelesaikan satu nama dalaman, sedangkan pelayar di sebelahnya membuka wiki tanpa rungutan. Terowong sudah naik, pelayar membuktikannya, dan kontena itu berada di ruang nama rangkaian lain dengan jadual laluan berbeza dan penyelesai berbeza. Berikut ialah urutan yang saya semak sekarang: jadual laluan dahulu, penyelesaian kedua, penghantaran ketiga, dan platform hos terakhir. Berhenti pada langkah pertama yang sudah gagal, kerana menambah peraturan lebih jauh ke bawah tindanan menyembunyikan sempadan dan bukan memindahkannya.
Bandingkan ketiga-tiga jadual laluan sebelum anda mengubah peraturan
Kontena pada jambatan lalai Docker mempunyai satu laluan lalai yang menuju ke get laluan docker0 dan tidak tahu bahawa tun0 wujud. Hos mempunyai tun0, laluan yang ditolak oleh VPN, dan mungkin peraturan dasar yang menghantar trafik ujian melalui antara muka berbeza daripada yang anda jangkakan. WSL menambah jadual ketiga di belakang penyesuai mayanya sendiri. Cetak ketiga-tiganya sebelum menyunting mana-mana satu.
| Context | Command | What a wrong answer looks like |
|---|---|---|
| Host | ip route get 10.8.0.20 | Leaves a physical interface instead of tun0 |
| Container | ip route | Only 172.17.0.0/16 via 172.17.0.1 |
| Container DNS | cat /etc/resolv.conf | A public resolver, or an upstream the tunnel never pushed |
| WSL | ip addr; ip route | Only the WSL subnet, no Windows VPN adapter |
Jika satu-satunya laluan kontena ialah jambatan dan tun0 tidak pernah muncul dalam ruang namanya, tiada apa di bawah akan membantu: tiada perubahan pelayan nama mencipta laluan, dan tiada laluan mencipta identiti terowong yang akan diterima oleh rakan. Urutan penting kerana kegagalan DNS dan kegagalan laluan kelihatan sama dari dalam shell.
Halakan penyelesai ke terowong dan bukan ke penyelesai awam
Pada hos, resolvectl status menyenaraikan pelayan DNS bagi setiap pautan, dan readlink -f /etc/resolv.conf memberitahu anda sama ada fail itu stub systemd, fail NetworkManager, atau sesuatu yang ditulis semula oleh klien vendor. Di dalam kontena pada rangkaian yang ditakrifkan pengguna, /etc/resolv.conf menamakan 127.0.0.11, penyelesai terbina Docker, yang menghantar ke upstream yang digunakan semasa daemon dikonfigurasikan. Kontena pada jambatan lalai pula menerima salinan fail hos semasa ia dicipta, dan menyimpannya.
Salinan itulah sebabnya terowong yang naik selepas kontena bermula membiarkan kontena menanyakan upstream lama. Sama ada hantar penyelesai VPN secara jelas dengan docker run --dns 10.8.0.53, atau tetapkan "dns": ["10.8.0.53"] dalam /etc/docker/daemon.json dan mulakan semula daemon, atau cipta semula kontena setelah terowong naik. Mencipta semula biasanya lebih murah daripada menyahpepijat penyelesai yang betul sejam yang lalu.
Menukar kepada penyelesai awam ialah pembaikan yang mengekalkan simptom. Ia menyelesaikan internet dan gagal dalam setiap zon peribadi, dan ia boleh memintas penapisan yang menjadi sebab terowong itu wujud secara senyap. Jika anda cuba menulis di dalam /etc/resolv.conf kontena yang sedang berjalan, jangkakan Device or resource busy: Docker melakukan bind-mount fail itu, jadi suntingan memerlukan nyahlekap dahulu. Menetapkan --dns semasa penciptaan ialah urutan yang bertahan selepas permulaan semula.
Hantar dan terjemah apabila kontena meminjam terowong
Dengan jambatan lalai, hos ialah penghala antara docker0 dan tun0, dan secara lalai ia tidak melakukan kedua-dua tugas itu. Hidupkan penghantaran dan terjemahkan alamat sumber supaya rakan melihat alamat terowong hos dan bukan alamat yang tiada laluan balik (gantikan tun0 dengan nama yang klien anda berikan pada antara muka):
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i docker0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o docker0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTPeraturan FORWARD penting pada hos yang dasar penghantarannya DROP. Docker memasukkan rantaiannya sendiri, jadi uji dengan paket dan bukan dengan membaca iptables -S: dari kontena, ip route get 10.8.0.20 sepatutnya menamakan get laluan jambatan, dan nc -vz 10.8.0.20 443 sepatutnya bersambung atau tamat masa di terowong dan bukan di penyelesai.
Tanpa MASQUERADE rakan memerlukan laluan balik ke 172.17.0.0/16, yang tidak akan ditolak oleh kebanyakan VPN akses jauh. Di sinilah juga klien berasaskan dasar memecahkan rancangan: jika ia hanya menangkap trafik daripada UID atau cgroups tertentu, peraturan penghantaran anda tidak pernah melihat paket di dalam terowong, dan pembaikan itu terletak pada dasar penghalaan klien dan bukan pada iptables. Peraturan yang ditambah dengan tangan hilang selepas permulaan semula, jadi letakkan dalam unit systemd atau jadual netfilter-persistent dan uji semula selepas permulaan semula, kerana terowong yang naik lewat boleh menyapunya.
Letakkan terowong di dalam kontena apabila tujuannya pengasingan
Jika satu kontena perlu keluar melalui nod tertentu, jalankan klien dalam kontena itu. Ia memerlukan --cap-add NET_ADMIN dan --device /dev/net/tun, dan kemudian ia memiliki tun0, laluan dan dinding api sendiri. Jika kontena lain melaluinya, ia juga memerlukan penghantaran dan peraturan MASQUERADE di dalam kontena, dan rakan-rakan itu memerlukan laluan atau proksi eksplisit yang menuju kepadanya; jambatan lalai Docker tidak menambah laluan itu untuk anda.
Rangkaian hos, docker run --network host, ialah versi murah: kontena menyertai ruang nama hos dan melihat laluan terowong secara langsung. Ia juga menggugurkan pengasingan rangkaian, mengundang perlanggaran port, dan dalam praktiknya ialah pilihan Linux. Port yang diterbitkan bukan pengganti. -p 8080:80 menjadikan perkhidmatan boleh dicapai dari hos; ia tidak menjadikan alamat dalaman 10.x boleh dicapai dari dalam kontena, dan mencampuradukkan kedua-duanya ialah cara masalah penghalaan menjadi port pangkalan data yang terdedah.
Bezakan kegagalan nama daripada subrangkaian bertindih
Jambatan lalai Docker ialah 172.17.0.0/16, dan banyak kumpulan VPN korporat terletak dalam 172.16.0.0/12. Setelah terowong memiliki julat itu, trafik yang dimaksudkan untuk kontena boleh dihalakan ke dalam terowong. Nama gagal, ralat kelihatan seperti DNS, dan masalahnya ialah alamat. Semak destinasi, bukan penyelesai: ip route get 172.17.0.5 pada hos, kemudian bandingkan awalan jambatan dengan kumpulan VPN dan dengan docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.
Pembaikannya ialah memindahkan salah satu julat: sama ada kumpulan alamat lalai yang berbeza untuk Docker dalam daemon.json atau kumpulan berbeza pada penumpu. Menambah pelayan nama lain tidak melakukan apa-apa di sini, dan begitu juga ssh -b: mengikat klien pada antara muka menukar alamat sumber, bukan laluan destinasi yang menuju ke dalam terowong. Pembahagian kerja pantas: nama yang diselesaikan pada hos tetapi tidak dalam kontena ialah masalah penyelesai, manakala sambungan IP langsung yang tergantung dalam kontena tetapi berfungsi pada hos ialah masalah laluan atau rantaian penghantaran.
WSL dan Docker Desktop tidak mengikut peraturan Linux
Dalam mod NAT lalainya, WSL berada di belakang penyesuai mayanya sendiri dan tidak menerima laluan dalaman atau akhiran DNS VPN Windows, itulah sebabnya pelayar berfungsi dan ping di dalam pengedaran tidak. Rangkaian cermin, tersedia dalam binaan Windows 11 terkini, berkongsi antara muka hos, tetapi ia perlu dihidupkan dalam .wslconfig dan pengedaran dimulakan semula dengan wsl --shutdown. Sahkan mod aktif dengan wslinfo --networking-mode sebelum menggunakan pembaikan, kerana jawapan NAT salah untuk mod cermin dan sebaliknya.
Docker Desktop menambah satu lagi lapisan. Kontena Linux pada Windows berada di belakang pelaksanaan NAT yang secara sejarah dipanggil vpnkit, dan laluannya berbeza daripada hos Linux asli. Kontena Windows bersambung melalui suis maya Hyper-V, dan klien korporat boleh menyekat trafik daripada suis itu, jadi kontena Linux pada mesin yang sama boleh mencapai rangkaian manakala kontena Windows tidak mempunyai apa-apa. Suis luaran yang terikat pada penyesuai fizikal ialah penyelesaian biasa, dan ia mengubah identiti rangkaian kontena dengan cara yang mungkin tidak dibenarkan oleh dasar.
Sebelum menulis peraturan lain, telusuri empat lapisan mengikut urutan dan berhenti di tempat salah satu daripadanya tidak betul:
- Di dalam kontena: adakah
ip routemencapai awalan peribadi, dan adakah/etc/resolv.confmenamakan upstream yang menyelesaikannya? - Pada hos: adakah penghantaran dihidupkan, adakah NAT terikat pada antara muka terowong, dan adakah rantaian penghantaran menerima jambatan ke terowong?
- Pada rakan: adakah ia tahu laluan balik, atau anda bergantung pada NAT untuk menyembunyikan subrangkaian kontena?
- Pada platform: adakah WSL dalam mod NAT atau cermin, dan adakah kontena itu Linux atau Windows?
Jalankan semula setiap ujian dalam kontena atau shell baharu. Proses jangka panjang dengan jawapan cache atau sambungan yang sudah terjalin akan terus gagal selepas konfigurasi betul, dan kegagalan itu kelihatan sama seperti pembaikan yang tidak berkesan.