SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor

تفاوت iptables و nftables در اوبونتو و نحوه بررسی آن

در اوبونتو دستور iptables قوانین را برای nftables می‌نویسد. با اجرای دستور iptables -V بررسی کنید که آیا از back end نسخه nft استفاده می‌شود یا legacy.

مقایسه iptables و nftables در اوبونتو: سرور شما از کدام استفاده می‌کند؟

در اوبونتو 20.04 و نسخه‌های بعد از آن، دستور iptables یک رابط کاربری است که قوانین را برای nftables می‌نویسد. در واقع یک فیلتر بسته در هسته سیستم‌عامل به نام nftables اجرا می‌شود و دو دستور در فضای کاربری (user space) آن را برنامه‌ریزی می‌کنند. یک خط دستور iptables -A INPUT همچنان دقیقاً مانند گذشته کار می‌کند و قانونی که ایجاد می‌کند، یک قانون nftables است که nft می‌تواند آن را نمایش دهد.

پیش از آنکه به این موضوع اطمینان کنید، آن را روی سرور خود بررسی کنید.

iptables -V
sudo update-alternatives --display iptables
sudo nft list ruleset

در اوبونتو 24.04 (نسخه iptables 1.8.10، تا اوت 2026)، دستور iptables -V خروجی iptables v1.8.10 (nf_tables) را چاپ می‌کند. نام داخل براکت، نشان‌دهنده back end است. عبارت (nf_tables) به این معناست که دستور با nftables در ارتباط است. عبارت (legacy) به back end قدیمی x_tables اشاره دارد که اوبونتو همچنان آن را به عنوان iptables-legacy ارائه می‌دهد و هسته سیستم‌عامل نیز آن را به عنوان یک مجموعه قوانین کاملاً مجزا حفظ کرده است. دستور update-alternatives لینک نمادین (symlink) پشت این انتخاب را نمایش می‌دهد: link currently points to /usr/sbin/iptables-nft.

در یک VPS تازه که هیچ فایروالی روی آن تنظیم نشده است، دستور sudo nft list ruleset هیچ خروجی‌ای ندارد. این خروجی خالی، مبنای کار شماست. یک قانون را به روش قدیمی اضافه کنید و دوباره بررسی کنید.

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo nft list ruleset
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
  chain INPUT {
    type filter hook input priority filter; policy accept;
    tcp dport 22 counter packets 0 bytes 0 accept
  }
  chain FORWARD {
    type filter hook forward priority filter; policy accept;
  }
  chain OUTPUT {
    type filter hook output priority filter; policy accept;
  }
}

قانون iptables شما در واقع یک قانون nftables است. iptables-nft جداولی را که ایجاد می‌کند علامت‌گذاری کرده و nft هنگام مشاهده این علامت، آن هشدار را چاپ می‌کند؛ زیرا ویرایش چنین جدولی با nft باعث می‌شود دو ابزار مختلف مسئول مدیریت قوانین یکسانی شوند. به خروجی تولید شده توسط یک دستور نگاه کنید: جدولی که شما نام‌گذاری نکرده‌اید و زنجیره‌هایی (chains) که درخواست نکرده‌اید. این مدل قدیمی است و اولین چیزی است که هنگام نوشتن مستقیم nftables تغییر می‌کند.

What iptables -L hides from you

iptables -L shows the filter table only. NAT (network address translation) rules need iptables -t nat -L, and mangle rules need -t mangle. IPv6 lives in a separate command, ip6tables, with its own copy of every rule. A box can therefore look clean in one listing while something drops or rewrites your packets from a table you never checked.

sudo nft list ruleset prints every family, every table, every chain and every rule in one output. On a server you did not build yourself, that single command is the fastest way to see what is really loaded. Add -a to print rule handles, which you need in order to delete one rule instead of the whole chain.

Two habits are worth fixing while you are here. iptables -L resolves addresses and ports into names, so on a box with a broken resolver it looks like it has hung: use iptables -nvL. And confirm the legacy back end is empty with sudo iptables-legacy -nvL, because if rules exist in both back ends the kernel evaluates both, and neither listing shows you the whole picture.

