Konteynerin paketi heç vaxt tun0-a çatmır və konteynerdəki əlavə imkanlar bunu dəyişməyəcək. Qonaqla tunel arasında iki marşrut axtarışı dayanır: biri qonağın şəbəkə ad sahəsinin içində, biri çərçivə körpüyə düşdükdən sonra hostda, ikincisi isə fərqli uyğunlaşdırma qaydaları olan başqa cədvələ müraciət edir. Mənim istinad sxemim Linux hostudur: üzərində OpenVPN müştərisi olan sistem, müştəri 10.8.0.10 ünvanını tun0 üzərində saxlayır, Docker körpüsü 172.18.0.0/16, və yalnız tunel tərəfinin çata bildiyi şəxsi ünvan var. Məqsəd dar qalır: bu qonaq alt şəbəkəsi tuneldən çıxır, host isə adi uplinkini saxlayır.

VPN müştərisini konteynerin içində işlətmək başqa bir dizayndır, qısa yol deyil. Onda konteyner öz tunelinə və etimad məlumatlarına sahib olur, iş isə iptables-da qalmaq əvəzinə Dockerfile-a keçir.

Yönləndirmə marşrutu təyinatla seçir, sonra NAT mənbəni yenidən yazır

Şəbəkə üçün net.ipv4.ip_forward=1 təyin edildikdə, yönləndirilən paket yalnız təyinatla, əsas cədvəldə marşrutlaşdırılır. Mənbə bu qərarda iştirak etmir. Marşrut seçildikdən sonra kernel POSTROUTING, və Docker-in öz qaydası elə buradadır: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE. Körpünü başqa interfeysə tərk edən hər şey tərcümə olunur və aldığı ünvan marşrutun onu göndərdiyi interfeysdən asılıdır.

Bu qayda məndən soruşulan simptomların çoxunu izah edir. Əsas cədvəldə şəxsi təyinat üçün marşrut yoxdursa, paket hostun fiziki ünvanı ilə uplinkdən çıxır. Provayderiniz təyinatı atır, ya da uzaq sayt heç gözləmədiyi RFC 1918 mənbəyini atır, konteyner isə tunel işlək və sağlam qalarkən vaxt aşımına düşür. Üzərində tun0 heç nə göstərmir və əlamət budur. Marşrut tun0-a yönəlibsə, MASQUERADE mənbəni 10.8.0.10 ünvanına yenidən yazır və eyni konteyner heç nəyə toxunmadan işləyir.

Qonaq mənbəyini göstərən axtarışı istəyin. Olmadan from və iif olmadan host öz soketi üçün cavab verir və yönləndirilən paketin heç vaxt tutmayacağı yolu bildirir:

ip route get 192.168.11.222 from 172.18.0.5 iif br-appnet

Bu cavab uplinkdən bəhs edirsə, tunel işin içində deyil və tunel tərəfində heç bir parametr kömək etməyəcək.

Qonağı tunelin öz ünvanına köçürün

Ən kiçik işlək dəyişiklik çıxışda açıq mənbə yenidən yazmasıdır. Onu əlavə etmək əvəzinə daxil edin: Docker artıq POSTROUTING başındadır, ona görə -A ilə əlavə edilən qayda Docker-inkindən sonra qiymətləndirilir və heç vaxt işə düşmür.

iptables -t nat -I POSTROUTING 1 -s 172.18.0.0/16 -o tun0 -j SNAT --to-source 10.8.0.10

Bunun davam etməsini iki şərt həll edir. Ünvan müştərinin həqiqətən saxladığı ünvan olmalıdır, ona görə onu hər müştəri üçün ifconfig-push 10.8.0.10 255.255.255.0 ehtiva edən qeydlə bərkidin; heç vaxt təyin edilməmiş ünvanı göstərən qayda səssiz itkilər verir, xəta yox. Və uzaq tərəf bu mənbəni qəbul edib cavabları geri yönləndirməlidir, buna görə oradakı icazə siyahısı qonaq alt şəbəkəsini deyil, tunel ünvanını göstərir. Müştəri ünvanı dinamik olduqda, -j MASQUERADE ilə -o tun0 interfeysin saxladığını izləyir, sabit dəyərə qarşı yaza bilmədiyiniz uzaq siyasət hesabına.

Filtrasiya digər yarıdır. Docker FORWARD siyasətini drop edir və hər daemon yenidən başlamasında sahib olduğu zəncirləri boşaldır, ona görə yerli siyasəti DOCKER-USER içinə qoyun, o, qalır:

