تکنولوژی

IPv6 برای سرور وب: راه‌اندازی دو پشته و تله‌های رایج

اگر بعد از فعال‌سازی IPv6 سایت از بیرون باز نمی‌شود یا فقط بعضی کاربران خطا می‌گیرند، مشکل معمولاً رکورد AAAA یا فایروال جداست. راهنمای عملی رفع آن.

تکنولوژی

سرور شما به IPv6 جواب می‌دهد، از داخل با ping6 هم پینگ می‌شود، اما کاربری که اینترنت IPv6 دارد می‌گوید سایت باز نمی‌شود. یا بدتر: سایت برای اکثر مردم باز است و فقط درصدی از کاربران موبایل صفحهٔ سفید می‌بینند. این تقریباً همیشه یعنی یک جای زنجیرهٔ IPv6 نصفه مانده. زنجیره این است: آدرس روی اینترفیس، روت پیش‌فرض، رکورد AAAA در DNS، گوش‌دادن سرویس، و فایروال. اگر یکی از این پنج حلقه نباشد، نتیجه دقیقاً همین رفتار متناقض است.

اولین کاری که باید بکنید این است که بفهمید مشکل از سمت سرور است یا از مسیر شبکه. روی خود سرور:

ip -6 addr show dev eth0
ip -6 route show default
curl -6 -I https://example.com
ss -6 -tlnp | grep :443

اگر ip -6 addr آدرس نشان می‌دهد ولی ip -6 route show default خالی است، سرور آدرس دارد اما راهی به بیرون ندارد. این حالت در VPSهایی که آدرس IPv6 را دستی اضافه کرده‌اید خیلی رایج است. اگر روت هست ولی ss -6 چیزی نشان نمی‌دهد، یعنی Nginx یا Apache فقط روی IPv4 گوش می‌دهد.

چرا Nginx روی IPv6 گوش نمی‌دهد

پیش‌فرض خیلی از کانفیگ‌های قدیمی این است:

listen 443 ssl;
listen [::]:443 ssl;

خط دوم را باید دستی اضافه کنید. اگر فقط listen 443 ssl; باشد، سوکت روی 0.0.0.0 باز می‌شود و IPv6 کاری با آن ندارد. بعد از اضافه‌کردن، nginx -t و بعد systemctl reload nginx. توجه کنید که اگر ipv6only=on را اشتباه بگذارید روی سوکتی که هم‌زمان IPv4 را می‌گیرد، ممکن است پورت دوباره bind نشود و خطای address already in use بگیرید.

در Apache ماجرا فرق دارد. با Listen 80 به‌تنهایی Apache روی IPv6 گوش نمی‌دهد؛ باید Listen [::]:80 را جدا بنویسید. در نسخه‌های جدیدتر اگر Listen 80 را بگذارید و سیستم net.ipv6.bindv6only=0 داشته باشد، یک سوکت هر دو را می‌گیرد. این تفاوت بین توزیع‌ها باعث می‌شود کانفیگ کپی‌شده از یک سرور روی سرور دیگر رفتار متفاوتی بدهد.

رکورد AAAA را کجا و چطور بگذارید

رکورد AAAA معادل IPv6 رکورد A است و فقط آدرس IPv6 می‌گیرد. اگر آدرس اشتباه یا قدیمی بگذارید، مرورگر تلاش می‌کند به آن وصل شود و بعد از تایم‌اوت به IPv4 برمی‌گردد. این fallback در مرورگرهای مدرن وجود دارد، ولی چند ثانیه تأخیر اضافه می‌کند و در بعضی کلاینت‌ها (مثل کتابخانه‌های قدیمی HTTP) اصلاً وجود ندارد.

example.com.   300   IN   AAAA   2001:db8:1::10
www.example.com. 300 IN   AAAA   2001:db8:1::10

عدد 300 همان TTL است. اگر در حال تست هستید، TTL را پایین بگذارید تا تغییرات سریع propagate شود؛ بعد از پایدارشدن می‌توانید به 3600 برگردانید. یک نکتهٔ عملی: اگر سرور شما IPv6 دارد ولی سرویس روی آن گوش نمی‌دهد، رکورد AAAA را نگذارید. نبودن رکورد AAAA بهتر از وجود رکورد اشتباه است، چون کلاینت سریع سراغ IPv4 می‌رود.