جدول‌ها و زنجیره‌هایی که خودتان می‌سازید، نه آن‌هایی که به ارث می‌برید

nftables با هیچ شروع می‌شود. تا زمانی که یک جدول نسازید، هیچ جدول filter وجود ندارد و کلمه filter صرفاً نامی است که شما انتخاب کرده‌اید. یک زنجیره تنها زمانی بسته‌ها را می‌بیند که به آن نوع (type)، قلاب (hook) و اولویت (priority) بدهید؛ این ویژگی آن را به یک زنجیره پایه (base chain) تبدیل می‌کند. زنجیره‌ای که فاقد این موارد باشد، تنها با یک دستور صریح jump یا goto در دسترس قرار می‌گیرد، بنابراین تا زمانی که دستوری به آن پرش (jump) نکند، هیچ هزینه‌ای برای سیستم ندارد.

تغییر بزرگ دیگر، خانواده inet است. یک جدول inet می‌تواند IPv4 و IPv6 را در قوانین یکسانی مدیریت کند؛ این کار باعث حذف دسته‌ای از باگ‌ها می‌شود که در آن‌ها یک پورت در iptables بسته است اما در ip6tables کاملاً باز می‌ماند. این عدم تطابق به قدری رایج است که حالت شکست خاص خود را در سیستم‌های ufw دارد.

در اینجا یک مجموعه قوانین کامل برای سرور آورده شده است. این فایل در مسیر /etc/nftables.conf قرار می‌گیرد.

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
  set admin_ips {
    type ipv4_addr
    flags interval
    elements = { 203.0.113.5, 198.51.100.0/24 }
  }

  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    meta l4proto ipv6-icmp accept
    tcp dport 22 ip saddr @admin_ips counter accept
    tcp dport { 80, 443 } counter accept
  }

  chain forward {
    type filter hook forward priority filter; policy drop;
  }

  chain output {
    type filter hook output priority filter; policy accept;
  }
}

خط 2 را دو بار بخوانید. flush ruleset تمام جدول‌های موجود در سیستم، از جمله جدول‌هایی که توسط ufw و Docker ایجاد شده‌اند را حذف می‌کند. پیش از اجرای این دستور روی یک سرور فعال، ادامه مطلب را مطالعه کنید.

اولین قانون در زنجیره ورودی (input chain)، بیشترین حجم کار را انجام می‌دهد. ct state established,related accept اجازه می‌دهد پاسخ‌های مربوط به اتصالاتی که شما آغاز کرده‌اید به داخل بازگردند، بنابراین بقیه زنجیره فقط باید درباره اتصالات جدید تصمیم‌گیری کند. ct state invalid drop بسته‌هایی که با هیچ اتصال شناخته‌شده یا شروع معتبری مطابقت ندارند را دور می‌ریزد. هر چیزی که پس از آن می‌آید یک حفره صریح است و policy drop بقیه موارد را مدیریت می‌کند.

پیش از بارگذاری فایل، آن را بررسی کنید و هنگام انجام این کار، یک نشست SSH دوم باز نگه دارید. policy drop به همراه تنها یک غلط تایپی در قانون SSH، شما را از سرور خودتان بیرون می‌اندازد.

sudo nft -c -f /etc/nftables.conf
sudo nft -f /etc/nftables.conf
sudo nft list ruleset

nft -c -f فایل را تجزیه (parse) کرده و بدون بارگذاری هیچ چیزی، خطاها را گزارش می‌دهد. یک تجزیه موفق، هیچ خروجی‌ای چاپ نمی‌کند.

استفاده از Sets به‌جای لیست‌های طولانی قوانین

tcp dport { 80, 443 } یک set ناشناس است: یک قانون و یک جستجو، به‌جای یک قانون برای هر پورت. یک set نام‌گذاری‌شده مانند admin_ips فراتر می‌رود، زیرا می‌توانید در حین اجرای فایروال، محتوای آن را تغییر دهید.

sudo nft add element inet filter admin_ips { 203.0.113.9 }
sudo nft list set inet filter admin_ips
sudo nft delete element inet filter admin_ips { 203.0.113.9 }

