اگر nmap را از بیرون روی سرور خودتان زدهاید و خروجی چیزی بیشتر از 22 و 80 و 443 نشان میدهد، همان لحظه یک تصمیم دارید: کدامیک از این پورتها باید بسته شود و کدامیک واقعاً لازم است باز بماند. این متن همان مرجع است؛ نه آموزش نصب، نه مقدمهچینی.
یک نکته پیش از جدول: «پورت سرویس» فقط یک عدد نیست. ترکیب پروتکل و پورت و آدرس bind است که معنا پیدا میکند. 3306/tcp روی 127.0.0.1 یک چیز است و همان پورت روی 0.0.0.0 چیز دیگری. بیشتر حادثههایی که دیدهام از نوع دوم بوده، نه از نوع اول.
جدول پورت سرویسهای پرکاربرد
| پورت | پروتکل | سرویس | باز بودن روی اینترنت؟ |
|---|---|---|---|
| 22 | TCP | SSH | فقط با کلید و محدودسازی IP |
| 25 | TCP | SMTP | تقریباً هرگز (اکثر ارائهدهندهها بستهاند) |
| 53 | TCP/UDP | DNS | فقط resolver عمومی؛ نه recursive باز |
| 80 | TCP | HTTP | بله، فقط برای redirect به HTTPS |
| 110 / 143 | TCP | POP3 / IMAP | فقط نسخه TLS دار |
| 443 | TCP/UDP | HTTPS / HTTP3 | بله |
| 587 / 465 | TCP | SMTP submission | بله، با احراز هویت |
| 993 / 995 | TCP | IMAPS / POP3S | بله |
| 1433 | TCP | MSSQL | خیر |
| 3000 / 8000 / 8080 | TCP | اپلیکیشن (Node، Django، …) | خیر؛ پشت reverse proxy |
| 3306 | TCP | MySQL / MariaDB | خیر |
| 5432 | TCP | PostgreSQL | خیر |
| 6379 | TCP | Redis | خیر، هرگز |
| 27017 | TCP | MongoDB | خیر |
ستون آخر را جدی بگیرید. پورتهای 6379 و 27017 و 3306 بیشترین قربانی را در اسکنهای خودکار میگیرند، چون نصب پیشفرض بسیاری از توزیعها آنها را روی همه اینترفیسها bind میکند و کاربر هم متوجه نمیشود.
پورتهایی که باز بودنشان یعنی فاجعه
سه دسته را جدا میکنم، چون راهحلشان یکی نیست.
۱. دیتابیسها
MySQL و PostgreSQL و Redis و MongoDB هیچوقت نباید از اینترنت قابل دسترس باشند. اگر اپلیکیشن روی همان سرور است، bind را به لوکال ببرید. در my.cnf:
[mysqld]
bind-address = 127.0.0.1
skip-networking = 0
در PostgreSQL هم در postgresql.conf مقدار listen_addresses = 'localhost' و در pg_hba.conf فقط 127.0.0.1/32 را مجاز بگذارید. اگر دیتابیس روی سرور دیگری است، تونل SSH بزنید، نه باز کردن پورت. راهنمای امنیت MySQL و محدودکردن دسترسیها همین مسیر را قدمبهقدم پوشش میدهد.
۲. Redis و سرویسهای بدون احراز هویت
Redis بهصورت پیشفرض رمز ندارد. یک نصب تازه روی سرور ابری، در فاصله چند دقیقه تا چند ساعت اسکن میشود. اگر خروجی redis-cli -h <ip> ping از بیرون PONG برگرداند، سرور شما همین حالا در خطر است. راهحل: bind 127.0.0.1 ::1 بههمراه protected-mode yes و در صورت نیاز requirepass.
۳. پنلهای مدیریتی و پورتهای دیباگ
پورت 8080 برای پنل، 9200 برای Elasticsearch، 2375 برای Docker daemon بدون TLS. مورد آخر بدترین است: دسترسی به 2375/tcp یعنی اجرای کانتینر دلخواه روی سرور شما با دسترسی root. اگر Docker را تازه راه انداختهاید، راهاندازی داکر روی VPS را بخوانید و سوکت را فقط از طریق TLS یا SSH expose کنید.
چطور بفهمیم چه چیزی واقعاً باز است
از داخل سرور، ss -tulpn لیست listenerها را میدهد. اما این کافی نیست؛ چون فایروال ممکن است جلوی بعضیها را گرفته باشد. تست واقعی از بیرون است:
nmap -sS -Pn -p- --min-rate 2000 203.0.113.10
فلگ -p- هر 65535 پورت را اسکن میکند و --min-rate سرعت را بالا میبرد. اسکن کامل روی یک سرور معمولی بین 30 تا 90 ثانیه طول میکشد. اگر نمیخواهید از بیرون اسکن کنید، حداقل ss -tulpn | grep -v 127.0.0.1 بزنید تا ببینید چه چیزی روی 0.0.0.0 گوش میدهد.
برای فایروال، روی سیستمهای جدید nftables و روی قدیمیترها ufw یا firewalld رایج است. یک قاعده ساده nftables که فقط 22 و 80 و 443 را باز میگذارد:
nft add rule inet filter input tcp dport { 22, 80, 443 } ct state new accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input drop
ترتیب مهم است. اگر قاعده drop را اول بزنید، خودتان هم قطع میشوید. همیشه قبل از اعمال، یک نشست SSH دوم باز نگه دارید.
اینجا اشتباه میکنند
رایجترین اشتباهی که دیدهام این است: کاربر پورت را در فایروال میبندد، خیالش راحت میشود، ولی سرویس همچنان روی 0.0.0.0 گوش میدهد. بعد یک روز فایروال را برای کار دیگری موقتاً خاموش میکند و همان لحظه دیتابیس لخت میشود. نشانهاش هم واضح است: در لاگ MySQL خطهایی مثل Aborted connection ... (Got an error reading communication packets) از IPهای ناشناس، یا در Redis جهش ناگهانی در keyspace_hits بدون ترافیک اپلیکیشن.
اشتباه دوم: باز گذاشتن پورت 22 برای همه و اتکا به رمز. حمله brute-force روی SSH در سرورهای عمومی روزانه هزاران تلاش دارد. PasswordAuthentication no و PermitRootLogin prohibit-password را در sshd_config بگذارید و کلید را جای رمز استفاده کنید.
پورت غیراستاندارد: ارزشش را دارد؟
انتقال SSH به پورت غیرمعمول مثل 2222 یا 49152، حجم اسکنهای خودکار را بهشدت کم میکند. ولی امنیت واقعی نمیآورد؛ فقط نویز را کم میکند. من شخصاً این کار را میکنم، اما بهعنوان لایه دوم، نه جایگزین کلید و فایروال. اگر تیم پشتیبانی یا ابزار مانیتورینگ دارید که به پورت 22 وابسته است، هزینهاش بیشتر از فایده است و همان 22 با محدودسازی IP کافی است.
در مقابل، برای سرویسهای داخلی مثل API بین دو سرور، پورت غیراستاندارد روی شبکه خصوصی ارزش دارد. اگر سرورها در یک شبکه داخلی هستند، کلاً از پورت عمومی استفاده نکنید.
وقتی دسترسی را از دست دادید
بدترین حالت این است که قاعده فایروال را اشتباه اعمال کنید و SSH قطع شود. اگر دسترسی کنسول دارید، از طریق KVM یا کنسول وب وارد شوید و قاعده را برگردانید. اگر ندارید، باید سرور را به حالت rescue ببرید و از بیرون فایلسیستم را mount کنید. مراحلش در بازنصب سرور و کار با حالت rescue آمده. یک قاعده شخصی: قبل از هر تغییر فایروال، nft list ruleset > /root/nft-backup-$(date +%F).txt بگیرید. سی ثانیه وقت میگیرد و یک شب بیخوابی را حذف میکند.
اگر سرور شما روی زیرساخت ابری است، معمولاً یک لایه Security Group هم بالای فایروال سیستمعامل وجود دارد. این دو با هم جمع میشوند، نه جای هم. پورت را در سیستمعامل ببندید و در Security Group هم نبندید، و برعکسش هم. اگر روی سرور ابری کار میکنید، این نکته را در طراحی اولیه لحاظ کنید تا بعداً مجبور نشوید همه قواعد را دوباره بنویسید.
پرسشهای پرتکرار
پورت 8080 برای چیست و آیا باید باز باشد؟
پورت 8080 معمولاً بهعنوان پورت جایگزین HTTP استفاده میشود؛ برای پنلهای مدیریتی، Tomcat، Jenkins و پروکسیهای معکوس. باز بودن آن روی اینترنت تقریباً همیشه اشتباه است. اگر اپلیکیشن روی 8080 گوش میدهد، آن را پشت Nginx روی 443 بگذارید و خود 8080 را فقط روی 127.0.0.1 باز بگذارید.
چطور بفهمم کدام پورتها روی سرورم باز است؟
از داخل سرور با ss -tulpn لیست listenerها را ببینید و از بیرون با nmap -sS -Pn -p- <ip> تأیید کنید. تفاوت این دو خروجی همان چیزی است که فایروال مسدود کرده. فقط به خروجی داخل اعتماد نکنید، چون فایروال ممکن است بعداً خاموش شود.
آیا تغییر پورت SSH امنیت را بیشتر میکند؟
کمی، ولی نه به آن اندازه که تصور میشود. مزیت اصلی کاهش نویز لاگ و اسکنهای خودکار است. امنیت واقعی از غیرفعال کردن ورود با رمز، استفاده از کلید و محدودسازی IP میآید. اگر این سه را دارید، تغییر پورت اختیاری است.
پورت 3306 را بستم ولی MySQL هنوز از بیرون جواب میدهد؛ چرا؟
چون احتمالاً قاعده فایروال در زنجیره اشتباه یا با ترتیب نادرست اعمال شده، یا سرویس روی اینترفیس دیگری bind شده. با ss -tulpn | grep 3306 ببینید آدرس bind چیست. اگر 0.0.0.0:3306 است، فایروال تنها لایه دفاعی شماست و باید bind-address را هم اصلاح کنید.
همین حالا یک بار ss -tulpn بزنید و هر خطی که با 0.0.0.0 یا :: شروع میشود را یادداشت کنید. بعد برای هر کدام یک جمله بنویسید که چرا باید از اینترنت قابل دسترس باشد. آن خطی که جوابش را ندارید، همان پورتی است که امشب باید ببندید.