انتشار پورت کلاینت VPN از پشت CGNAT: چکلیست
یک قاعده NAT مقصد بهتنهایی اتصالهای نیمهباز میدهد. آدرس تونل را ثابت کنید، در هر دو جهت ترجمه کنید و مسیر پاسخ را پیش از آزمایش تأیید کنید.
سرویسی را روی لپتاپی پشت NAT سطح اپراتور بگذارید، آن لپتاپ را از طریق VPN به یک VPS وصل کنید، و هیچکس در بیرون نمیتواند به آن برسد. یک قاعده NAT مقصد روی VPS اضافه میکنید و چیزی بدتر از سکوت میگیرید: اتصالها باز میشوند و سپس متوقف میمانند. پاسخ گم نشده است، بلکه از مسیر پیشفرض خود کلاینت خارج میشود، یعنی سرور هرگز آن را نمیبیند. این پنج بررسی را به ترتیب انجام دهید و در اولین بررسیای که برقرار نمیماند توقف کنید.
تأیید کنید که سرور اصلاً فوروارد میکند
پیش از نوشتن حتی یک ترجمه این جعبه را تیک بزنید. قاعده DNAT برای بستهای که هسته از فوروارد کردن آن سر باز میزند، توسط تحلیلگر قواعد پذیرفته و سپس توسط مسیر فوروارد دور انداخته میشود، که یک وقفه ایجاد میکند که شبیه مشکل فایروال به نظر میرسد.
sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
تنظیم آن در هستهای که در حال اجراست با تنظیم آن در طول یک راهاندازی مجدد یکی نیست. net.ipv4.ip_forward=1 را در فایلی زیر /etc/sysctl.d/ بنویسید، sysctl --system را اجرا کنید، و سپس مقدار را دوباره بخوانید بهجای اینکه به برداشته شدن فایل اعتماد کنید. کانتینری که فضای نام شبکه خود را مدیریت میکند به همان مقدار درون آن فضا نیاز دارد، نه فقط روی میزبان.
اگر بازخوانی هنوز صفر است، همینجا توقف کنید. هیچ چیز در ادامه کار نخواهد کرد.
آدرس تونل را پیش از آنکه هیچ قاعدهای به آن اشاره کند ثابت کنید
استخر آدرسها را به ترتیب اتصال توزیع میکند، پس قاعدهای که برای اجاره امروز نوشته شده ممکن است هفته آینده بیصدا به کلاینت دیگری اشاره کند. آدرس را به هویت گواهی گره بزنید نه به ترتیب ورود.
client-config-dir /etc/openvpn/ccd
ifconfig-push 10.77.0.14 10.77.0.13
آن جفت، انتهای کلاینت و انتهای همتای یک تونل نقطهبهنقطه است، و سرور روی نام مشترک گواهی کلید خورده است. در توپولوژی زیرشبکه مقدار دوم بهجای آن بهعنوان ماسک شبکه خوانده میشود، پس شکلی را بنویسید که با توپولوژی در استفاده میخواند. سپس کلاینت را دوباره وصل کنید و آدرس را روی خود کلاینت بخوانید، چون دید سرور از استخر اثبات آنچه کلاینت پیکربندی کرده نیست.
اگر آدرس پس از اتصال دوباره تغییر کند، توقف کنید. قاعده NAT که هدف متحرک را دنبال میکند بهصورت متناوب شکست میخورد و چیزی به شما نمیآموزد.
در هر دو جهت ترجمه کنید
ترجمه مقصد بسته ورودی را به کلاینت میفرستد. ترجمه مبدأ چیزی است که کلاینت را وادار میکند به سرور پاسخ دهد نه به فرستنده اصلی، و همان قاعدهای است که مردم جا میاندازند.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 29443 -j DNAT --to-destination 10.77.0.14:29443
iptables -t nat -A POSTROUTING -d 10.77.0.14 -p tcp --dport 29443 -j SNAT --to-source 10.77.0.13
بدون قاعده دوم کلاینت از طریق لینک بالاسری ISP خود پاسخ میدهد، پس همتای دور آدرس مبدأیی میبیند که هرگز با آن صحبت نکرده، در حالی که سرور هیچ ورودی ردیابی برای پاسخ ندارد. ناظر بیرونی یک دستدادن نیمهتمام میبیند، و این دقیقاً همان نشانهای است که مردم را به شکار خطای فایروالی میفرستد که وجود ندارد.
هر دو قاعده را با iptables -t nat -S بازخوانی کنید و تأیید کنید که نام رابط همانی است که آدرس عمومی را حمل میکند. روی میزبانی که از پیش با nftables فیلتر میکند، ترجمه را در زنجیره NAT در nftables از خانواده آدرس مطابق بنویسید نه با مخلوط کردن ابزارها.
بگذارید جدول فیلتر عبور کند
جدولهای NAT سرآیندها را بازنویسی میکنند؛ اجازه نمیدهند. با سیاست پیشفرض DROP جریان فورواردشده به پذیرش خودش نیاز دارد، بهعلاوه جهت بازگشت که بیشتر سیاستها از قبل با قاعده established,related پوشش میدهند.
iptables -A FORWARD -i eth0 -o tun0 -p tcp --dport 29443 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
پیش از افزودن هر چیزی سیاست زنجیره FORWARD را بررسی کنید، چون ترتیب یک DROP زودهنگام تعیین میکند که قاعده شما اصلاً دیده میشود یا نه. روی میزبانی که فیلترش در nftables زندگی میکند، قاعده معادل را به قلاب forward جدول inet اضافه کنید و تأیید کنید که زنجیره پایه واقعاً ترافیک فورواردشده را میبیند نه فقط ورودی محلی. اگر شمارنده بستهها روی قاعده جدید صفر بماند در حالی که شمارندههای NAT بالا میروند، بسته پیش از قاعده شما دور انداخته میشود. این نشانه خواندن ترتیب زنجیرههاست، نه افزودن نسخه دوم از همان قاعده.
آن را از شبکه بیرونی اثبات کنید
از شبکهای نامرتبط آزمایش کنید. کاوش از ماشین دیگری در همان LAN میتواند از پشتیبانی NAT سنجاقی عبور کند و هرگز مسیری را که یک کلاینت دور استفاده میکند تمرین نکند، پس نتیجه سبز در آنجا چیز اشتباهی را اثبات میکند.
tcpdump -ni any port 29443
conntrack -L | grep 29443
ضبط را همزمان روی سرور و روی کلاینت اجرا کنید. ضبط سرور نشان میدهد آیا بسته ترجمهشده به سمت تونل خارج میشود؛ ضبط کلاینت نشان میدهد آیا درخواست میرسد و پاسخ به کجا نشانهگذاری شده است. یک ورودی ترجمه در conntrack -L اثبات میکند که قاعده تطبیق داده، و نبودش اثبات میکند که بسته هرگز به زنجیره NAT نرسیده است.
اسکنرهای پورت شواهد ضعیفی هستند. تا زمانی که برنامه متصل نشده و گوش نمیدهد پورت را بسته گزارش میکنند، پس از یک اتصال واقعی به سرویس واقعی استفاده کنید. وقتی سرانجام کار کرد، مواجهه را فقط به همان یک پورت محدود نگه دارید: فوروارد کردن SSH یا پنل مدیریت چون قاعده اول ناخوشایند به نظر میرسید تصمیمی بسیار بزرگتر از انتشار یک سرویس است.