بدون نیاز به reload و بدون شماره‌گذاری مجدد قوانین، تطبیق همیشه یک جستجوی واحد باقی می‌ماند، چه set شامل 5 آدرس باشد چه 50 هزار آدرس. flags interval قابلیتی است که به یک set اجازه می‌دهد محدوده‌ها و پیشوندهای CIDR (مسیریابی بدون کلاس بین دامنه‌ای) مانند 198.51.100.0/24 را در خود جای دهد. بدون این flag، set فقط آدرس‌های تکی را می‌پذیرد و بارگذاری پیشوند با خطا مواجه می‌شود.

Sets همچنین می‌توانند عناصر خود را پس از مدتی منقضی کنند.

set banned {
  type ipv4_addr
  flags timeout
  timeout 1h
}

با قانون ip saddr @banned drop، هر عنصر یک ساعت پس از اضافه شدن، خودبه‌خود حذف می‌شود. این همان روشی است که اکشن nftables در fail2ban on Ubuntu 24.04 برای مسدود کردن یک آدرس استفاده می‌کند: یک عنصر به set اضافه می‌شود، نه یک قانون جدید. اگر مفهوم پورت‌ها برای شما تازگی دارد، با what a port actually is on Linux شروع کنید.

یک تفاوت در هنگام مهاجرت باعث سردرگمی کاربران می‌شود. nftables تا زمانی که از آن نخواهید، بسته‌ها را نمی‌شمارد. iptables -nvL همیشه شمارنده‌ها را برای تمام قوانین نشان می‌دهد. در nftables فقط قوانینی که دارای کلمه کلیدی counter باشند، دارای شماره هستند؛ بنابراین در هر قانونی که انتظار دارید بعداً عیب‌یابی کنید، counter را قرار دهید.

نحوه تعیین ترتیب توسط هوک‌ها و اولویت‌ها

یک base chain یک هوک را نام‌گذاری می‌کند که همان نقطه در مسیر بسته (packet) است که زنجیره در آن اجرا می‌شود. prerouting پیش از تصمیم‌گیری مسیریابی اجرا می‌شود. input برای بسته‌هایی که مقصدشان این ماشین است اجرا می‌شود. forward برای بسته‌هایی که از طریق این ماشین مسیریابی می‌شوند اجرا می‌شود. output برای بسته‌هایی که از فرآیندهای محلی می‌آیند اجرا می‌شود. postrouting در آخرین مرحله، درست پیش از خروج بسته، اجرا می‌شود.

اولویت، زنجیره‌های درون یک هوک را مرتب می‌کند و عددی که کمتر باشد، زودتر اجرا می‌شود. nftables برای مقادیر کلاسیک نام‌هایی در نظر گرفته است: raw برابر با -300، mangle برابر با -150، dstnat برابر با -100، filter برابر با 0 و srcnat برابر با 100 است. نوشتن priority filter; همانند نوشتن priority 0; است.

اکنون بخشی که تعیین می‌کند آیا ترکیب ابزارها با هم کار می‌کند یا خیر: هر base chain که روی یک هوک ثبت شده باشد، به ترتیب اولویت اجرا می‌شود. بسته‌ای که در زنجیره شما پذیرفته (accept) شود، کارش تمام نشده است: accept فقط همان زنجیره را پایان می‌دهد و بسته به مسیر خود به سمت base chain بعدی در همان هوک ادامه می‌دهد. drop در همه جا نهایی است و بسته را بلافاصله متوقف می‌کند. بنابراین، یک قانون سهل‌گیرانه در جدول شما نمی‌تواند اثر یک drop در جدول ufw را خنثی کند، صرف‌نظر از اینکه کدام‌یک زودتر اجرا شود؛ و accept شما هیچ حفاظتی در برابر زنجیره‌ای که بعداً اجرا می‌شود، ایجاد نمی‌کند.

دو base chain روی یک هوک با اولویت یکسان، به ترتیب ثبت اجرا می‌شوند که این ترتیب به این بستگی دارد که کدام سرویس زودتر شروع شده باشد. این ترتیب ممکن است پس از reboot تغییر کند. اگر مجبورید جدول خود را در کنار ufw اجرا کنید، به آن اولویت متمایزی بدهید تا ترتیب اجرا به‌جای رقابت بر سر زمان‌بندی، به‌صورت مشخص تعیین شده باشد.

