عیبیابی شبکه در لینوکس: از لایهها تا ابزارها
روش لایهلایه برای وصل نشدن سرویس: لینک، IP، مسیر، DNS، پورت، TLS و فایروال — با فرمانهای استاندارد لینوکس.
بنیانگذار و مهندس محصول

«سایت بالا نمیآید» یک علامت است نه تشخیص. ممکن است DNS بشکند، سرویس listen نکند، فایروال DROP کند، گواهی TLS رد شود، یا فقط از یک مسیر خاص MTU مشکل داشته باشد. عیبیابی خوب فرض را کم و آزمایش را زیاد میکند: هر تست یک لایه را تأیید یا رد میکند.
این راهنما یک ترتیب عملی روی سرور لینوکس میدهد تا بین connection refused، timeout و TLS error سردرگم نمانید.

پاسخ کوتاه
از پایین به بالا بروید: لینک و IP (`ip`) → مسیر و پینگ gateway → رزولوشن نام → گوشدادن سرویس (`ss`) → اتصال به پورت (`nc`/`curl`) → فایروال محلی و ابری → در صورت نیاز capture. پیام خطا را دقیق بخوانید: Connection refused معمولاً یعنی به جایی رسیدید ولی کسی آن پورت را قبول نکرد؛ timeout اغلب فیلتر یا مسیر است.
قبل از باز کردن tcpdump، یک جمله بنویسید: چه چیزی را رد یا تأیید میکنید؟
طبقهبندی خطاهای رایج
| پیام/نشانه | معنی تقریبی | لایهٔ بعدی |
|---|---|---|
| Temporary failure in name resolution | DNS/resolver | dig / resolvectl |
| Connection refused | رسیدن به میزبان؛ پورت بسته/بدون listener | ss -tulpn |
| Connection timed out | فیلتر، مسیر، یا میزبان خاموش | مسیر، SG، ufw |
| No route to host | مسیریابی/فایروال ICMP/unreach | ip route |
| TLS/certificate errors | نام، ساعت، زنجیرهٔ گواهی | curl -v؛ timedatectl |
گام ۱: میزبان و لینک
bash
ip -br link ip -br addr ip route ping -c2 $(ip route | awk '/default/ {print $3}')
اگر لینک DOWN است یا IP ندارید، اپ را دست نزنید. روی ابر، کنسول سریال و وضعیت attachment اینترفیس را هم ببینید. پینگ gateway تأیید میکند حداقل L3 محلی زنده است — اگر ICMP مسدود باشد، شکست پینگ لزوماً یعنی «همه چیز مرده» نیست.
گام ۲: نام یا IP؟
یکبار با IP مستقیم و یکبار با نام تست کنید. اگر IP کار میکند و نام نه، به DNS بروید. اگر هیچکدام نه، DNS را کنار بگذارید.
bash
getent hosts api.example.com dig +short api.example.com A curl -v --connect-timeout 5 https://IP_OR_NAME/ 2>&1 | head -n 40
گام ۳: آیا کسی گوش میدهد؟
bash
ss -tulpn | rg ':443|:80|:22' curl -v telnet://127.0.0.1:8080 nc -vz 127.0.0.1 8080
اول روی خود سرور به localhost وصل شوید. اگر محلی refused است، سرویس بالا نیست یا پورت اشتباه است — فایروال بیرونی بیتقصیر است. اگر محلی OK و از بیرون timeout، فیلتر مسیر یا bind فقط روی lo را بررسی کنید.
گام ۴: فایروال و سیاست ابر
bash
sudo ufw status verbose 2>/dev/null || true sudo nft list ruleset 2>/dev/null | head sudo iptables -L -n 2>/dev/null | head
دو لایه را قاطی نکنید: Security Group / NSG ابر و فایروال سیستمعامل. باز بودن یکی بدون دیگری کافی نیست. قانون «allow SSH قبل از enable» را همیشه رعایت کنید تا قفل نشوید.
گام ۵: مسیر اینترنت و MTU
bash
traceroute -n 1.1.1.1 2>/dev/null || tracepath -n 1.1.1.1 mtr -rwzc 20 1.1.1.1 2>/dev/null || true
از دست رفتن در یک hop میانی همیشه مقصر نیست (بسیاری ICMP را محدود میکنند). الگوی از دست رفتن پایدار نزدیک مقصد یا رفتار وابسته به اندازهٔ بسته به MTU/VPN مشکوک است. برای تشخیص سریع: پینگ با اندازه و DF bit در محیطهای پشتیبانیشده.
گام ۶: HTTP/TLS با جزئیات
bash
curl -vI --connect-timeout 5 https://example.com curl -v --resolve example.com:443:203.0.113.10 https://example.com/
`curl -v` مرحلهٔ DNS، connect، TLS و HTTP را جدا نشان میدهد. `--resolve` اجازه میدهد بدون دست زدن به hosts، یک IP خاص را برای آن نام تست کنید — عالی برای مقایسهٔ origin پشت CDN.
چه وقت tcpdump؟
وقتی لایههای بالا متناقضاند: مثلاً ss میگوید listen، ufw اجازه میدهد، ولی کلاینت timeout میکند. یک capture کوتاه روی اینترفیس درست با فیلتر پورت ببینید آیا SYN میرسد و آیا SYN-ACK برمیگردد. روی تولید با ترافیک زیاد فیلتر دقیق بگذارید و مدت را کوتاه کنید.
bash
# فقط با مجوز و هدف مشخص — نمونهٔ فیلتر پورت # sudo tcpdump -ni eth0 port 443 and host 203.0.113.10
چکلیست ۱۵ دقیقهای حادثه
- ساعت سیستم و گواهی (timedatectl).
- ip/route و پینگ gateway.
- ss روی پورت مورد نظر.
- تست localhost سپس تست ازbastion.
- ufw/nft و پنل Security Group.
- dig و curl -v با ثبت خروجی در تیکت.
اشتباههای رایج
- شروع از تغییر تصادفی فایروال بدون فرضیه.
- تفسیر traceroute بدون فهم سرکوب ICMP.
- فراموش کردن اینکه سرویس روی IPv6 listen میکند و تست فقط IPv4 است یا برعکس.
- باز کردن همهٔ پورتها «موقت» و جا گذاشتن دائمی.
- نداشتن دسترسی console هنگام آزمایش قوانین SSH.
سناریو A: Connection refused از بیرون
از لپتاپ به `IP:8080` میگیرید refused. روی سرور `ss -tulpn` نشان میدهد چیزی روی 8080 نیست — سرویس down است یا پورت در کانفیگ فرق دارد. اگر ss نشان دهد فقط `127.0.0.1:8080`، از بیرون refused یا unreachable خواهید دید مگر از reverse proxy محلی عبور کنید. اصلاح: bind درست یا پراکسی، نه باز کردن بیمحابای فایروال.
سناریو B: Timeout فقط از اینترنت
localhost و حتی ماشین هم VPC وصل میشوند، ولی اینترنت timeout میدهد. احتمالاً Security Group، ACL شبکه، یا UFW ورودی را میبندد. پینگ ممکن است همچنان کار کند اگر ICMP جدا اجازه داده شده. تست از bastion داخل همان SG و مقایسه با تست خانه، مرز مشکل را روشن میکند.
سناریو C: TLS handshake شکست
TCP برقرار میشود (curl به مرحلهٔ SSL میرسد) ولی گواهی نامعتبر است: ساعت سیستم، نام ناسازگار با SAN، یا زنجیرهٔ ناقص. `timedatectl` و `openssl s_client -connect host:443 -servername host` ابزارهای مکمل curl هستند. این دیگر «شبکهٔ لایه ۳» نیست؛ ولی در عمل در صف تیکت شبکه میآید و باید سریع جدا شود.
bash
timedatectl echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates -subject
ثبت شواهد برای تیکت
خروجی دقیق `curl -v`، `ss`، `ufw status`، و یک timestamp با timezone ثابت، زمان متوسط رفع را کم میکند. از گزارش «کار نمیکند» بدون این چهار قطعه خودداری کنید.
الگوی فرضیه و آزمایش
یک فرضیهٔ بد: «پس فایروال را خاموش کنیم.» یک فرضیهٔ خوب: «اگر SG پورت ۴۴۳ را میبندد، تست از bastion داخل همان SG باید موفق و از خانه timeout باشد.» فرضیهٔ خوب آزمایش دارد و محدوده را کم میکند. هر آزمایش باید یک متغیر را عوض کند؛ همزمان باز کردن همهٔ پورتها و restart همهٔ سرویسها به شما نمیگوید چه چیزی درستش کرد.
زمانبندی هم بخشی از تشخیص است. اگر فقط در ساعت اوج fail میشود، به ظرفیت و rate limit فکر کنید نه به «DNS گاهی کار نمیکند» بدون داده. نمودار نرخ خطا کنار traceroute در همان پنجرهٔ زمانی ارزش بیشتری از دهها فرمان پراکنده دارد.
در تیمهای توزیعشده، از کلاینتهای مختلف (شبکهٔ خانگی، دفتر، موبایل) تست بگیرید تا مشکل را به ISP خاص یا IPv6 خاص وصل کنید. یک شکست از یک شبکه بهمعنی down بودن جهانی نیست.
اگر سرویس پشت load balancer است، عیبیابی را به سه بخش تقسیم کنید: کلاینت تا LB، LB تا backend، و خود backend روی localhost. بدون این تقسیم، لاگها با هم حرف نمیزنند و انگشتها به سمت اشتباه اشاره میکنند.
مرز بین شبکه و اپلیکیشن
اگر TCP و TLS سالماند و HTTP=500 میگیرید، مشکل دیگر در دامنهٔ این مقاله نیست — به لاگ اپ بروید. اگر TCP برقرار نمیشود، اپ را برای ساعتها debug نکنید. این مرز ساده بیشترین زمان را در تیمهای مختلط ذخیره میکند. توافق کنید که «شبکه» یعنی تا برقراری نشست و ترجیحاً پاسخ لایهٔ کاربرد پایه؛ منطق کسبوکار داخل 500 شبکه نیست.
برای APIهای خارجی، علاوه بر ابزارهای میزبان، وضعیت وضعیتصفحهٔ فروشنده و مسیر DNS آنها را هم در نظر بگیرید. گاهی همهٔ فرمانهای محلی سبزند و مشکل سمت مقابل است. داشتن کانال وضعیت و timeoutهای معقول در کلاینت بخشی از عیبیابی پیشگیرانه است.
در پایان هر حادثهٔ شبکهای، یک خط به Runbook اضافه کنید: نشانه، لایهٔ شکست، فرمان طلایی. Runbook زنده جلوی تکرار فرمانهای تصادفی را میگیرد.
و اگر دیدید یک کلاس مشکل هر ماه تکرار میشود — مثلاً SG جاافتاده بعد از ساخت محیط جدید — بهجای قهرمانی در عیبیابی، قالب ساخت محیط را درست کنید.
جمعبندی on-call شبکه
پیام خطا را ترجمه کنید، لایه را انتخاب کنید، یک فرضیه بسازید، یک تست بزنید، شاهد را ذخیره کنید. اگر بعد از سه تست هنوز تصویر ندارید، دامنه را عوض کنید نه اینکه همان ping را صدبار تکرار کنید. تکرار بدون تغییر متغیر، روش نیست.
همیشه مسیر مدیریتی جایگزین (console، bastion) را قبل از آزمایشهای فیلتر SSH محکم کنید. بهترین تشخیص دنیا اگر خودتان را بیرون قفل کند شکست است.
بعد از رفع، یک خط Runbook و در صورت تکرار، یک اصلاح قالب. عیبیابی قهرمانانه در برابر حادثهٔ تکراری، بدهی عملیاتی است نه افتخار.
ابزارهای مکمل بدون گمشدن
`mtr` برای دیدن مسیر و از دست رفتن در زمان، `tcpdump` برای اثبات رسیدن بسته، `nmap` فقط در محدودهٔ مجاز برای دیدن پورتهای باز خودتان، و متریکهای LB برای دیدن سلامت backend. هیچکدام جای ترتیب لایهلایه را نمیگیرند. ابزار را وقتی بیاورید که فرضیه دارید؛ نه بهعنوان اولین واکنش.
در سازمانها، اسکن و capture ممکن است سیاست داشته باشد. قبل از اجرا روی شبکهٔ مشترک، محدوده و مجوز را روشن کنید. عیبیابی خوب، بیانضباطی امنیتی نیست.
خروجی ابزار مکمل را کوتاه و با توضیح فرضیه بایگانی کنید تا نفر بعدی همان مسیر را از صفر کشف نکند.
یک تمرین مفید ماهانه: روی staging عمداً یک پورت را در UFW ببندید و از اعضای تیم بخواهید با روش لایهلایه علت را پیدا کنند. ماهیچهٔ تشخیص فقط با خواندن ساخته نمیشود؛ با تکرار هدایتشده ساخته میشود.
خلاصه
عیبیابی شبکه یعنی جدا کردن DNS، مسیر، listener، سیاست فیلتر و TLS با تستهای کوچک و قابلتکرار. پیام خطا را جدی بگیرید، از پایین به بالا بیایید، و هر لایه را یکبار ثابت کنید. آنگاه راهحل معمولاً آشکار است.
سوالات متداول
تفاوت timeout و refused؟
refused معمولاً پاسخ فعال «بسته» از پشتهٔ مقصد است؛ timeout یعنی در زمان معقول پاسخی برای برقراری اتصال نیامده (اغلب DROP یا فقدان مسیر).
آیا غیرفعال کردن ufw برای تست خوب است؟
فقط در بازهٔ بسیار کوتاه، با دسترسی جایگزین، و روی سیستم غیرحساس. بهتر است قانون مشخص allow را موقتاً اضافه و بعد حذف کنید.
از کانتینر وصل نمیشود ولی میزبان میشود؟
شبکهٔ bridge/CNI، DNS داخل کانتینر، و publish پورت را جدا از شبکهٔ میزبان عیبیابی کنید.
منابع و مراجع
- curl(1) manual: https://curl.se/docs/manpage.html
- ss(8): https://man7.org/linux/man-pages/man8/ss.8.html
- ping(8): https://man7.org/linux/man-pages/man8/ping.8.html
- Ubuntu Server — Firewalls (ufw): https://documentation.ubuntu.com/server/how-to/security/firewalls/
- tcpdump man page / Wireshark university materials for packet analysis basics
نویسنده
سهیل ابراهیمپور بنیانگذار FutureForge است. روی طراحی محصول، معماری و استقرار نرمافزار سفارشی کار میکند.
یادداشتهای مرتبط
اگر در انتخاب معماری یا مسیر توسعه مطمئن نیستید، میتوانید درباره پروژه صحبت کنیم.
مسئله و محدودیت را بنویسید. اگر تطابق داشته باشیم، برای گفتگو هماهنگ میکنیم.




