اگر بعد از ریاستارت سرور، پورت ۸۰۸۰ که با ufw allow 8080 باز کرده بودید دوباره بسته شده، مشکل از دستور شما نیست؛ از این است که قاعده در زنجیرهٔ runtime نوشته شده و در فایل راهانداز ذخیره نشده. این متن برای وقتی است که میدانید کدام قاعده را میخواهید، فقط معادل دقیقش در ابزار دیگر یا شکل دائمیاش را لازم دارید.
سه ابزار، سه مدل ذهنی متفاوت
iptables روی زنجیرههای خطی کار میکند و هر بسته از بالا به پایین ارزیابی میشود تا اولین قاعدهٔ منطبق. nftables همان مدل را با جدولها و setها و mapها جلو برده و از کرنل 3.13 به بعد در دسترس است؛ روی اکثر توزیعهای امروزی، iptables فقط یک لایهٔ سازگاری روی nft است. ufw و firewalld هم چیزی جز تولیدکنندهٔ قاعده برای یکی از این دو نیستند.
نتیجهٔ عملی این حرف: اگر همزمان ufw و یک اسکریپت iptables -A اجرا میکنید، دو نویسنده روی یک زنجیره دارید و ترتیب قواعدتان دیگر قابل پیشبینی نیست. یکی را انتخاب کنید.
معادل دقیق دستورها در iptables و nftables و ufw
جدول زیر همان چیزهایی است که واقعاً سرچ میشوند. ستون nft معادل مدرن است، نه ترجمهٔ تحتاللفظی.
| کار | iptables | nftables | ufw |
|---|---|---|---|
| دیدن قواعد | iptables -L -n -v --line-numbers | nft list ruleset | ufw status verbose |
| باز کردن پورت | iptables -A INPUT -p tcp --dport 443 -j ACCEPT | nft add rule inet filter input tcp dport 443 accept | ufw allow 443/tcp |
| محدودکردن نرخ SSH | iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set | nft add rule inet filter input tcp dport 22 ct state new limit rate 4/minute accept | ufw limit 22/tcp |
| حذف یک قاعده | iptables -D INPUT 3 | nft -a list chain inet filter input سپس nft delete rule inet filter input handle 12 | ufw delete allow 443/tcp |
| ذخیرهٔ دائمی | iptables-save > /etc/iptables/rules.v4 | فایل /etc/nftables.conf و systemctl enable nftables | خودکار در /etc/ufw/ |
یک نکتهٔ ریز که وقت زیاد میبرد: در nftables ترتیب ct state و dport در یک قاعده مهم نیست، اما ترتیب قاعدهها نسبت به هم مهم است. در iptables هم همینطور. اگر قاعدهٔ DROP را قبل از ACCEPT بگذارید، بسته هرگز به خط دوم نمیرسد و در لاگ هم چیزی نمیبینید مگر اینکه صراحتاً -j LOG گذاشته باشید.
ذخیرهٔ دائمی: جایی که بیشترین قاعده گم میشود
روی Debian و Ubuntu بستهٔ iptables-persistent فایلهای /etc/iptables/rules.v4 و rules.v6 را در بوت بار میکند. روی RHEL و مشتقاتش، iptables-services و service iptables save. اگر هیچکدام نصب نیست، قواعد شما فقط تا ریاستارت بعدی زندهاند.
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
systemctl enable --now netfilter-persistent
برای nftables، فایل /etc/nftables.conf را با nft list ruleset > /etc/nftables.conf بازنویسی کنید و سرویس را enable کنید. حواش باشید که این دستور کل فایل را جایگزین میکند؛ اگر کامنت یا include داخلش داشتید، از دست میرود.
اینجا اشتباه میکنند
رایجترین اشتباهی که در تیکتها میبینم این است: کسی ufw enable میزند بدون اینکه ufw allow 22/tcp را قبلش اجرا کرده باشد، و بعد از قطعشدن SSH دنبال خطای شبکه میگردد. نشانهاش این است که پینگ جواب میدهد (چون ICMP در سیاست پیشفرض ufw مجاز است) اما ssh روی پورت ۲۲ تایماوت میشود. اگر دسترسی را از دست دادید، از طریق حالت rescue و بازنصب سرور میتوانید وارد شوید و قواعد را اصلاح کنید.
ترتیب ارزیابی و زنجیرههای سفارشی
در iptables سه زنجیرهٔ داخلی دارید: INPUT، OUTPUT و FORWARD. اگر سرور شما نقش روتر یا میزبان کانتینر دارد، FORWARD را دستکم نگیرید؛ Docker بهطور پیشفرض قواعد خودش را در زنجیرههای DOCKER-USER و DOCKER تزریق میکند و سیاست FORWARD DROP شما میتواند ترافیک کانتینرها را قطع کند. اگر روی VPS داکر اجرا میکنید، پیش از دستزدن به FORWARD، راهاندازی داکر روی VPS را ببینید تا بدانید کدام زنجیرهها را نباید لمس کنید.
برای دیباگ، شمارندهها بهترین دوست شما هستند. iptables -L INPUT -n -v تعداد بستههای هر قاعده را نشان میدهد. اگر قاعدهای صفر بسته گرفته، یعنی هیچ ترافیکی به آن نرسیده و مشکل جای دیگری است. در nftables معادلش nft list ruleset با شمارندههاست، به شرطی که قاعده با counter ساخته شده باشد.
سیاست پیشفرض را قبل از هر چیز تعیین کنید
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
این چهار خط پایهٔ هر فایروال سالمی است. خط ESTABLISHED,RELATED را حذف نکنید؛ بدون آن، پاسخهای DNS و اتصالهای خروجی هم برمیگردند و قطع میشوند. اگر سرور شما سرویس MySQL دارد و از بیرون به آن وصل میشوید، بهجای باز کردن پورت ۳۳۰۶ به کل اینترنت، محدودکردن دسترسی MySQL را در پیش بگیرید.
کدام را انتخاب کنم
اگر سرور تازه راه افتاده و مدیر سیستم حرفهای ندارید، ufw را انتخاب کنید. سینتکسش کوتاه است، ذخیرهسازی خودکار دارد و برای ۹۰٪ سناریوها کافی است. اگر روی زیرساخت ابری کار میکنید و قواعد پویا یا setهای بزرگ IP دارید، nftables انتخاب درست است؛ lookup در set از نوع hash روی هزاران آیپی، مرتبهٔ ثابت دارد در حالی که iptables خطی پیمایش میکند. iptables را فقط وقتی نگه دارید که اسکریپتهای قدیمی یا پنلهای مدیریتی به آن وابستهاند.
هزینهای که باید بپذیرید: nftables روی توزیعهای قدیمیتر از کرنل 3.13 کار نمیکند و بعضی ابزارهای مانیتورینگ هنوز خروجی iptables -L را پارس میکنند. اگر تیم شما به آن خروجی وابسته است، مهاجرت را عقب بیندازید.
قبل از هر تغییر، راه برگشت داشته باشید
هر بار که زنجیرهٔ INPUT را دست میزنید، یک at یا screen با دستور بازگردانی زمانبندی کنید. مثلاً echo "iptables-restore < /root/rules.backup" | at now + 10 minutes. اگر خودتان را بیرون قفل کردید، ده دقیقه بعد برمیگردید. این عادت، بیشتر از هر مستنداتی نجاتتان میدهد.
برای سرورهایی که ترافیک سنگین دارند، فایروال فقط بخشی از کار است؛ اگر بعد از اعمال قواعد لود بالا رفت، تشخیص علت لود بالای سرور قدم بعدی است. و اگر روی سرور اختصاصی یا ابری کار میکنید و میخواهید بدانید کدام لایهٔ شبکه در دست شماست، سرور اختصاصی و سرور ابری را ببینید. برای راهاندازی اولیه هم یک هاست لینوکس با دسترسی root کافی است تا همین قواعد را بدون واسطه تست کنید.
پرسشهای پرتکرار
چرا بعد از ریاستارت سرور قواعد iptables پاک میشوند؟
چون قواعد فقط در حافظهٔ کرنل هستند و در فایل ذخیره نشدهاند. با iptables-save > /etc/iptables/rules.v4 آنها را بنویسید و بستهٔ iptables-persistent یا netfilter-persistent را نصب و enable کنید. بدون این مرحله، هر ریاستارت یا ریلود سرویس شبکه، قواعد را به حالت اول برمیگرداند.
تفاوت ufw و iptables در چیست و کدام سریعتر است؟
ufw یک رابط کاربری روی iptables یا nftables است و خودش موتور فیلتر جداگانهای ندارد؛ پس سرعت پردازش بسته در هر دو یکی است. تفاوت در مدیریت است: ufw ذخیرهسازی و ترتیب را خودش نگه میدارد، iptables کنترل کامل میدهد اما همهچیز را دستی باید بنویسید.
چطور بفهمم یک پورت واقعاً بسته است یا سرویس گوش نمیدهد؟
از بیرون با nc -vz your-server-ip 443 تست کنید. اگر اتصال رد شد ولی ss -tlnp روی سرور نشان میدهد سرویس روی آن پورت listen میکند، مشکل فایروال است. اگر سرویس listen نمیکند، فایروال بیتقصیر است و باید سرویس را بررسی کنید.
آیا باز کردن پورت در فایروال کافی است تا سرویس از بیرون در دسترس باشد؟
نه. سه لایه باید همراستا باشند: فایروال سیستمی، فایروال شبکهٔ ابری (security group) و خود سرویس که روی 0.0.0.0 گوش بدهد نه 127.0.0.1. اگر سرویس به localhost بایند شده باشد، هیچ قاعدهای در هیچ فایروالی آن را از بیرون قابل دسترس نمیکند.