چرا نیازی به نوشتن قانون NAT معکوس نیست؟

این پرسشی است که افراد اغلب در آن دچار اشتباه می‌شوند، بنابراین پاسخ مستقیم آن اینجاست. سیستم Connection tracking (ردیابی اتصال) ترجمه معکوس را برای شما می‌نویسد. هیچ قانون دومی برای اضافه کردن وجود ندارد.

یک جدول nat که هر دو نیمه وظیفه معمول VPS را انجام می‌دهد، به این شکل است:

table inet nat {
  chain prerouting {
    type nat hook prerouting priority dstnat; policy accept;
    iifname "enp1s0" tcp dport 8080 dnat ip to 10.0.0.5:80
  }

  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.0.0.0/24 oifname "enp1s0" masquerade
  }
}

تنها اولین بسته (packet) از یک اتصال در برابر زنجیره nat ارزیابی می‌شود. هنگامی که یک قانون مطابقت پیدا می‌کند، هسته (kernel) آن ترجمه را در جدول connection tracking در کنار ورودی اتصال ذخیره می‌کند. هر بسته بعدی، در هر دو جهت، بر اساس ورودی ذخیره‌شده بازنویسی می‌شود و دیگر هیچ قانونی خوانده نمی‌شود. ابزار conntrack را نصب کنید و یک ورودی زنده را مشاهده کنید.

sudo apt install -y conntrack
sudo conntrack -L -p tcp
tcp 6 431999 ESTABLISHED src=198.51.100.20 dst=203.0.113.10 sport=54321 dport=8080 src=10.0.0.5 dst=198.51.100.20 sport=80 dport=54321 [ASSURED] mark=0 use=1

آن را به صورت دو چندتایی (tuple) بخوانید. چهار فیلد اول، اتصالی است که کلاینت ارسال کرده و خطاب به 203.0.113.10:8080، یعنی آدرس عمومی شما، بوده است. چهار فیلد دوم، پاسخی است که هسته انتظار دارد؛ این پاسخ از قبل معکوس و ترجمه شده و از سمت 10.0.0.5:80، یعنی backend واقعی، می‌آید. آن چندتایی دوم همان قانون معکوس است. هسته زمانی که اولین بسته مطابقت پیدا کرد، آن را نوشت.

بنابراین برای جهت بازگشت، قانونی ننویسید. چنین قانونی نمی‌تواند مطابقت پیدا کند، زیرا بسته‌های بازگشتی متعلق به یک اتصال برقرار شده (established) هستند و هرگز به زنجیره nat نمی‌رسند؛ و اگر به نحوی مطابقت پیدا می‌کرد، شما بسته‌ای را ترجمه می‌کردید که هسته قبلاً آن را اصلاح کرده است.

اینکه بازنویسی باید کجا قرار گیرد، از همان مکانیسم پیروی می‌کند. ترجمه مقصد (Destination translation) باید در prerouting و پیش از تصمیم مسیریابی (routing decision) اجرا شود، زیرا مسیریابی باید مقصد جدید را ببیند، در غیر این صورت بسته به جای اشتباهی می‌رود. ترافیکی که خودِ سیستم تولید می‌کند نیز به همین دلیل در hook مربوط به output مدیریت می‌شود. ترجمه مبدأ (Source translation)، شامل بازنویسی پورت مبدأ، باید در postrouting و پس از آنکه مسیریابی، رابط خروجی را انتخاب کرد، اجرا شود. masquerade آدرس خود را از آن رابط می‌گیرد و رابط تا زمانی که مسیریابی اجرا نشود، مشخص نیست.

به همین دلیل است که قانونی مانند این، تنها در انتهای مسیر قرار می‌گیرد و نه جای دیگر.

ip saddr 10.0.0.0/24 oifname "enp1s0" snat ip to 203.0.113.10:20000-30000