برای بررسی اینکه رکورد درست propagate شده، از ابزارهای شبکه مثل ابزارهای شبکه سرورنت یا dig AAAA example.com @1.1.1.1 استفاده کنید. اگر پاسخ از رزولورهای مختلف متفاوت بود، هنوز کش قدیمی پاک نشده.

فایروالی که فراموش می‌کنید

اینجا اشتباه می‌کنند. کسی ufw allow 443 می‌زند، IPv4 باز می‌شود، تست می‌کند، کار می‌کند، و تمام. بعد سایت برای کاربران IPv6 باز نمی‌شود و ساعت‌ها دنبال مشکل در Nginx می‌گردد. قاعدهٔ ufw این است که قوانین IPv4 و IPv6 جدا هستند و باید با ipv6 مشخص شوند:

ufw allow proto tcp from any to any port 443
ufw allow proto tcp from any to any port 443

در واقع ufw به‌صورت پیش‌فرض اگر IPV6=yes در /etc/default/ufw باشد، هر دو را با هم می‌نویسد. ولی اگر آن خط no باشد، فقط IPv4 نوشته می‌شود و شما هیچ خطایی نمی‌بینید. علامتش این است: ufw status verbose قانون را نشان می‌دهد، ولی ip6tables -L -n خالی است.

در iptables خام هم همین داستان است. زنجیرهٔ INPUT در iptables و ip6tables دو چیز کاملاً جدا هستند. اگر اسکریپت فایروال دارید که فقط iptables را صدا می‌زند، IPv6 شما باز و بی‌محافظ است. این بدترین حالت است: سرویس کار می‌کند، تست هم پاس می‌شود، ولی پورت‌های مدیریتی روی IPv6 برای کل اینترنت باز است.

دو پشته در عمل: هزینه‌ای که کسی حساب نمی‌کند

دو پشته یعنی سرویس هم‌زمان روی IPv4 و IPv6 گوش می‌دهد. مزیتش واضح است. هزینه‌اش این است که سطح حمله دو برابر می‌شود و لاگ‌ها دو نوع آدرس دارند. اگر سیستم fail2ban یا rate-limit دارید، باید مطمئن شوید آدرس‌های IPv6 را هم می‌بیند. یک آدرس IPv6 می‌تواند یک /64 کامل باشد؛ اگر rate-limit را روی یک آدرس ببندید، مهاجم به‌سادگی از آدرس بعدی در همان سابنت ادامه می‌دهد. در Nginx باید limit_req_zone را با دقت روی $binary_remote_addr تنظیم کنید و بدانید که این متغیر برای IPv6 شانزده بایت است، نه چهار.

نکتهٔ دوم: اگر پشت CDN هستید، باید هدر X-Forwarded-For را برای IPv6 هم درست parse کنید. خیلی از کانفیگ‌های آماده فقط بازه‌های IPv4 را در set_real_ip_from دارند و آدرس واقعی کاربر IPv6 در لاگ به‌شکل آدرس CDN ثبت می‌شود.

کدام را انتخاب کنم؟

اگر سایت عمومی دارید و ترافیک از موبایل و شبکه‌های بزرگ می‌آید، دو پشته را فعال کنید. اگر سرویس داخلی است و همهٔ کلاینت‌ها IPv4 دارند، فعال‌کردن IPv6 فقط سطح حمله اضافه می‌کند و سودی ندارد. من در عمل برای سرورهای وب عمومی دو پشته را انتخاب می‌کنم، ولی فقط بعد از اینکه فایروال IPv6 و مانیتورینگ را قبل از رکورد AAAA آماده کرده باشم. ترتیب مهم است: اول فایروال، بعد سرویس، بعد DNS. اگر برعکس بروید، پنجره‌ای دارید که سرویس روی IPv6 باز است و کسی محافظتش نمی‌کند.

