Host VPN-inə məhəl qoymayan Docker və WSL trafikini düzəldin
Konteynerlər və WSL öz marşrutlarını, həlledicisini və yönləndirmə yolunu saxlayır, ona görə işləyən host tuneli onları köhnəlmiş DNS və ya çıxışsız qoyur. Hər qatı düzəldin.
Bu yaz bir səhərin çoxunu tək bir daxili adı həll edə bilməyən konteynerin arxasınca keçirdim, halbuki yanındakı brauzer vikini heç bir şikayət etmədən açırdı. Tunel qalxmışdı, brauzer bunu sübut edirdi və konteyner fərqli marşrut cədvəli və fərqli həlledici ilə fərqli şəbəkə adlar məkanında. Bundan sonra izlədiyim sıra budur: əvvəlcə marşrut cədvəlləri, ikinci həll, üçüncü yönləndirmə və ən sonda host platforması. Artıq uğursuz olan ilk addımda dayanın, çünki yığının daha aşağısına qaydalar əlavə etmək sərhədi yerindən tərpətmək əvəzinə gizlədir.
Bir qaydanı dəyişməzdən əvvəl üç marşrut cədvəlini müqayisə edin
Docker-in defolt körpüsündəki konteynerin docker0 şlüzünə yönələn bir defolt marşrutu var və tun0-un mövcud olduğundan xəbəri yoxdur. Hostda tun0, VPN-in itələdiyi marşrutlar və ola bilsin ki, yoxlama trafikini gözlədiyinizdən fərqli interfeysdən çıxaran siyasət qaydası var. WSL öz virtual adapterinin arxasına üçüncü cədvəl əlavə edir. Onlardan hər hansı birini redaktə etməzdən əvvəl hər üçünü çap edin.
| 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 |
Əgər konteynerin yeganə marşrutu körpüdürsə və tun0 onun adlar məkanında heç vaxt görünmürsə, aşağıdakıların heç biri kömək etməyəcək: heç bir ad serveri dəyişikliyi marşrut yaratmır və heç bir marşrut həmyaşıdın qəbul edəcəyi tunel kimliyi yaratmır. Sıra vacibdir, çünki DNS uğursuzluğu ilə marşrut uğursuzluğu qabığın içindən eyni görünür.
Həlledicini ictimai olana deyil, tunelə yönəldin
Hostda, resolvectl status hər keçid üzrə DNS serverlərini sadalayır və readlink -f /etc/resolv.conf faylın systemd stub-u, NetworkManager faylı, yoxsa bir vendor müştərisinin yenidən yazdığı bir şey olduğunu bildirir. İstifadəçi tərəfindən təyin olunmuş şəbəkədəki konteynerin içində, /etc/resolv.conf adlandırır 127.0.0.11, Docker-in daxili həlledicisini, hansı ki daemonun konfiqurasiya edildiyi yuxarı axına yönləndirir. Defolt körpüdəki konteyner isə yaradılanda host faylının surətini alıb və onu saxlayır.
Bu surət ona görədir ki, konteyner başladıqdan sonra qalxan tunel konteyneri köhnə yuxarı axına sorğu göndərən vəziyyətdə qoyur. Ya VPN həlledicisini açıq şəkildə ötürün docker run --dns 10.8.0.53, ya da "dns": ["10.8.0.53"] içində /etc/docker/daemon.json təyin edib daemonu yenidən başladın, ya da tunel qalxdıqdan sonra konteyneri yenidən yaradın. Yenidən yaratmaq adətən bir saat əvvəl düzgün olan həlledicini sazlamaqdan ucuzdur.
İctimai həlledici ilə əvəz etmək simptomu saxlayan təmirdir. O, interneti həll edir və hər şəxsi zonada uğursuz olur, və tunelin tətbiq etmək üçün mövcud olduğu filtrləməni səssizcə yan keçə bilər. Əgər işləyən konteynerin /etc/resolv.conf içində yazmağa çalışsanız, Device or resource busy: Docker həmin faylı bind-mount edir, ona görə redaktə əvvəlcə unmount tələb edir. --dns yaradılış zamanı təyin etmək yenidən başlatmadan sağ çıxan ardıcıllıqdır.
Konteynerlər tuneli borc aldıqda yönləndirin və tərcümə edin
Defolt körpü ilə host docker0 və tun0 arasında marşrutlaşdırıcıdır və defolt olaraq bu işlərin heç birini görmür. Yönləndirməni yandırın və mənbə ünvanını tərcümə edin ki, həmyaşıd geri marşrutu olmayan ünvan əvəzinə host tunel ünvanı görsün (tun0-u müştərinizin interfeysə verdiyi adla əvəz edin):
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 ACCEPTFORWARD qaydaları yönləndirmə siyasəti DROP olan hostlarda vacibdir. Docker öz zəncirlərini daxil edir, ona görə oxumaq əvəzinə paketlə sınayın iptables -S: konteynerdən, ip route get 10.8.0.20 körpü şlüzünü adlandırmalıdır və nc -vz 10.8.0.20 443 həlledicidə deyil, tuneldə qoşulmalı və ya vaxt aşımına uğramalıdır.
MASQUERADE olmadan həmyaşıdın 172.17.0.0/16-ya geri marşrutu lazımdır, ki əksər uzaqdan çıxış VPN-ləri bunu itələməyəcək. Bu həm də siyasət əsaslı müştərinin planı pozduğu yerdir: əgər o yalnız müəyyən UID-lərdən və ya cgroups-dan trafik tutursa, yönləndirmə qaydalarınız paketi tunelin içində heç vaxt görməyəcək və düzəliş iptables-da deyil, müştərinin marşrutlaşdırma siyasətində olmalıdır. Əl ilə əlavə edilən qaydalar yenidən başlatmada yox olur, ona görə onları systemd vahidinə və ya netfilter-persistent cədvəlinə qoyun və yenidən başlatmadan sonra yenidən sınaqdan keçirin, çünki gec qalxan tunel onları silə bilər.
Məqsəd izolyasiyadırsa, tuneli konteynerin içərisinə qoyun
Əgər bir konteyner müəyyən bir qovşaqdan çıxmalıdırsa, müştərini həmin konteynerdə işə salın. Ona lazımdır --cap-add NET_ADMIN və --device /dev/net/tun, və sonra o, öz tun0-una, marşrutlarına və firewall-una sahib olur. Əgər digər konteynerlər onun içindən keçirsə, onun içində yönləndirmə və MASQUERADE qaydası da lazımdır və o həmyaşıdların ona yönələn açıq marşrutu və ya proksisi olmalıdır; Docker-in defolt körpüsü bu marşrutu sizin üçün əlavə etmir.
Host şəbəkəsi, docker run --network host, ucuz versiyadır: konteyner hostun adlar məkanına qoşulur və tunel marşrutlarını birbaşa görür. O həmçinin şəbəkə izolyasiyasını atır, port toqquşmalarını dəvət edir və praktikada Linux seçimidir. Dərc edilmiş port əvəzedici deyil. -p 8080:80 bir xidməti hostdan əlçatan edir; daxili 10.x ünvanlarını konteynerin içindən əlçatan etmir və ikisini qarışdırmaq marşrut probleminin açıq verilənlər bazası portuna çevrilmə üsuludur.
Ad uğursuzluğunu üst-üstə düşən alt şəbəkədən ayırın
Docker-in defolt körpüsü 172.17.0.0/16-dır və bir çox korporativ VPN hovuzu 172.16.0.0/12-nin içində yerləşir. Tunel həmin diapazona sahib olduqdan sonra konteyner üçün nəzərdə tutulan trafik onun yerinə tunelə yönləndirilə bilər. Adlar uğursuz olur, xəta DNS kimi görünür və problem ünvanlardadır. Həllediciyə deyil, təyinat yerinə baxın: ip route get 172.17.0.5 hostda, sonra körpü prefiksini VPN hovuzu ilə və docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.
Təmir diapaznlardan birini köçürməkdir: ya daemon.json içində Docker üçün fərqli defolt ünvan hovuzu, ya da konsentratorda fərqli hovuz. Başqa bir ad serveri əlavə etmək burada heç nə etmir və ssh -b: müştərini interfeysə bağlamaq mənbə ünvanını dəyişir, tunelə yönələn təyinat marşrutunu deyil. Sürətli iş bölgüsü: hostda həll olunan, lakin konteynerdə olmayan ad həlledici problemidir, halbuki konteynerdə asılan, lakin hostda işləyən birbaşa IP bağlantısı marşrut və ya yönləndirmə zənciri problemidir.
WSL və Docker Desktop Linux qaydalarına əməl etmir
Defolt NAT rejimində WSL öz virtual adapterinin arxasında oturur və Windows VPN-inin daxili marşrutlarını və ya DNS şəkilçilərini almır, buna görə brauzer işləyir və ping distribusiyanın içində işləmir. Son Windows 11 buraxılışlarında mövcud olan güzgülənmiş şəbəkə bunun əvəzinə host interfeyslərini paylaşır, amma o, .wslconfig içində aktivləşdirilməli və distribusiya wsl --shutdown ilə yenidən başladılmalıdır. Aktiv rejimi wslinfo --networking-mode ilə təsdiqləyin, çünki NAT cavabı güzgülənmiş rejim üçün səhvdir və əksi də.
Docker Desktop başqa bir qat əlavə edir. Windows-da Linux konteynerləri tarixən vpnkit adlanan NAT tətbiqinin arxasında oturur və onların yolu yerli Linux hostundan fərqlənir. Windows konteynerləri Hyper-V virtual kommutatoru vasitəsilə qoşulur və korporativ müştəri həmin kommutatordan gələn trafiki bloklaya bilər, ona görə eyni maşındakı Linux konteynerləri şəbəkəyə çata bilər, halbuki Windows konteynerlərinin heç biri yoxdur. Fiziki adapterə bağlanmış xarici kommutator adətən işlədilən həlldir və o, konteynerin şəbəkə kimliyini siyasətin icazə verməyə biləcəyi şəkildə dəyişir.
Başqa bir qayda yazmazdan əvvəl dörd qatı sıra ilə gəzin və onlardan birinin səhv olduğu yerdə dayanın:
- Konteynerin içində:
ip routeşəxsi prefiksə çatırmı və/etc/resolv.confonu həll edən yuxarı axını göstərirmi? - Hostda: yönləndirmə yanırmı, NAT tunel interfeysinə bağlanıbmı və yönləndirmə zənciri körpüdən tunelə keçidi qəbul edirmi?
- Həmyaşıdda: geri yol bilirmi, yoxsa konteyner alt şəbəkəsini gizlətmək üçün NAT-a güvənirsiniz?
- Platformada: WSL NAT, yoxsa güzgülənmiş rejimdədir və konteyner Linux, yoxsa Windows-dur?
Hər testi təzə konteynerdə və ya qabıqda yenidən işlədin. Keşlənmiş cavabı və ya qurulmuş bağlantısı olan uzunömürlü proses konfiqurasiya düzgün olduqdan sonra da uğursuz olmağa davam edəcək və bu uğursuzluq işləməyən bir təmirə tam bənzəyir.