محدوده پورت، پورت مبدأ را همراه با آدرس مبدأ بازنویسی می‌کند؛ این همان چیزی است که وقتی چندین کلاینت داخلی از یک آدرس عمومی استفاده می‌کنند و پورت‌های مبدأ آن‌ها با هم تداخل پیدا می‌کند، به آن نیاز دارید. یک پاسخ خطاب به پورتی در آن محدوده می‌رسد، conntrack آن را با ورودی مطابقت می‌دهد و پیش از تحویل بسته، پورت مبدأ اصلی جایگزین می‌شود. باز هم تأکید می‌شود: هیچ قانون دومی نیاز نیست.

یک نتیجه عملی: تغییر یک قانون NAT، اتصالات موجود را جابه‌جا نمی‌کند، زیرا ترجمه آن‌ها از قبل ذخیره شده است. آن‌ها تا زمانی که ورودی‌هایشان منقضی نشود، رفتار قبلی را حفظ می‌کنند. sudo conntrack -D -p tcp --dport 8080 ورودی‌های منطبق را حذف می‌کند و sudo conntrack -F همه آن‌ها را پاک می‌کند. در مورد دومی روی یک دستگاه NAT با احتیاط عمل کنید، زیرا آن ترجمه‌های ذخیره‌شده همان چیزی هستند که اتصالات فعلی را زنده نگه می‌دارند؛ بنابراین پاک کردن آن‌ها، تمام اتصالات عبوری از دستگاه را یک‌باره قطع می‌کند.

تداخل قوانین ufw و Docker

ابزار ufw یک رابط کاربری برای iptables است که خود در اوبونتو رابطی برای nftables محسوب می‌شود. بنابراین، یک سرور مجهز به ufw دارای جدولی به نام ip filter است که مملو از زنجیره‌هایی با نام‌های ufw-before-input، ufw-user-input و غیره است؛ همچنین یک کپی ip6 filter از همین ساختار نیز وجود دارد. وضعیت را با sudo nft list ruleset | grep ufw بررسی کنید. این زنجیره‌ها از فایل‌های موجود در /etc/ufw تولید می‌شوند و ufw reload آن‌ها را از نو بازنویسی می‌کند؛ به همین دلیل است که یک قانون iptables که به‌صورت دستی اضافه شده باشد، با بارگذاری مجدد ufw ناپدید می‌شود. مقاله اصول اولیه ufw برای VPS این ساختار فایل‌ها را پوشش می‌دهد.

Docker قوانین فایروال را خودش مدیریت می‌کند و با ufw هماهنگ نیست. انتشار یک پورت با استفاده از -p 80:80، یک قانون DNAT در جدول nat و یک قانون accept در مسیر forward می‌نویسد که هر دو پیش از زنجیره‌های کاربری ufw اجرا می‌شوند. نتیجه این است که همه غافلگیر می‌شوند: ufw deny 80 بارگذاری شده است، اما کانتینر همچنان از اینترنت در دسترس است. راه‌حل این مشکل در زنجیره DOCKER-USER نهفته است که Docker برای قوانین شما در نظر گرفته است و مقاله چرا کانتینرهای Docker قوانین ufw را نادیده می‌گیرند آن را به‌طور کامل توضیح می‌دهد. با استفاده از sudo nft list ruleset | grep -i docker ببینید چه قوانینی روی سرور شما فعال است.

اکنون خط flush ruleset را از پیکربندی بالا دوباره بخوانید. این دستور تمام جداول، از جمله جداولی که این دو ابزار مدیریت می‌کنند را حذف می‌کند. در یک میزبان Docker، پورت‌های منتشرشده تا زمانی که sudo systemctl restart docker زنجیره‌ها را بازسازی نکند، از کار می‌افتند. این یک خط، رایج‌ترین روشی است که کاربران هنگام مرتب‌سازی فایروال، سرویس‌های خود را به‌طور ناخواسته از دسترس خارج می‌کنند.

قوانینی که پس از راه‌اندازی مجدد باقی می‌مانند

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

برای nftables، فایل /etc/nftables.conf توسط nftables.service خوانده می‌شود. اوبونتو این سرویس را به‌صورت غیرفعال عرضه می‌کند، بنابراین پیش از اعتماد به آن، وضعیتش را بررسی کنید.

