केवल Docker कन्टेनरको ट्राफिक OpenVPN बाट कसरी रुट गर्ने
होस्टलाई यसको सामान्य अपलिङ्कमा राख्नुहोस् र एउटा कन्टेनर सबनेट सुरुङमा राख्नुहोस्: NAT क्रम, स्रोत नियम, OpenVPN iroute र MSS जाँच।
कन्टेनरको प्याकेट कहिल्यै tun0 सम्म पुग्दैन, र कन्टेनरमा थप क्षमताहरूले यसलाई बदल्दैन। अतिथि र सुरुङबीच दुई रुट खोजहरू छन्: एउटा अतिथिको नेटवर्क नामस्थानभित्र, एउटा फ्रेम पुलमा अवतरण भएपछि होस्टमा, र दोस्रो फरक मिलान नियमहरू भएको फरक तालिकालाई सोध्छ। मेरो सन्दर्भ लेआउट एउटा Linux होस्ट हो जसमा OpenVPN क्लाइन्ट चल्छ, जसले 10.8.0.10 लाई tun0 मा राख्छ, 172.18.0.0/16 मा Docker पुल, र सुरुङको पट्टिबाट मात्र पुग्न सकिने निजी ठेगाना। लक्ष्य साँघुरै रहन्छ: त्यो अतिथि सबनेट सुरुङबाट बाहिर जान्छ, होस्टले आफ्नो सामान्य अपलिङ्क राख्छ।
VPN क्लाइन्ट कन्टेनरभित्र चलाउनु अर्को डिजाइन हो, सजिलो बाटो होइन। त्यसपछि कन्टेनरले आफ्नै सुरुङ र प्रमाणहरू राख्छ, र काम iptables मा नबसी Dockerfile मा जान्छ।
फर्वार्डिङले गन्तव्यअनुसार मार्ग छान्छ, त्यसपछि NAT ले स्रोत पुनःलेखन गर्छ
जब net.ipv4.ip_forward=1 सेट हुन्छ, फर्वार्ड गरिएको प्याकेट मुख्य तालिकामा केवल गन्तव्यअनुसार रुट हुन्छ। त्यो निर्णयमा स्रोतको कुनै भूमिका हुँदैन। मार्ग छानिएपछि मात्र कर्नेलले POSTROUTING चलाउँछ, र त्यहीँ Docker को आफ्नै नियम बस्छ: -s 172.18.0.0/16 ! -o br-appnet -j MASQUERADE। पुल छोडेर अर्को इन्टरफेसमा जाने सबै अनुवाद हुन्छ, र त्यो कुन ठेगाना बन्छ भन्ने मार्गले त्यसलाई कुन इन्टरफेसमा पठायो त्यसमा निर्भर गर्छ।
यो नियमले मलाई सोधिने अधिकांश लक्षणहरू व्याख्या गर्छ। मुख्य तालिकामा निजी गन्तव्यको मार्ग नभए प्याकेट होस्टको भौतिक ठेगानासहित अपलिङ्कबाट बाहिर जान्छ। तपाईंको प्रदायकले गन्तव्य फाल्छ, वा टाढाको साइटले कहिल्यै नपर्खेको RFC 1918 स्रोत फाल्छ, र सुरुङ माथि र स्वस्थ रहँदा कन्टेनरको समय सकिन्छ। tun0 मा क्याप्चरले केही देखाउँदैन, र यही संकेत हो। मार्ग साँच्चै tun0 तर्फ देखाउँछ भने, MASQUERADE ले स्रोतलाई 10.8.0.10 मा पुनःलेखन गर्छ, र त्यही कन्टेनर तपाईंले केही नछोई चल्छ।
अतिथिको स्रोत नाम दिने खोज माग्नुहोस्। from र iif बिना होस्टले आफ्नै सकेटका लागि जवाफ दिन्छ र फर्वार्ड गरिएको प्याकेटले कहिल्यै नलिने बाटो रिपोर्ट गर्छ:
ip route get 192.168.11.222 from 172.18.0.5 iif br-appnetत्यो जवाफले अपलिङ्कको नाम लिन्छ भने सुरुङ चित्रमा छैन र सुरुङको पट्टिको कुनै सेटिङले सहयोग गर्दैन।
अतिथिलाई सुरुङको आफ्नै ठेगानामा ल्याउनुहोस्
सबैभन्दा सानो काम गर्ने परिवर्तन बाहिर जाँदा स्पष्ट स्रोत पुनःलेखन हो। यसलाई थप्नुको सट्टा घुसाउनुहोस्: Docker पहिले नै POSTROUTING को टाउकोमा बसेको छ, त्यसैले -A ले थपिएको नियम Docker को नियमपछि मूल्याङ्कन हुन्छ र कहिल्यै चल्दैन।
iptables -t nat -I POSTROUTING 1 -s 172.18.0.0/16 -o tun0 -j SNAT --to-source 10.8.0.10यो टिक्छ कि टिक्दैन दुई सर्तले निर्धारण गर्छ। ठेगाना क्लाइन्टसँग साँच्चै भएको हुनुपर्छ, त्यसैले प्रत्येक क्लाइन्टका लागि ifconfig-push 10.8.0.10 255.255.255.0 भएको प्रविष्टिले यसलाई पिन गर्नुहोस्; कहिल्यै नतोकिएको ठेगानाको नाम लिने नियमले त्रुटि होइन, शान्त ड्रप उत्पन्न गर्छ। र टाढाको पक्षले त्यो स्रोत स्वीकार गरी जवाफहरू फर्काउनुपर्छ, त्यसैले त्यहाँको अनुमति सूचीले अतिथि सबनेट होइन, सुरुङको ठेगाना नाम दिन्छ। क्लाइन्टको ठेगाना गतिशील हुँदा, -j MASQUERADE सँग -o tun0 इन्टरफेसमा भएको कुरा पछ्याउँछ, तर स्थिर मानविरुद्ध लेख्न नसकिने टाढाको नीतिको मूल्यमा।
फिल्टरिङ अर्को आधा हो। Docker ले FORWARD नीतिलाई drop मा राख्छ र प्रत्येक डेमन रिस्टार्टमा आफ्ना चेनहरू खाली गर्छ, त्यसैले स्थानीय नीति DOCKER-USER मा राख्नुहोस्, जो टिक्छ:
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फिर्तीको नियम महत्त्वपूर्ण छ: tun0 मा आउने जवाफ पुलबाट खोलिएको जडानका लागि बाहिरको दिशा स्वीकारिएको भरमा स्वीकारिँदैन।
स्रोत नियमले होस्टलाई सिधै राख्नुहोस्
जब पूरै पुलले सुरुङ प्रयोग गर्नुपर्छ तर होस्टमा अरू केही पनि होइन, NAT छोड्नुहोस् र त्यो स्रोतलाई आफ्नै तालिका दिनुहोस्। अतिथि ठेगानाहरू त्यसपछि सुरुदेखि अन्तसम्म देखिन्छन्।
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नियमहरू मुख्य तालिकाअघि हेरिन्छन्, र from स्रोतसँग मिल्छ। सुरुङका आफ्नै बाहिरी प्याकेटहरूले होस्टको भौतिक स्रोत बोक्छन्, त्यसैले ती कहिल्यै from 172.18.0.0/16 सँग मिल्दैनन् र सुरुङले आफैलाई फर्केर रुट गर्न सक्दैन। यही आत्म-बहिष्कारले लेआउटलाई स्थिर बनाउँछ।
फिर्तीको बाटोलाई अब सहयोग चाहिन्छ। टाढाको पक्षले अनुवाद नगरिएको 172.18.0.x देख्छ र त्यो कहाँ बस्छ भन्ने थाहा पाउने कारण हुँदैन। सर्भरमा प्रत्येक क्लाइन्टको फाइललाई iroute 172.18.0.0 255.255.0.0 चाहिन्छ, ताकि सर्भरको आन्तरिक तालिकाले त्यो प्रिफिक्स यो क्लाइन्टलाई दिन्छ, र धकेलिएको route 172.18.0.0 255.255.0.0 चाहिन्छ, ताकि अरू क्लाइन्टहरूले त्यो छ भन्ने थाहा पाउन्।
विश्वास गर्नुअघि दुई जाँच। चलाउनुहोस् ip route show default : redirect-gateway def1 सँग तालिकामा 0.0.0.0/1 र 128.0.0.0/1 छन् tun0 बाट, र होस्ट बिल्कुलै सिधा छैन, किनकि ती आधा-पूर्वनिर्धारित default प्रतिस्थापन नगरी जित्छन्। ip rule add ले थपिएका नियमहरू पनि रिबुटमा हराउँछन्, त्यसैले तिनलाई up स्क्रिप्टमा राख्नुहोस्।
प्याकेटको आकार दोस्रो असफलता हो जुन तपाईंले भेट्नुहुन्छ
1500 बाइटको पुल इन्टरफेसले बाहिरी UDP र IP हेडर थपिएपछि सुरुङलाई यसको क्षमताभन्दा बढी दिन्छ। साना आदानप्रदान पार हुन्छन्, त्यसैले DNS समाधान हुन्छ र TLS ह्यान्डशेक पूरा हुन्छ, त्यसपछि ठूलो अपलोड कतै पनि त्रुटिबिना अड्किन्छ। पठाउनेले उही सेगमेन्ट आकार दोहोर्याइरहन्छ, किनकि सानो हुन भन्ने ICMP खण्डीकरण-आवश्यकता सन्देश कहिल्यै पुग्दैन।
इन्टरफेसमा, MSS मा, वा दुवैमा यसलाई सुधार्नुहोस्। क्ल्याम्पिङलाई अतिथिको सहयोग चाहिँदैन:
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क्ल्याम्पले केवल TCP पुनःलेखन गर्छ। UDP, QUIC सहित, यसको सट्टा अतिथिको इन्टरफेस तल झार्नुपर्छ, --opt com.docker.network.driver.mtu=1400 ले नेटवर्क बनाउँदा वा मिल्ने compose कुञ्जीसँग।
DNS र दोहोर्याउन लायक जाँचहरू
नाम समाधान उही बाटो पछ्याउँछ। Docker को अन्तर्निहित रिजोल्भर 127.0.0.11 मा होस्टका कन्फिगर गरिएका सर्भरहरूमा फर्वार्ड गर्छ, त्यसैले कन्टेनरले होस्टले प्रयोग गर्ने कुरा पाउँछ। निजी जोनको जवाफ सुरुङबाट मात्र पुग्ने रिजोल्भरले दिन्छ भने, अतिथिलाई त्यो ठेगानातर्फ देखाउनुहोस्, र getent hosts बाट कन्टेनरभित्र जाँच्नुहोस्, होस्टमा होइन।
- असफल हुने अनुरोध अतिथिभित्रै चलाउनुहोस्; होस्ट पट्टिको परीक्षणले फरक स्रोत ठेगाना प्रयोग गरी समस्या लुकाउँछ।
- तपाईंले थपेका NAT र फिल्टर नियमहरूका काउन्टर पढ्नुहोस्। शून्य मिलान भएको नियम रुटिङको गल्ती हो, नीतिको होइन।
- तपाईंको SNAT नियमको सुरुङ ठेगाना क्लाइन्टसँग साँच्चै भएको हो भनी पुष्टि गर्नुहोस्।
- अड्किएकोमा सर्भरलाई दोष दिनुअघि अतिथिको MTU घटाउनुहोस् वा MSS क्ल्याम्प गर्नुहोस्।
सूची तल जानुहोस् र पहिलो असफलतामा रोक्नुहोस्। त्यही तह सुधार्नुपर्ने हो; तल थपिएको जुनसुकै कुराले टुट्दै गरेको सीमा मात्र लुकाउँछ।