OpenVPN का फुल टनल आपका SSH सत्र काट देता है: जवाब का रास्ता ठीक करें
डिफ़ॉल्ट रूट SSH जवाबों को टनल में भेजता है। पीयर को पिन करें, redirect-gateway फ़िल्टर करें, या मशीन खोने से पहले स्रोत के अनुसार रूट करें।
जिस मशीन तक आप SSH से पहुँचते हैं, उस पर पूरी टनल वाला OpenVPN क्लाइंट चालू करने से सत्र एक सेकंड में कट सकता है, और मशीन कुछ भी ग़लत नहीं कर रही होती। टनल यह नहीं बदलता कि पैकेट सर्वर तक कैसे पहुँचते हैं; यह बदलता है कि जवाब कैसे बाहर जाते हैं। जैसे ही डिफ़ॉल्ट रूट tun0 की ओर इशारा करता है, आपके SSH क्लाइंट को जवाब प्रदाता के नेटवर्क में चला जाता है, जिसके पास आपके पते तक वापस जाने का कोई रूट नहीं है। कनेक्शन लटक जाता है, अगली कोशिश समय-सीमा पार करती है, और डेमॉन पूरे समय पोर्ट 22 पर सुनता रहता है।
VPN लॉग पढ़ने से पहले रूटिंग तालिका पढ़ें। लॉग कहेगा कि टनल ऊपर आई, और वह सही है। सवाल यह है कि हर जवाब किस इंटरफ़ेस को सौंपा जाता है, और यह उस तालिका में हर पैकेट के लिए खोज है जिसे टनल ने अभी-अभी फिर से लिखा है।
जवाब ग़लत दरवाज़े से क्यों निकलता है
आने वाले पैकेट अब भी भौतिक इंटरफ़ेस पर आते हैं, क्योंकि VPN क्लाइंट यह नहीं बदल सकता कि इंटरनेट आपके सर्वर के सार्वजनिक पते तक कैसे पहुँचता है। जवाब एक अलग फ़ैसला हैं: हर पैकेट के लिए कर्नेल गंतव्य खोजता है, और --redirect-gateway के बाद डिफ़ॉल्ट प्रविष्टि टनल कहती है। प्रदाता का एग्ज़िट ऐसा गंतव्य देखता है जिसकी वह सेवा नहीं करता और पैकेट गिरा देता है।
OpenVPN की अपनी सुरक्षा ठीक एक गंतव्य को कवर करती है। 2.6 की मार्गदर्शिका --redirect-gateway को एक क्रम के रूप में बताती है: यह टनल से पहले इस्तेमाल हुए गेटवे के ज़रिए VPN पीयर के लिए होस्ट रूट जोड़ता है, ताकि एन्क्रिप्टेड ट्रैफ़िक अपने भीतर वापस न लूप कर सके, और फिर डिफ़ॉल्ट रूट बदल देता है। वह होस्ट रूट सिर्फ़ पीयर के लिए है। आपका SSH क्लाइंट बस एक और इंटरनेट पता है और उसे कोई अपवाद नहीं मिलता।
एक प्रीफ़िक्स गलती को जल्दी बाहर करना अच्छा है। लंबाई के बिना ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 सिर्फ़ एक पते 0.0.0.0 से मेल खाता है, इंटरनेट से नहीं; यह 0.0.0.0/0 होना चाहिए। और अगर डिफ़ॉल्ट लेने से टनल का अपना परिवहन टूटता है, तो भौतिक इंटरफ़ेस के ज़रिए एंडपॉइंट को होस्ट रूट के रूप में जोड़ें, प्रदाता के असली पते का उपयोग करते हुए।
तुरंत ठीक करने के लिए अपने SSH क्लाइंट का पता पिन करें
सबसे तेज़ मरम्मत आपके क्लाइंट पते के लिए उस गेटवे के ज़रिए होस्ट रूट है जो सर्वर ने टनल से पहले इस्तेमाल किया था। अपनी तरफ़ से, वह पता खोजें जो सर्वर देखेगा, फिर पुराना गेटवे जानने के लिए सर्वर की तालिका पढ़ें:
curl -s https://ifconfig.co
ip route
सर्वर पर, क्लाइंट शुरू होने से पहले अपवाद जोड़ें। यहाँ पते प्लेसहोल्डर हैं; आकार मायने रखता है:
sudo ip route add 80.128.240.55 via 192.168.178.1
यह वही मरम्मत है जो रिपोर्ट किए गए मामले में इस्तेमाल हुई, और यह तुरंत काम करती है। यह दो अनुमानित तरीक़ों से नाज़ुक भी है: रीबूट पर रूट गायब हो जाता है, और जिस पल आपका ISP आपको दूसरा पता देता है वह ग़लत हो जाता है। इसे आपातकालीन उपाय मानें और जान-बूझकर इसे टिकाऊ बनाएँ, किसी नेटवर्क यूनिट या डिस्पैचर हुक के ज़रिए, या स्वीकार करें कि यह अस्थायी है और रिकवरी का रास्ता लिख लें।
क्लाइंट को डिफ़ॉल्ट लेने से रोकें
ज़्यादा साफ़ विकल्प यह है कि टनल को डिफ़ॉल्ट रूट बिल्कुल बदलने न दिया जाए। route-nopull, --client या --pull के साथ इस्तेमाल होने पर, रूट के अलावा भेजे गए विकल्प, block-outside-dns और DNS सर्वर जैसे DHCP-शैली के विकल्प स्वीकार करता है, इसलिए आप सिर्फ़ ज़रूरी प्रीफ़िक्स जोड़ते हैं। ज़्यादा संकरा औज़ार पुल फ़िल्टर है, जो एक समस्याग्रस्त निर्देश हटा देता है और बाकी रखता है:
route-nopull
pull-filter ignore "redirect-gateway"
एक या दूसरा इस्तेमाल करें, दोनों नहीं, और साफ़ रहें कि क्या बदलता है। टनल के ज़रिए डिफ़ॉल्ट रूट के बिना सर्वर अब प्रदाता के ज़रिए इंटरनेट नहीं ब्राउज़ करता; वह सिर्फ़ उसी तक पहुँचता है जिसे आपने स्पष्ट रूप से रूट किया। अगर पूरी टनल ही सेटअप का पूरा मक़सद थी, तो यह ग़लत स्विच है और ऊपर का होस्ट रूट सही है।
वापसी का रास्ता स्रोत या कनेक्शन के अनुसार बाँटें
जब आने वाला पता स्थिर हो, तो स्रोत नियम टनल के अपने रूट को छुए बिना जवाबों को स्थानीय रखता है। भौतिक इंटरफ़ेस के पते को LAN प्रीफ़िक्स और भौतिक डिफ़ॉल्ट वाली अपनी तालिका दें, फिर उससे आने वाले ट्रैफ़िक के लिए वही तालिका चुनें:
ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1
यह काम करता है क्योंकि आने वाले SSH कनेक्शन के जवाब उसी पते से जाते हैं जिससे क्लाइंट जुड़ा था। जिस रिपोर्ट किए गए मामले में हर आने वाली सेवा को चलते रहना था, उसने ठीक यही आकार इस्तेमाल किया। जब आने वाला पता तैरता हो या रास्ता गतिशील हो, तो इसके बजाय कनेक्शन को चिह्नित करें: भौतिक इंटरफ़ेस से आने वाले पहले पैकेट पर conntrack चिह्न लगाएँ, OUTPUT में जवाब पैकेट पर उसकी नकल करें, और चिह्नित पैकेट को उस तालिका से रूट करें जो भौतिक गेटवे की ओर इशारा करती है।
iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412
परीक्षण के दौरान कनेक्शन चिह्न, फ़ायरवॉल चिह्न और तालिका संख्या अलग रखें। दो भूमिकाओं के लिए एक ही संख्या दोबारा इस्तेमाल करने से ऐसा नियम बनता है जो सही दिखता है और ग़लत पैकेट से मेल खाता है। तालिका की डिफ़ॉल्ट प्रविष्टि को सामान्य ईथरनेट लिंक पर LAN गेटवे के साथ via की भी ज़रूरत होती है; नंगी dev eth0 तभी काम करती है जब इंटरफ़ेस पॉइंट-टू-पॉइंट हो या अगला हॉप किसी और तरीक़े से हल हो। रिपोर्ट किया गया Jessie होस्ट संयोग से ऐसे लिंक पर था जहाँ नंगा रूप काम करता था, जो नकल करने लायक कोई डिस्ट्रीब्यूशन नियम नहीं है।
बाहर ताला लगाए बिना जाँचें
डिस्कनेक्ट करके परीक्षण न करें। पहला सत्र खुला रखें, टनल ऊपर लाएँ, और कर्नेल से पूछें कि आपका अपना पता कौन-सा रास्ता लेगा:
ip route get 80.128.240.55
जवाब में भौतिक इंटरफ़ेस और पुराना गेटवे होना चाहिए, टनल नहीं। फिर दूसरा SSH कनेक्शन खोलें; यही असली परीक्षा है, क्योंकि पुराना सत्र ऐसी स्थिति पर टिक सकता है जिसे नया कनेक्शन दोबारा नहीं बना सकता। अगर दूसरा लटक जाए जबकि पहला अब भी जवाब दे रहा हो, तो नियम कभी उस ट्रैफ़िक से मेल नहीं खाया जो मायने रखता है, और चिह्न या स्रोत पता ही देखने की जगह हैं।
पूरे अभ्यास के दौरान आउट-ऑफ़-बैंड कंसोल उपलब्ध रखें। जिस सर्वर का एकमात्र पहुँच मार्ग वही टनल है जिसे आपने अभी तोड़ा है, उसे उसी टनल से ठीक नहीं किया जा सकता, और वापसी आसान होती है जब आप जोड़ी गई तालिका संख्याएँ और प्रीफ़िक्स लिख चुके हों।