systemctl is-enabled nftables
sudo nft -c -f /etc/nftables.conf
sudo systemctl enable --now nftables

برای iptables، بسته مورد نیاز iptables-persistent است که netfilter-persistent را نصب کرده و قوانین را در /etc/iptables/rules.v4 و /etc/iptables/rules.v6 ذخیره می‌کند.

sudo apt install -y iptables-persistent
sudo netfilter-persistent save

هر دو را هم‌زمان اجرا نکنید. دو فایلی که هر کدام ادعای مدیریت فایروال را دارند، دچار اختلاف می‌شوند و فایلی که در نهایت بارگذاری می‌شود، اولویت پیدا می‌کند؛ وضعیتی که با خواندن هیچ‌کدام از فایل‌ها قابل پیش‌بینی نیست.

یک دام مرتبط در خروجی گرفتن (dump) از قوانین فعال وجود دارد. دستور sudo nft -s list ruleset > /etc/nftables.conf هر چیزی را که در آن لحظه بارگذاری شده است، شامل جداول ufw و جداول Docker، ضبط می‌کند. اگر این خروجی را در زمان بوت بازیابی کنید، یک کپی ثابت از قوانینی خواهید داشت که آن ابزارها انتظار دارند خودشان بسازند؛ سپس با شروع به کار آن ابزارها، یک کپی دوم نیز ایجاد می‌شود. فقط جدول خودتان را با استفاده از sudo nft -s list table inet filter خروجی بگیرید. فلگ -s شمارنده‌ها را حذف می‌کند، چرا که شمارنده‌ها جایی در فایل پیکربندی ندارند.

آیا باید فایروال را روی VPS خود فعال کنید؟

تا زمانی که به قابلیتی فراتر از توانایی‌های ufw نیاز ندارید، آن را به حال خود رها کنید. ufw نیازهای معمول یک VPS را پوشش می‌دهد: یک سیاست پیش‌فرض deny به همراه تعدادی پورت باز. جایگزینی آن با یک مجموعه قوانین دست‌نویس، صرفاً برای انجام این کار، همان سطح امنیت را به شما می‌دهد با این تفاوت که یک مورد اضافه برای نگهداری خواهید داشت.

زمانی به سراغ ابزارهای بومی (native) بروید که نیاز شما خارج از مدل ufw باشد: مواردی مانند NAT و port forwarding، مجموعه‌هایی که در زمان اجرا (runtime) به‌روزرسانی می‌کنید، یک قانون واحد که هر دو خانواده آدرس (IPv4 و IPv6) را پوشش دهد، یا اولویت‌بندی زنجیره‌ها (chain priorities) که خودتان تعیین می‌کنید. این‌ها دلایل واقعی هستند و ufw راهی برای پیاده‌سازی آن‌ها ندارد.

اگر تصمیم گرفتید از ابزارهای بومی استفاده کنید، این کار را به‌طور کامل انجام دهید. دستورات sudo ufw disable و sudo systemctl disable --now ufw را اجرا کنید، با sudo nft list ruleset تأیید کنید که جداول آن پاک شده‌اند، و سپس فایل قوانین خود را بارگذاری کنید. سیستمی که همزمان ufw و یک جدول دست‌نویس را اجرا می‌کند همچنان ترافیک را عبور می‌دهد، اما سیاست اجرایی در واقع ترکیبی از دو مجموعه قوانین است که ترتیب ارزیابی آن‌ها توسط زمان راه‌اندازی سرویس‌ها تعیین می‌شود؛ در این حالت، هیچ‌کس با خواندن فایل‌ها نمی‌تواند بگوید که سیستم واقعاً چه رفتاری دارد.

مهاجرت مجموعه‌قوانین موجود iptables

iptables-translate یک قانون را تبدیل کرده و فرمت nftables آن را چاپ می‌کند. این دستور هیچ تغییری در سیستم ایجاد نمی‌کند.

iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
nft add rule ip filter INPUT tcp dport 22 counter accept

