آموزش تنظیمات firewalld در Rocky و AlmaLinux
با دستورات firewalld در Rocky و AlmaLinux آشنا شوید. یاد بگیرید چگونه پورتهای SSH و وب را باز کنید و با استفاده از فلگ --permanent از حذف قوانین پس از ریبوت جلوگیری کنید.
firewalld چیست و چرا Rocky و AlmaLinux آن را ارائه میدهند
firewalld مدیریت فایروالی است که بهصورت پیشفرض روی Rocky Linux، AlmaLinux و سایر توزیعهای بازسازیشده از Red Hat Enterprise Linux (RHEL) نصب میشود. هر دو توزیع این پیشفرض را به ارث بردهاند، نه اینکه خود آن را انتخاب کرده باشند؛ این موضوع زمانی منطقیتر میشود که بدانید چگونه Rocky و AlmaLinux پس از تغییر مسیر CentOS، کار Red Hat را بازسازی کردند. این ابزار خود بستهها را بازرسی نمیکند. بلکه یک پیکربندی ذخیرهشده را نگه میدارد و آن را به قوانین nftables تبدیل میکند. یک دستور، یعنی firewall-cmd، آن را در حالی که سرور آنلاین است ویرایش میکند. هیچچیز در این راهنما بین این دو توزیع تغییر نمیکند، زیرا مواردی که واقعاً Rocky را از AlmaLinux جدا میکنند، تعهد به سازگاری و طیف پردازندههای پشتیبانیشده هستند، نه فایروال.
اگر قبلاً میدانید ufw در یک VPS اوبونتو چگونه کار میکند، وظیفه آن را میشناسید. firewalld دو مفهوم اضافه میکند که ufw ندارد. اولی zones است: یک سیاست نامگذاریشده که بستهها در آن دستهبندی میشوند. دومی تفکیک بین قوانین زنده (live) و قوانین ذخیرهشده است که با فلگ --permanent مشخص میشود و بزرگترین منبع سردرگمی در این ابزار است.
تمام موارد زیر دستوراتی هستند که روی سرور خود اجرا میکنید. هر تغییر را از یک ماشین دوم تست کنید، زیرا قانونی که روی خودِ سرور درست به نظر میرسد، ممکن است از سمت اینترنت اشتباه باشد.
پیش از هر اقدام دیگری، SSH را باز کنید
بیشتر نصبهای Rocky و AlmaLinux بهصورت پیشفرض دارای firewalld هستند و پیکربندی ارائهشده در آن، اجازه دسترسی SSH را میدهد. برخی از ایمیجهای حداقلی (minimal) ابری، این سرویس را حذف میکنند. بهجای فرض کردن، وضعیت را بررسی کنید.
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --stateدستور firewall-cmd --state وضعیت running را چاپ میکند. اگر سرویس متوقف باشد، هر فراخوانی دیگر firewall-cmd پاسخ FirewallD is not running را برمیگرداند و با کد خروجی غیر صفر خارج میشود. این اولین موردی است که هنگام کار نکردن یک دستور باید بررسی کنید.
اکنون آنچه در حال حاضر مجاز است را بخوانید.
sudo firewall-cmd --list-allخروجی واقعی شامل چند خط بیشتر است. این موارد همانهایی هستند که اهمیت دارند:
public (active)
target: default
interfaces: eth0
sources:
services: cockpit dhcpv6-client ssh
ports:
rich rules:وجود ssh در خط services: دلیل فعال ماندن نشست (session) شماست. اگر این مورد وجود ندارد، پیش از دست زدن به هر چیز دیگری آن را اضافه کنید؛ زیرا راهاندازی فایروال بدون قانون SSH، نشست شما را قطع کرده و اجازه ورود مجدد نمیدهد.
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reloadعبارت target: default به این معناست که بستهای که با هیچ قانونی مطابقت ندارد، با یک پاسخ ICMP (پروتکل پیام کنترل اینترنت) از نوع host-prohibited رد میشود، بنابراین کلاینتی که به یک پورت بسته متصل میشود، بلافاصله No route to host را دریافت میکند. تنظیم هدف (target) روی DROP باعث میشود سرور در عوض سکوت کند و اسکنرها منتظر timeout بمانند.
sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reloadپیش از اجرای آن، از هزینه این کار آگاه باشید: DROP همچنین باعث میشود سرور به ping پاسخ ندهد، بنابراین سیستم مانیتورینگ خودتان نیز دیگر پاسخی دریافت نخواهد کرد.
چرا قانون من ناپدید شد؟ پرچم --permanent
ابزار firewalld همزمان دو پیکربندی را نگهداری میکند. پیکربندی runtime همان چیزی است که هسته سیستمعامل در همین لحظه اعمال میکند. پیکربندی permanent همان چیزی است که در /etc/firewalld/zones/public.xml ذخیره شده و پس از reload یا reboot دوباره بارگذاری میشود.
دستوری که بدون --permanent اجرا شود، فقط پیکربندی runtime را تغییر میدهد. این تغییر بلافاصله اعمال میشود اما با reload یا reboot بعدی از بین میرود. دستوری که با --permanent اجرا شود، فایل را تغییر میدهد اما وضعیت در حال اجرا را دستنخورده باقی میگذارد؛ بنابراین پورت تا زمانی که reload نکنید، بسته میماند. هیچکدام از این رفتارها باگ نیستند. هر دو مورد باعث تعجب کاربران میشوند، زیرا دستور در هر دو حالت خروجی success را نمایش میدهد.
همیشه هر دو را با هم بنویسید.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reloadشما میتوانید هر دو پیکربندی را مشاهده کنید؛ این سریعترین راه برای تشخیص این است که کدامیک از دو اشتباه بالا را مرتکب شدهاید.
sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-servicesدستور اول مجموعه فعال (live) را نمایش میدهد. دستور دوم مجموعه ذخیرهشده را چاپ میکند. اگر مجموعه فعال شامل سرویسی باشد که در مجموعه ذخیرهشده نیست، آن قانون با reload بعدی حذف میشود. اگر مجموعه ذخیرهشده شامل سرویسی باشد که در مجموعه فعال نیست، شما فراموش کردهاید reload کنید. دستور sudo firewall-cmd --runtime-to-permanent تمام تنظیمات فعال را در فایل ذخیرهشده کپی میکند که پس از یک جلسه آزمایش، بسیار مفید است.
دستور --reload وضعیت رهگیری اتصالات (connection tracking) را حفظ میکند، بنابراین نشست SSH شما قطع نمیشود. دستور --complete-reload ماژولهای هسته را نیز دوباره بارگذاری میکند و آن وضعیت را از دست میدهد که معمولاً باعث قطع شدن تمام اتصالات باز، از جمله اتصال شما میشود. از reload معمولی استفاده کنید.
یک لایه امنیتی داخلی وجود دارد. یک قانون runtime میتواند بهصورت خودکار منقضی شود.
sudo firewall-cmd --add-service=http --timeout=5mاین قانون پس از پنج دقیقه خودبهخود حذف میشود. این قابلیت با --permanent قابل ترکیب نیست و هدف همین است: این دستور برای آزمایش تغییری که از آن مطمئن نیستید، کاربرد دارد. لایه امنیتی قدیمیتر، بهتر است. هنگام ویرایش قوانین، یک نشست SSH دوم باز نگه دارید و تا زمانی که با یک ورود (login) جدید ثابت نشده که قوانین جدید کار میکنند، آن را نبندید.
زونها و دلیل اهمیت زون پیشفرض در VPS
زون (Zone) مجموعهای نامگذاریشده از مجوزها با یک سطح اعتماد مشخص است. firewalld هر بسته ورودی را دقیقاً در یک زون قرار میدهد. این ابزار ابتدا آدرس مبدأ بسته را با لیست sources: هر زون مطابقت میدهد. اگر هیچ موردی مطابقت نداشته باشد، از زونی استفاده میکند که اینترفیس ورودی به آن متصل است. اگر اینترفیس به هیچ زونی متصل نباشد، بسته به زون پیشفرض هدایت میشود.
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zonesدر یک VPS با یک اینترفیس شبکه، پاسخ اول تقریباً همیشه public است و این تنها زونی است که از آن استفاده خواهید کرد. دستور firewall-cmd بدون آرگومان --zone= روی زون پیشفرض عمل میکند؛ به همین دلیل است که تمام دستورات کوتاه در این راهنما بدون نیاز به نام بردن از زون کار میکنند.
خطایی که باعث هدر رفتن وقت میشود این است: اگر اینترفیس به زون دیگری متصل باشد، قوانین شما در public ثبت میشوند در حالی که ترافیک در جای دیگری پردازش میشود؛ بنابراین هر چه اضافه کنید بیاثر است و هیچ هشداری هم دریافت نمیکنید. دستور --get-active-zones اتصال را نشان میدهد:
public
interfaces: eth0اگر اینترفیس تحت نام زون دیگری ظاهر شد، یا قوانین خود را با --zone= در آن زون بنویسید، یا اینترفیس را جابهجا کنید.
sudo firewall-cmd --permanent --zone=public --change-interface=eth0
sudo firewall-cmd --reloadNetworkManager اینترفیسها را در Rocky و AlmaLinux مدیریت میکند و هنگام بالا آمدن اتصال، زون را مجدداً اعمال میکند. زون را در آنجا نیز تنظیم کنید تا با reboot، تنظیمات شما از بین نرود. نام اتصال را از دستور اول بردارید، زیرا بهندرت با نام دستگاه (device name) یکسان است.
sudo nmcli connection show
sudo nmcli connection modify "System eth0" connection.zone publicتطبیق بر اساس مبدأ (Source matching) بر تطبیق بر اساس اینترفیس اولویت دارد؛ این همان روشی است که باعث میشود یک آدرس، سیاست متفاوتی دریافت کند. زون داخلی trusted همه چیز را میپذیرد.
sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10/32
sudo firewall-cmd --reloadدر استفاده از آن دقت کنید. این زون تمام پورتهای سرور را برای آن آدرس باز میکند، از جمله دیتابیسی که تصور میکردید خصوصی است. زمانی که فقط یک پورت خاص را برای یک میزبان میخواهید، از rich rule استفاده کنید.
سرویس در firewalld چیست؟
یک سرویس، مجموعهای نامگذاریشده از پورتهاست که در قالب یک فایل XML ارائه میشود. --add-service=https پورت 443/tcp را باز میکند، زیرا /usr/lib/firewalld/services/https.xml تعریف میکند که https به چه معناست.
sudo firewall-cmd --get-services
sudo firewall-cmd --info-service=https--info-service پورتهای پنهانشده پشت این نام را نمایش میدهد:
https
ports: 443/tcpهرگاه نامی برای یک سرویس وجود دارد، از آن استفاده کنید. این کار باعث میشود پیکربندی شما در --list-all پس از شش ماه خوانایی داشته باشد؛ همچنین بستههایی مانند Cockpit فایل سرویس اختصاصی خود را نصب میکنند. برای هر موردی که تعریفی ندارد، از --add-port استفاده کنید.
نکتهای که باید به آن توجه داشت: سرویس ssh فقط به معنای پورت 22/tcp است و هیچ چیز دیگری را شامل نمیشود. اگر در حین ایمنسازی دسترسی SSH روی سرور، پورت SSH را تغییر دادهاید، --add-service=ssh پورتی که واقعاً از آن استفاده میکنید را باز نخواهد کرد.
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reloadدر توزیعهای مبتنی بر RHEL، قفل دومی نیز برای این در وجود دارد. SELinux (مخفف Security-Enhanced Linux) به شماره پورتها برچسب میزند و sshd اجازه ندارد به پورتی خارج از برچسبهای تعریفشدهاش متصل شود. در این صورت، سرویس از اجرا امتناع میکند و در لاگ پیام error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. ثبت میشود. ابتدا پورت را برچسبگذاری کنید.
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222چگونه میتوانم ببینم در حال حاضر چه چیزی باز است؟
sudo firewall-cmd --list-all
sudo firewall-cmd --list-rich-rules
sudo nft list table inet firewalld | head -n 40دو دستور اول گزارش میدهند که firewalld چه وضعیتی را در نظر دارد. دستور سوم قوانینی را میخواند که هسته (kernel) واقعاً در جدول متعلق به firewalld اعمال کرده است. این موارد باید با یکدیگر مطابقت داشته باشند.
هیچکدام از اینها اثبات قطعی نیست. تست را از یک ماشین دیگر انجام دهید:
nc -zv 203.0.113.20 443تست را روی خود سرور اجرا نکنید. فایروال firewalld تمام ترافیک ورودی به رابط loopback را میپذیرد، بنابراین curl http://localhost:8080 فارغ از قوانین شما با موفقیت انجام میشود. این تست فقط به شما میگوید که سرویس فعال است و هیچ اطلاعاتی درباره وضعیت فایروال به شما نمیدهد.
مجاز کردن یک پورت وب
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-servicesدستور آخر اکنون باید http https را در کنار موارد قبلی فهرست کند. اگر سایت همچنان پاسخ نمیدهد، احتمالاً مشکل از فایروال نیست. یک قانون فقط اجازه عبور بسته را میدهد. یک پردازش همچنان باید روی آن پورت در حال گوش دادن باشد.
sudo ss -tlnpسوکتی که به صورت 0.0.0.0:443 یا *:443 نمایش داده میشود، اتصالات را از هر آدرسی میپذیرد. سوکتی که به صورت 127.0.0.1:443 نمایش داده میشود، فقط روی loopback پاسخ میدهد و هیچ قانون فایروالی نمیتواند آن را از خارج قابل دسترس کند. پورتها و سوکتهای در حال گوش دادن در لینوکس این تفاوت را با جزئیات بیشتری بررسی میکند.
چگونه میتوانم دوباره یک پورت را ببندم؟
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reloadقانون --permanent در اینجا نیز صدق میکند و در این جهت، تأثیر آن شدیدتر است. اگر سرویسی را فقط از runtime حذف کنید، پورت بسته به نظر میرسد، اما با reload یا reboot بعدی، تنظیمات از فایل ذخیرهشده دوباره بارگذاری شده و پورت باز میشود. این یک حفره امنیتی است که متوجه آن نخواهید شد، زیرا بررسی اولیهای که انجام دادید با موفقیت انجام شده است.
حذف موردی که اصلاً وجود نداشته است، پیام Warning: NOT_ENABLED: http را چاپ میکند و همچنان با کد خروج 0 پایان مییابد. افزودن یک مورد تکراری نیز پیام Warning: ALREADY_ENABLED: http را در پی دارد. هر دو حالت ایمن هستند. اشتباه تایپی در نام سرویس متفاوت است: Error: INVALID_SERVICE به این معناست که firewalld هیچ تعریفی با آن نام ندارد و هیچ تغییری اعمال نشده است.
اگر در --list-all خود عبارت cockpit را میبینید و از کنسول وب Cockpit روی پورت 9090 استفاده نمیکنید، آن را حذف کنید. هر پورت باز، سرویسی است که باید آن را بهروز نگه دارید. برای سرویسهایی که تصمیم دارید حفظ کنید، dnf-automatic میتواند بهروزرسانیهای امنیتی را طبق زمانبندی نصب کند تا این وظیفه به حافظه شما وابسته نباشد. البته نصب وصله با اجرای آن متفاوت است و needs-restarting نشان میدهد که پس از اعمال بهروزرسانیها، کدام سرویسها هنوز از کتابخانههای قدیمی استفاده میکنند.
محدود کردن یک پورت به یک آدرس مبدأ
قوانین Rich برای زمانی است که نام سرویس بهتنهایی نمیتواند منظور شما را بیان کند و به فرمت طولانیتری نیاز دارید. محدود کردن SSH به یک آدرس دفتر کار، نیازمند دو دستور است؛ دستور دوم همان چیزی است که معمولاً فراموش میشود.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reloadیک zone مجموعهای از مجوزهاست، نه یک لیست شمارهدار که با اولین تطبیق متوقف شود. قانون Rich یک مجوز پذیرش (accept) برای یک آدرس خاص اضافه میکند. این قانون هیچکس را رد (deny) نمیکند. تا زمانی که ssh در خط services: قرار دارد، کل اینترنت همچنان به پورت 22 دسترسی دارد و قانون Rich هیچ تغییر قابلاندازهگیری ایجاد نمیکند. ورودی عمومی را حذف کنید، در غیر این صورت قانون محدودکننده صرفاً جنبه تزئینی خواهد داشت.
برای پورتی که نام سرویس ندارد، بهجای آن از شماره پورت استفاده کنید.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'برای مسدود کردن (drop) یک شبکه مزاحم و ثبت سابقه آن، عنصر log را پیش از action قرار دهید؛ این همان ترتیبی است که زبان قوانین Rich انتظار دارد.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" log prefix="fw-drop " level="info" limit value="3/m" drop'
sudo firewall-cmd --reload
sudo journalctl -k -g fw-dropمقدار limit از پر شدن journal توسط سیل بستههای ارسالی جلوگیری میکند. پیش از آنکه دسترسی SSH را به یک آدرس واحد محدود کنید، مطمئن شوید که آن آدرس ثابت است. اتصال خانگی با IP متغیر، در روزی که آدرس تغییر کند شما را از سرور بیرون میاندازد؛ بنابراین ابتدا از عملکرد صحیح دسترسی کنسول ارائهدهنده سرویس خود اطمینان حاصل کنید.
دستورات ufw و معادلهای آنها در firewall-cmd
وظایف یکسان، ابزار متفاوت. هر خط --permanent به یک sudo firewall-cmd --reload پس از خود نیاز دارد، که این تنها نکتهای است که لیستی مانند این نمیتواند به شما نشان دهد.
sudo ufw enableبهsudo systemctl enable --now firewalldتبدیل میشودsudo ufw disableبهsudo systemctl disable --now firewalldتبدیل میشودsudo ufw status verboseبهsudo firewall-cmd --list-allتبدیل میشودsudo ufw allow OpenSSHبهsudo firewall-cmd --permanent --add-service=sshتبدیل میشودsudo ufw allow 443/tcpبهsudo firewall-cmd --permanent --add-port=443/tcpتبدیل میشودsudo ufw delete allow 443/tcpبهsudo firewall-cmd --permanent --remove-port=443/tcpتبدیل میشودsudo ufw allow from 203.0.113.10 to any port 22به قانون غنی (rich rule) نمایش داده شده در بالا تبدیل میشودsudo ufw reloadبهsudo firewall-cmd --reloadتبدیل میشودsudo ufw default deny incomingهمان رفتاری است که زونpublicدارد و--set-target=DROPنسخه بیصدای آن استsudo ufw logging onبهsudo firewall-cmd --set-log-denied=allتبدیل میشود
یک تفاوت ارزش بیان صریح دارد. ufw یک لیست شمارهگذاریشده نگه میدارد و شما میتوانید یک قانون را در موقعیت 1 درج کنید. firewalld هیچ شماره قانونی ندارد، بنابراین «قرار دادن این قانون در اولویت» در اینجا معنایی ندارد. هنگامی که دو ورودی firewalld با یکدیگر در تضاد به نظر میرسند، قانون پذیرش (accept) کلیتر برنده است، زیرا هیچ چیزی در مجموعه قوانین، دسترسی را رد (deny) نمیکند. شما باید خودتان ورودی کلی را حذف کنید.
چرا کانتینر Docker من در حالی که فایروال بسته به نظر میرسد، در دسترس است؟
دلیل این است که پورت منتشرشدهٔ کانتینر هرگز به بخشی از فایروال که zone شما کنترل میکند، نمیرسد. docker run -d -p 8080:80 nginx به Docker دستور میدهد تا قوانین NAT (ترجمه آدرس شبکه) و forwarding اختصاصی خود را بنویسد. بستهای که به پورت 8080 میرسد، بازنویسی شده و به سمت کانتینر هدایت میشود؛ بنابراین این بسته به جای تحویل به میزبان (host)، فوروارد (forward) میشود. خطوط services: و ports: در zone شما، بستههایی را مدیریت میکنند که به خود میزبان تحویل داده میشوند. قوانین Docker مسیر forward را کنترل میکنند و آنها را میپذیرند.
نتیجه این است که سروری دارید که در آن sudo firewall-cmd --list-all هیچ پورتی روی 8080 نشان نمیدهد، اما nc -zv 203.0.113.20 8080 از یک ماشین دیگر همچنان متصل میشود. ببینید Docker چه چیزی نصب کرده است:
sudo iptables -t nat -L DOCKER -nراه حل در پرچم publish نهفته است. پورت را به loopback متصل کنید و یک reverse proxy در مقابل آن قرار دهید.
docker run -d -p 127.0.0.1:8080:80 nginxاکنون کانتینر به curl http://127.0.0.1:8080 روی سرور پاسخ میدهد و از بیرون هیچ پاسخی دریافت نمیشود. کاربران Ubuntu نیز با همین مشکل مواجه میشوند که در چرا کانتینرهای Docker پورتها را مستقیماً از ufw عبور میدهند توضیح داده شده است. نسخه Rootful از Podman که در مخازن پایه Rocky و AlmaLinux ارائه میشود، پورتها را با همان رویکرد NAT منتشر میکند؛ بنابراین به جای اعتماد به لیست zone، از یک ماشین دیگر تست بگیرید. همین همپوشانی دلیلی است که نصب Docker Engine روی این توزیعها به چند مرحله نیاز دارد که در راهنماهای Ubuntu هرگز ذکر نمیشود؛ این مراحل با این واقعیت شروع میشوند که Podman از قبل مالک دستور docker است.
پایدارسازی پس از راهاندازی مجدد و خطاهایی که با آنها مواجه خواهید شد
sudo systemctl is-enabled firewalld
sudo systemctl status firewalldenabled و active (running) همان چیزی هستند که به آن نیاز دارید. فایروالی که در حال اجراست اما فعال (enable) نشده، تنها تا اولین راهاندازی مجدد (reboot) از شما محافظت میکند. این بررسی باید در لیستی که در ده دقیقه اول روی یک VPS جدید انجام میدهید، در کنار کلیدهای SSH و بهروزرسانیها قرار بگیرد.
دستورات خام nftables و firewalld با هم سازگار نیستند. فایروال firewalld جدولی به نام inet firewalld را مدیریت میکند. دستور sudo nft flush ruleset آن را حذف میکند، در نتیجه سرور در برابر همه چیز باز میشود و firewall-cmd --list-all همچنان پیکربندی مورد نظر شما را نمایش میدهد، زیرا firewalld آنچه را که تصور میکند گزارش میدهد، نه آنچه را که در هسته (kernel) وجود دارد. دستور sudo firewall-cmd --reload قوانین را دوباره نصب میکند. قوانین را با firewall-cmd بنویسید تا پس از بارگذاری مجدد (reload) باقی بمانند.
دو مدیریت فایروال روی یک سرور. نصب ufw یا iptables-services در کنار firewalld باعث میشود دو برنامه بدون اطلاع از یکدیگر شروع به نوشتن قوانین کنند و برنده کسی است که سرویسش دیرتر شروع شده باشد. یکی را انتخاب کنید. در Rocky و AlmaLinux، فایروال firewalld همان گزینهای است که توسط توزیع پشتیبانی میشود.
فایروال ارائهدهنده در مقابل سرور. بسیاری از پنلهای VPS یک فایروال شبکه جداگانه دارند. اگر --list-all نشان میدهد که یک پورت باز است اما اتصال از خارج همچنان ناموفق است، پیش از تغییر هر چیزی در سرور، پنل را بررسی کنید. این موضوع برعکس هم صادق است: یک قانون باز در پنل تا زمانی که firewalld بسته را رد (reject) میکند، هیچ تأثیری ندارد.
اجرای firewall-cmd بدون sudo. هر تغییری به دسترسی root نیاز دارد. بدون آن، درخواست توسط بررسی مجوز رد میشود و هیچ چیزی تغییر نمیکند، که در نگاه اول ممکن است به نظر برسد دستور نادیده گرفته شده است.
شش دستور، اکثر نیازهای روزمره را پوشش میدهند: --list-all برای خواندن وضعیت، --permanent --add-service یا --add-port برای باز کردن یک پورت، --permanent --remove-service برای بستن آن، --reload برای اعمال فایل ذخیرهشده، و --runtime-to-permanent پس از یک دوره آزمایش. زون (zone) مورد نظر public است، فلگ آن --permanent است و تنها بررسی دقیق و صادقانه، از طریق یک ماشین دیگر انجام میشود.
FAQ
چرا قانون firewalld من پس از راهاندازی مجدد ناپدید شد؟
این قانون فقط در پیکربندی runtime اعمال شده است. sudo firewall-cmd --add-service=http بلافاصله اعمال میشود و در reload یا reboot بعدی از بین میرود، زیرا پیکربندی ذخیرهشده در /etc/firewalld/zones/public.xml هرگز تغییر نکرده است. --permanent را اضافه کنید و سپس sudo firewall-cmd --reload را اجرا کنید. برای حفظ قوانینی که قبلاً بهصورت دستی اضافه کردهاید، sudo firewall-cmd --runtime-to-permanent را اجرا کنید که مجموعه قوانین فعال را در فایل ذخیرهشده کپی میکند.
چرا پس از افزودن قانون با --permanent تغییری ایجاد نمیشود؟
زیرا --permanent فقط فایل را مینویسد و فایروال در حال اجرا را تغییر نمیدهد. پورت تا زمانی که sudo firewall-cmd --reload پیکربندی ذخیرهشده را در kernel بارگذاری نکند، بسته میماند. sudo firewall-cmd --list-services را با sudo firewall-cmd --permanent --list-services مقایسه کنید: اگر لیست ذخیرهشده ورودیای دارد که در لیست فعال نیست، یعنی reload را انجام ندادهاید.
آیا باید از --add-service استفاده کنم یا --add-port؟
زمانی که نامی برای سرویس شما وجود دارد، از --add-service استفاده کنید. این کار هدف را مشخص میکند و sudo firewall-cmd --info-service=https دقیقاً نشان میدهد که آن نام شامل چه پورتهایی است. زمانی که سرویس شما تعریفنشده است یا روی پورت غیرمعمولی گوش میدهد، از --add-port استفاده کنید. سرویس ssh فقط به معنای 22/tcp است، بنابراین اگر SSH را به 2222 منتقل کردهاید، به --add-port=2222/tcp و یک برچسب SELinux برای آن پورت نیاز دارید.
چرا کانتینر Docker من در دسترس است در حالی که firewall-cmd پورت را بسته نشان میدهد؟
پورت منتشرشده توسط قوانین NAT خودِ Docker بازنویسی شده و به کانتینر هدایت میشود، بنابراین بسته هرگز به host تحویل داده نمیشود و لیستهای سرویس و پورت در zone فقط شامل بستههایی است که به host تحویل داده میشوند. کانتینر از اینترنت پاسخ میدهد در حالی که --list-all چیزی نشان نمیدهد. با استفاده از docker run -d -p 127.0.0.1:8080:80 nginx، پورت را فقط روی loopback منتشر کنید و یک reverse proxy در مقابل آن قرار دهید.
آیا میتوانم به جای firewalld از ufw روی Rocky Linux استفاده کنم؟
دو مدیریت فایروال روی یک سرور، قوانین را بدون اطلاع از یکدیگر مینویسند و اینکه کدام مجموعه باقی بماند، بستگی به این دارد که کدام سرویس در آخر شروع شده باشد. firewalld ابزار پشتیبانیشده در Rocky Linux و AlmaLinux است، از قبل نصب شده است و همان backend مربوط به nftables را مدیریت میکند که ufw مدیریت میکرد. zone پیشفرض و فلگ --permanent را یاد بگیرید تا به کل ابزار مسلط شوید.