برای بارهای کاری سنگین‌تر که می‌خواهید کنترل کامل روی استک شبکه داشته باشید، سرور فیزیکی گزینهٔ منطقی‌تری از یک VPS اشتراکی است، چون می‌توانید خودتان روتینگ و فایروال را بدون محدودیت پلتفرم تنظیم کنید. اگر بار کاری سبک‌تر است و فقط می‌خواهید سریع راه بیفتید، سرور ابری با آدرس IPv6 اختصاصی همین کار را با تنظیمات کمتر انجام می‌دهد. برای پروژه‌هایی که به یک ماشین پایدار با آدرس ایران نیاز دارند، سرور مجازی ایران نقطهٔ شروع متعارفی است.

تست نهایی قبل از اینکه رکورد AAAA را منتشر کنید

  1. روی سرور: ss -6 -tlnp باید پورت 443 را روی [::] نشان بدهد.
  2. از بیرون: curl -6 -I https://example.com باید هدر برگرداند، نه تایم‌اوت.
  3. فایروال: ip6tables -L -n باید قوانین شما را داشته باشد، نه زنجیرهٔ خالی.
  4. DNS: dig AAAA example.com +short باید همان آدرسی باشد که روی اینترفیس دارید.
  5. SSL: گواهی باید برای همان دامنه معتبر باشد؛ اگر از Let's Encrypt استفاده می‌کنید، چالش HTTP-01 روی IPv6 هم باید کار کند.

اگر هر کدام از این پنج مورد رد شد، رکورد AAAA را منتشر نکنید. یک راهنمای تکمیلی دربارهٔ IPv6 و اهمیت آن در زیرساخت‌های مدرن هم داریم که به بحث گذار و سازگاری می‌پردازد. برای جزئیات پیکربندی سرویس‌های خاص، مستندات و پایگاه دانش مرجع دقیق‌تری است.

پرسش‌های پرتکرار

چرا سایت با IPv6 باز نمی‌شود ولی با IPv4 کار می‌کند؟

معمولاً یکی از سه چیز: سرویس روی IPv6 گوش نمی‌دهد، فایروال IPv6 قانون ندارد، یا رکورد AAAA به آدرس اشتباهی اشاره می‌کند. با ss -6 -tlnp و ip6tables -L -n و dig AAAA هر سه را در چند دقیقه می‌شود تفکیک کرد.

آیا حذف رکورد AAAA مشکل را حل می‌کند؟

موقتاً بله. اگر رکورد AAAA را بردارید، کلاینت‌ها سریع سراغ IPv4 می‌روند و سایت باز می‌شود. ولی این راه‌حل است نه درمان؛ اگر هدف فعال‌کردن IPv6 است، باید سرویس و فایروال را درست کنید و بعد رکورد را برگردانید.

آیا ufw به‌صورت پیش‌فرض IPv6 را هم می‌بندد؟

فقط اگر IPV6=yes در /etc/default/ufw باشد. در غیر این صورت قوانین شما فقط روی IPv4 اعمال می‌شوند و ip6tables -L -n خالی می‌ماند، در حالی که ufw status همه‌چیز را نرمال نشان می‌دهد.

چطور بفهمم کاربران واقعاً از IPv6 وصل می‌شوند؟

در لاگ وب‌سرور دنبال آدرس‌هایی با دونقطه بگردید. اگر پشت CDN هستید، باید هدر X-Forwarded-For را در فرمت لاگ اضافه کنید، وگرنه فقط آدرس IPv4 یا IPv6 خود CDN را می‌بینید و آمار واقعی کاربران را از دست می‌دهید.

پشتیبانی سرورنت

تیم فنی و تحریریه‌ی سرورنت — تخصص در زیرساخت، شبکه و میزبانی وب.

سرور مجازی ایران
اشتراک‌گذاری:

دیدگاه‌ها ۰

هنوز دیدگاهی ثبت نشده؛ اولین نفر باشید!

دیدگاه خود را بنویسید

سرویس مرتبط

سرور مجازی ایران

NVMe در قلب تهران — برای سایت‌ها و اپلیکیشن‌هایی که کاربر ایرانی دارند: سریع‌ترین پینگ، ترافیک داخلی نیم‌بها و تحویل آنی.