iptables-restore-translate -f /etc/iptables/rules.v4 همین کار را برای کل یک مجموعه‌قانون ذخیره‌شده انجام می‌دهد. خروجی آن را به عنوان پیش‌نویس اولیه در نظر بگیرید. تبدیل به‌صورت مکانیکی و قانون‌به‌قانون انجام می‌شود؛ بنابراین نام جدول‌ها و زنجیره‌های قدیمی، دو مجموعه‌قانون مجزا برای IPv4 و IPv6، و هیچ‌کدام از مجموعه‌هایی (sets) که مهاجرت را ارزشمند می‌کردند، به دست نخواهید آورد. آن را به‌صورت دستی به یک جدول inet بازنویسی کنید و سپس پیش از اعمال روی سرور زنده، آن را با nft -c -f بررسی کنید.

آدرس‌های موجود در این مثال‌ها از محدوده‌های مستندات 203.0.113.0/24 و 198.51.100.0/24 گرفته شده‌اند و enp1s0 نام یک رابط شبکه است. به‌جای کپی کردن مقادیر من، از ip route show default و ip -br addr استفاده کنید، زیرا در ایمیج‌های فعلی Ubuntu به‌ندرت چیزی با نام eth0 یافت می‌شود.

FAQ

آیا iptables در اوبونتو منسوخ شده است؟

این دستور حذف نمی‌شود و همچنان در Ubuntu 24.04 کار می‌کند. آنچه تغییر کرده، مکانیزم زیرساختی آن است: iptables یک رابط کاربری است که قوانین را از طریق back end مربوط به iptables-nft در nftables می‌نویسد. وضعیت خود را با iptables -V بررسی کنید که در نسخه 24.04 خروجی iptables v1.8.10 (nf_tables) را نمایش می‌دهد. back end قدیمی یعنی x_tables همچنان به عنوان iptables-legacy ارائه می‌شود و مجموعه قوانین کاملاً مجزایی دارد؛ بنابراین قوانین را فقط در یک back end قرار دهید و نه در هر دو.

آیا برای خنثی‌سازی NAT در مسیر بازگشت به قانون دومی نیاز دارم؟

خیر. Connection tracking زمانی که اولین بسته از یک اتصال با یک قانون nat مطابقت پیدا می‌کند، ترجمه را ذخیره می‌کند و تمام بسته‌های بعدی در هر دو جهت بر اساس آن ورودی ذخیره‌شده بازنویسی می‌شوند. sudo conntrack -L آن را به صورت دو tuple برای هر اتصال نشان می‌دهد: جهت اصلی و سپس پاسخ معکوس‌شده. قانونی که برای جهت بازگشت نوشته شود کمکی نمی‌کند، زیرا بسته‌های بازگشتی هرگز به زنجیره nat نمی‌رسند.

آیا می‌توانم ufw و قوانین nftables خودم را همزمان اجرا کنم؟

این کار عملی است، اما برای خود دردسر ایجاد می‌کنید. هر base chain در یک hook اجرا می‌شود، بنابراین سیاست نهایی ترکیبی از هر دو مجموعه قوانین است که بر اساس اولویت و در صورت تساوی اولویت، بر اساس اینکه کدام سرویس زودتر شروع شده، مرتب می‌شوند. یک drop در هر کدام نهایی است و یک accept در قوانین شما مانع از آن نمی‌شود که دیگری همان بسته را drop کند. یکی از ابزارها را انتخاب کنید. اگر nftables است، ابتدا ufw را غیرفعال کنید و مطمئن شوید که جداول آن از sudo nft list ruleset پاک شده‌اند.

چگونه قوانین nftables را در اوبونتو پس از reboot حفظ کنم؟

مجموعه قوانین را در /etc/nftables.conf قرار دهید، آن را با sudo nft -c -f /etc/nftables.conf بررسی کنید و سپس sudo systemctl enable --now nftables را اجرا کنید. این سرویس به‌طور پیش‌فرض فعال نیست، بنابراین اجرای یک‌باره systemctl is-enabled nftables توصیه می‌شود. هنگام تولید آن فایل، فقط جدول خود را با sudo nft -s list table inet filter dump کنید، زیرا یک dump کامل با list ruleset جداولی را که ufw و Docker برای خود مدیریت می‌کنند نیز شامل می‌شود.