iptables -I DOCKER-USER -i br-appnet -o tun0 -j ACCEPT
iptables -I DOCKER-USER -i tun0 -o br-appnet -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Qaytarma qaydası vacibdir: tun0-a gələn cavab körpü ilə açılmış bağlantı üçün yalnız giden istiqamət qəbul edildiyi üçün qəbul edilmir.

Hostu mənbə qaydası ilə birbaşa saxlayın

Bütün körpü tuneldən istifadə etməli, hostda başqa heç nə etməməlidirsə, NAT-ı keçin və o mənbəyə öz cədvəlini verin. Qonaq ünvanları beləcə başdan-başa görünən qalır.

echo "200 vpnbox" >> /etc/iproute2/rt_tables
ip rule add from 172.18.0.0/16 lookup vpnbox pref 1000
ip route add default dev tun0 table vpnbox

Qaydalara əsas cədvəldən əvvəl baxılır və from mənbəyə uyğun gəlir. Tunelin öz xarici paketləri hostun fiziki mənbəyini daşıyır, ona görə onlar heç vaxt from 172.18.0.0/16-a uyğun gəlmir və tunel özünü özünə geri yönləndirə bilmir. Bu özünü xaric etmə sxemi sabit edən şeydir.

Cavab yolu indi kömək istəyir. Uzaq tərəf tərcümə olunmamış 172.18.0.x ünvanını görür və onun harada olduğunu bilməyə əsası yoxdur. Serverdə hər müştəri üçün fayl iroute 172.18.0.0 255.255.0.0 tələb edir ki, serverin daxili cədvəli bu prefiksi bu müştəriyə versin, və göndərilən route 172.18.0.0 255.255.0.0 lazımdır ki, digər müştərilər onun mövcud olduğunu bilsin.

Ona güvənməzdən əvvəl iki yoxlama. İşə salın ip route show default: redirect-gateway def1 ilə cədvəl 0.0.0.0/1 və 128.0.0.0/1 marşrutları tun0-dan keçir, və host ümumiyyətlə birbaşa deyil, çünki bu yarım-defoltlar default-i əvəz etmədən qalib gəlir. Qaydalar ip rule add ilə əlavə edilir və yenidən başlamada yox olur, ona görə onları up skriptinə yazın.

Paket ölçüsü ikinci rastlaşdığınız nasazlıqdır

1500 baytlıq körpü interfeysi xarici UDP və IP başlıqları əlavə olunandan sonra tunelə daşıya bildiyindən çoxunu verir. Kiçik mübadilələr keçir, yəni DNS həll olunur və TLS əl sıxma tamamlanır, sonra daha böyük yükləmə heç bir yerdə xəta olmadan donur. Göndərən eyni seqment ölçüsünü təkrarlayır, çünki ona kiçilməyi söyləyəcək ICMP parçalanma mesajı heç vaxt gəlmir.

Bunu interfeysdə, MSS-də və ya hər ikisində düzəldin. Sıxma qonaqdan heç bir əməkdaşlıq tələb etmir:

ip link set dev tun0 mtu 1400
iptables -t mangle -A FORWARD -o tun0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Sıxma yalnız TCP-ni yenidən yazır. UDP, QUIC daxil olmaqla, əvəzinə qonaq interfeysinin aşağı salınmasını tələb edir, --opt com.docker.network.driver.mtu=1400 ilə şəbəkə yaradılarkən və ya uyğun compose açarı verilir.

DNS və təkrarlanmağa dəyər yoxlamalar

Ad həlli eyni yolu izləyir. Docker-in daxili həlledicisi 127.0.0.11 ünvanında hostun konfiqurasiya edilmiş serverlərinə yönləndirir, ona görə konteyner hostun istifadə etdiyini miras alır. Şəxsi zona yalnız tuneldən əlçatan həlledici tərəfindən cavablandırıldıqda, qonağı o ünvana yönəldin və getent hosts ilə konteynerin içində, hostda deyil, sınaqdan keçirin.

  • Uğursuz sorğunu qonağın içində işə salın; host tərəfində sınaq fərqli mənbə ünvanı işlədir və problemi gizlədir.
  • Əlavə etdiyiniz NAT və filtr qaydalarındakı sayğacları oxuyun. Sıfır uyğunluğu olan qayda marşrut səhvidir, siyasət səhvi deyil.
  • SNAT qaydanızdakı tunel ünvanının müştərinin həqiqətən saxladığı ünvan olduğunu təsdiqləyin.
  • Serveri dayanma üçün günahlandırmazdan əvvəl qonağın MTU-nu aşağı salın və ya MSS-ni sıxın.

Siyahını aşağı doğru işləyin və ilk nasazlıqda dayanın. Düzəldilməli qat həmin qatdır; daha aşağıda əlavə olunan hər şey yalnız qırılan sərhədi gizlədir.

Əlaqəli məqalələr