ERR_CONNECTION_REFUSED یا ERR_TIMED_OUT؟ تشخیص روی سرور
ERR_CONNECTION_REFUSED یعنی کسی جواب رد فرستاد، از سرور یا فایروالی در مسیر. ERR_TIMED_OUT یعنی یک مرحله به مهلت رسید. با curl و ss و tcpdump لایهٔ مقصر را روی VPS پیدا کنید.
خطای ERR_CONNECTION_REFUSED و ERR_TIMED_OUT دقیقاً چه میگویند؟
ERR_CONNECTION_REFUSED با کد -102 یعنی تلاش مرورگر برای اتصال با جواب رد روبهرو شد. چیزی فوراً اعلام کرد که این اتصال پذیرفته نمیشود. آن چیز ممکن است خود سرور باشد که روی این پورت برنامهای ندارد، یا فایروالی در مسیر که ترافیک ردشده را با بستهٔ TCP RST جواب میدهد. ERR_TIMED_OUT با کد -7 یعنی یک عملیات به مهلت خود رسید، و خود کد نمیگوید کدام عملیات. پس اولی یعنی «کسی جواب رد داد» و دومی یعنی «چیزی در زمان مقرر تمام نشد». جای گشتن در این دو حالت کاملاً فرق دارد.
فرض این راهنما این است که شما صاحب سرور هستید. پنلی مثل n8n، wg-easy یا Webmin را روی VPS خودتان بالا آوردهاید، یا یک سایت را روی آن گذاشتهاید. بعد آدرس را در Chrome، Edge، یک برنامهٔ Electron یا پیشنمایش داخل IDE باز کردهاید و صفحهٔ خطا با یکی از این دو کد آمده است. فهرست آشنای «کش را پاک کنید و مودم را خاموش و روشن کنید» اینجا نیست. اینجا از سمت سرور تشخیص میدهیم که کدام لایه جواب داد و کدام لایه ساکت ماند.
این کدها از کجا میآیند؟
مرورگرهای مبتنی بر Chromium خطاهای شبکه را در یک فایل تعریف میکنند: net/base/net_error_list.h در مخزن Chromium. ما این فایل را در شاخهٔ main در تاریخ 2026-10-18 خواندیم. توضیح هر کد، با جملهٔ خود فایل، این است:
-102با نامCONNECTION_REFUSED: «A connection attempt was refused.» یعنی تلاش برای اتصال رد شد.-7با نامTIMED_OUT: «An operation timed out.» یعنی یک عملیات به مهلت خود رسید.-118با نامCONNECTION_TIMED_OUT: «A connection attempt timed out.» یعنی خود تلاش برای اتصال به مهلت رسید.-101با نامCONNECTION_RESET: اتصال قطع شد. توضیح فایل میگوید این حالت با یک TCP RST متناظر است.-105با نامNAME_NOT_RESOLVED: نام دامنه به هیچ IP ترجمه نشد.-130با نامPROXY_CONNECTION_FAILED: مرورگر نتوانست به سرور پراکسی وصل شود، یا در پیدا کردن نام آن یا در باز کردن سوکت به آن. طبق همان توضیح، خطاهای مرحلهٔCONNECTپراکسی HTTP جزو این کد نیستند.
صفحهٔ خطای مرورگر همین نامها را با پیشوند ERR_ نشان میدهد. اگر -105 گرفتید، درخواست هنوز به سرور نرسیده است و باید DNS را درست کنید. اگر -130 گرفتید، مرورگر یا سیستم شما از پراکسی استفاده میکند و اول باید همان پراکسی را بررسی کنید.
چرا -7 با -118 یکی نیست؟
بسیاری از راهنماها این دو را یکی حساب میکنند. فایل Chromium این کار را نمیکند. توضیح -118 صریحاً دربارهٔ «تلاش برای اتصال» است. توضیح -7 فقط میگوید «یک عملیات» به مهلت رسید و نمیگوید کدام عملیات. بنابراین -7 بهتنهایی به شما نمیگوید درخواست در کدام مرحله گیر کرد. ممکن است مرحلهٔ اتصال باشد، ممکن است مرحلهٔ بعد از آن. این راهنما ادعا نمیکند کدام وضعیت شبکه دقیقاً -7 میسازد. بهجای حدس زدن، پایینتر یاد میگیرید مرحله را با curl -v خودتان پیدا کنید.
«رد شد» یعنی چه؟ کسی جواب رد فرستاد
وقتی -102 میگیرید، میدانید چیزی جواب رد فرستاد. سؤال درست این است که آن چیز کجا است و چرا گفت «اینجا خبری نیست». جواب رد همیشه از خود سرور نمیآید. Fortinet مستند کرده که فایروال FortiGate بهطور پیشفرض برای ترافیکی که با یک سیاست deny جور شود، بهجای دور انداختن بیصدای بسته، بستهٔ TCP RST میفرستد و نتیجه «connection refused» است. پس فایروالی در مسیر هم میتواند -102 بسازد، بدون این که بسته به IP سرور برسد. وقتی جواب رد از خود سرور میآید، چهار علت رایج دارد:
- هیچ برنامهای روی آن پورت گوش نمیدهد. سرویس از کار افتاده، هنوز بالا نیامده، یا روی پورت دیگری اجرا میشود.
- برنامه فقط روی
127.0.0.1گوش میدهد. در این حالت برنامه سالم است وcurlروی خود سرور جواب میگیرد، اما از بیرون کسی به آن آدرس دسترسی ندارد. - پورت کانتینر هرگز منتشر نشده است. کانتینر داخل Docker گوش میدهد، اما روی خود میزبان هیچ پورتی برای آن باز نشده. پس از نگاه بیرون همان حالت اول است.
- یک قانون فایروال از نوع reject. فایروال، روی خود سرور یا جایی در مسیر، عمداً به فرستنده خبر میدهد که ترافیک رد شد.
یک استثنای مهم هم هست. اگر DNS دامنه به IP اشتباه اشاره کند، مثلاً به سرور قدیمیتان، جواب رد ممکن است از ماشین دیگری بیاید. پس -102 ثابت نمیکند جوابدهنده سرور شما است، یا حتی این که روی آن IP قرار دارد. برای فهمیدن این که جواب رد از کجا آمد، هنگام درخواست tcpdump را روی سرور اجرا کنید که پایینتر توضیح داده شده است. اگر هیچ بستهای به سرور نمیرسد ولی مرورگر باز هم -102 میدهد، جواب رد از جایی قبل از سرور آمده است. بخش DNS را هم پایینتر ببینید.
سکوت یعنی چه؟ بسته رفت و جوابی برنگشت
در حالت تایماوت، یک مرحله از درخواست در مهلت خود تمام نشد. اگر آن مرحله اتصال TCP باشد، معمولاً یعنی مرورگر بسته فرستاد و هیچ لایهای جواب نداد، نه جواب مثبت و نه جواب رد. اگر مرحلهٔ بعد از اتصال باشد، ارتباط برقرار شده ولی پاسخ بهموقع نیامده است. علتهای رایج اینها هستند:
- فایروال شبکهٔ ارائهدهنده. بسیاری از ارائهدهندهها جدا از فایروال داخل سیستمعامل، یک فایروال در پنل خود دارند. این که آن فایروال بسته را بیصدا دور میاندازد یا رد میکند، به ارائهدهنده بستگی دارد. قانونهای آن را در پنل خودتان نگاه کنید.
- قانون deny در ufw. طبق صفحهٔ راهنمای ufw،
denyترافیک را بیصدا نادیده میگیرد. - IP اشتباه در DNS. دامنه به آدرسی اشاره میکند که اصلاً جواب نمیدهد.
- مسیری که بستهها را دور میاندازد. جایی بین شما و سرور، ترافیک متوقف میشود.
- برنامه اتصال را میپذیرد ولی جواب نمیدهد. این درخواست از مرحلهٔ اتصال گذشته و در مرحلهٔ انتظار برای پاسخ گیر کرده است. به همین دلیل پیدا کردن مرحله اینقدر مهم است.
کدام مرحله گیر کرد؟ با curl -v از بیرون سرور
یک درخواست HTTPS سه مرحلهٔ جدا دارد: اتصال TCP، دستدادن TLS (رمزنگاری لایهٔ انتقال)، و انتظار برای پاسخ HTTP. curl -v نشان میدهد درخواست تا کدام مرحله جلو رفت. این دستور را روی رایانهٔ خودتان یا روی یک سرور دیگر اجرا کنید، نه روی همان سروری که مشکل دارد:
curl -v --connect-timeout 10 --max-time 30 https://panel.example.com/
echo $?اگر پنل روی یک پورت خاص است، همان را با IP مستقیم هم امتحان کنید تا DNS از معادله بیرون برود:
curl -v --connect-timeout 10 --max-time 30 http://203.0.113.10:8080/
echo $?طبق صفحهٔ راهنمای curl، --connect-timeout فقط مرحلهٔ اتصال را محدود میکند. این مرحله وقتی تمامشده حساب میشود که پیدا کردن DNS و دستدادنهای TCP و TLS انجام شده باشد. --max-time کل درخواست را محدود میکند. در خروجی -v هر خط یک پیشوند دارد. خطهایی که با * شروع میشوند توضیح خود curl هستند. خطهای > هدرهایی هستند که curl فرستاد. خطهای < هدرهایی هستند که curl دریافت کرد. حالا خروجی را اینطور بخوانید:
- اگر در خطهای
*نشانهای از برقرار شدن اتصال نیست و دستور بعد از ده ثانیه تمام میشود، مرحلهٔ TCP ساکت مانده است. سراغ فایروالها، DNS و مسیر شبکه بروید. - اگر اتصال برقرار شده ولی دستدادن TLS کامل نمیشود، چیزی روی پورت گوش میدهد اما TLS را با شما تمام نمیکند. سرویس پشت آن پورت و تنظیم گواهی آن را بررسی کنید.
- اگر خطهای
>را میبینید ولی هیچ خط<نمیآید، درخواست به سرور رسید و برنامه جواب نداد. مشکل در خود برنامه است، نه در شبکه. لاگ آن را بخوانید. - اگر خطهای
<آمدند، سرور جواب داده است. کد وضعیت HTTP را بخوانید.
echo $? کد خروج curl را چاپ میکند. طبق صفحهٔ راهنمای curl، کد 7 یعنی «Failed to connect to host.»، کد 28 یعنی مهلت عملیات تمام شد، و کد 6 یعنی نام میزبان پیدا نشد. کد 6 وضعیتی شبیه -105 مرورگر است.
تله: کد خروج 7 در curl هیچ ربطی به -7 در Chromium ندارد. این دو، دو سیستم شمارهگذاری جدا هستند. -7 مرورگر دربارهٔ مهلت است و 7 در curl دربارهٔ ناتوانی در اتصال. هر بار که عدد 7 دیدید، اول بپرسید این عدد را کدام برنامه چاپ کرده است.
یک آزمایش جفتی هم خیلی کمک میکند. همان آدرس را روی خود سرور با curl -v http://127.0.0.1:8080/ باز کنید. اگر آنجا جواب میگیرید و از بیرون نه، برنامه سالم است. مشکل در لایهای بین برنامه و بیرون است: آدرسی که برنامه روی آن گوش میدهد، فایروال، یا شبکه.
در ویندوز: Test-NetConnection
اگر روی ویندوز هستید و curl در دسترس ندارید، PowerShell ابزار Test-NetConnection را دارد. طبق مستندات Microsoft، این cmdlet آزمون ping، آزمون TCP، ردیابی مسیر و بررسی انتخاب مسیر را پشتیبانی میکند. با -Port اتصال TCP به آن پورت را روی رایانهٔ مقصد آزمایش میکند:
Test-NetConnection -ComputerName panel.example.com -Port 443در خروجی فیلد TcpTestSucceeded را بخوانید. این ابزار فقط مرحلهٔ اول یعنی TCP را میسنجد. اگر TCP موفق بود و مرورگر هنوز تایماوت میدهد، گیر در مرحلهٔ TLS یا پاسخ برنامه است. برای دیدن آن به curl -v نیاز دارید.
روی خود سرور: چه کسی روی پورت گوش میدهد؟
برای حالت «رد شد»، اولین دستور روی سرور این است:
sudo ss -ltnp
sudo ss -ltnp | grep ':8080'طبق صفحهٔ راهنمای ss، گزینهٔ -l فقط سوکتهای در حال گوش دادن را نشان میدهد، -t فقط TCP را، -n اسم سرویسها را ترجمه نمیکند و -p پردازهای را که از سوکت استفاده میکند نشان میدهد. ستونی که باید بخوانید ستون آدرس محلی است، یعنی Local Address:Port. اگر آنجا 0.0.0.0 میبینید، برنامه روی همهٔ آدرسهای IPv4 سرور گوش میدهد. اگر 127.0.0.1 میبینید، برنامه فقط از داخل خود سرور در دسترس است. از بیرون معمولاً جواب رد میگیرید، اما اگر فایروالی بستههای آن پورت را بیصدا دور بیندازد، بهجای آن تایماوت میبینید. صفحهٔ راهنمای iptables دربارهٔ هدف DROP میگوید بسته «روی زمین انداخته میشود». اگر هیچ خطی برای آن پورت نیست، هیچ برنامهای گوش نمیدهد. وضعیت سرویس را با systemctl status و لاگ آن را با journalctl -u بررسی کنید.
برای برنامهای که روی 127.0.0.1 گوش میدهد دو راه دارید. راه اول تغییر آدرس گوش دادن در تنظیمات خود برنامه است. این تنظیم در هر برنامه اسم متفاوتی دارد، پس مستندات همان برنامه را بخوانید. راه دوم برای پنلهای مدیریتی معمولاً بهتر است: برنامه را روی 127.0.0.1 نگه دارید و یک وبسرور جلوی آن بگذارید. تنظیم nginx بهعنوان reverse proxy دقیقاً همین کار را انجام میدهد. در این حالت مرورگر به nginx وصل میشود. پس اگر برنامهٔ پشت آن خاموش باشد، صفحهای از خود nginx میبینید و نه -102. برای روشهای بیشتر بررسی پورت از داخل و بیرون، راهنمای بررسی باز بودن پورت در لینوکس را ببینید.
کانتینرهای Docker: دو تلهٔ جدا
اگر پنل در Docker اجرا میشود، اول ستون PORTS را در خروجی docker ps نگاه کنید، و بعد همان پورت را در ss روی میزبان پیدا کنید:
docker ps
sudo ss -ltnpاگر برای کانتینر هیچ پورتی در ستون PORTS منتشر نشده، روی میزبان چیزی برای آن پورت گوش نمیدهد. مستندات Docker هم میگوید Docker بهطور پیشفرض دسترسی به پورتهایی را که منتشر نشدهاند میبندد. اگر پورت را روی 127.0.0.1 منتشر کردهاید، طبق همان مستندات فقط خود میزبان Docker به آن دسترسی دارد. همان مستندات هشدار میدهد که در نسخههای قدیمیتر از 28.0.0، میزبانهای داخل همان بخش لایهٔ ۲ شبکه، مثلاً دستگاههایی که به همان سوییچ وصلاند، میتوانند به پورتهای منتشرشده روی localhost برسند. پس نسخهٔ Docker خود را با docker version ببینید. این ترکیب برای پنلی که پشت nginx است درست است، ولی از بیرون جواب نمیگیرید.
تلهٔ دوم برعکس است. طبق مستندات Docker، پورتی که بدون آدرس میزبان منتشر شود روی همهٔ آدرسهای میزبان منتشر میشود. Docker ترافیک کانتینر را در جدول nat مسیریابی میکند. پس بستهها قبل از رسیدن به زنجیرههای INPUT و OUTPUT که ufw از آنها استفاده میکند، به مسیر دیگری میروند. نتیجه این است که پورت منتشرشدهٔ Docker از قانونهای ufw عبور میکند. پس اگر ufw status میگوید پورت بسته است ولی پنل از بیرون باز میشود، علت همین است. توضیح کامل و راهحلها در عبور پورتهای Docker از ufw آمده است.
فایروال: deny سکوت میسازد و reject جواب
صفحهٔ راهنمای ufw در Ubuntu 24.04 فرق این دو را اینطور میگوید: گاهی بهتر است به فرستنده خبر بدهید که ترافیکش رد شد، بهجای این که فقط آن را نادیده بگیرید. در این حالت بهجای deny از reject استفاده کنید. یعنی یک پورت بسته، بسته به نوع قانون، میتواند در مرورگر به شکل رد شدن یا به شکل تایماوت دیده شود. قانونها و سیاست پیشفرض را اینطور ببینید:
sudo ufw status verboseاگر پورت لازم بسته است، آن را باز کنید و دوباره از بیرون با curl -v امتحان کنید:
sudo ufw allow 443/tcpمبانی کار با ufw و ترتیب قانونها در راهنمای پایهٔ ufw روی VPS آمده است. اگر سرور و دامنهٔ شما IPv6 هم دارند، باز کردن پورت برای IPv6 در ufw را هم بخوانید.
برای حالت سکوت، و همینطور برای فهمیدن این که جواب رد از خود سرور آمده یا از مسیر، باید بفهمید بسته اصلاً به سرور میرسد یا نه. این دستور را روی سرور اجرا کنید و همزمان از بیرون curl -v بزنید:
sudo tcpdump -ni any tcp port 443اگر هیچ بستهای نمیبینید، ترافیک قبل از رسیدن به سرور متوقف میشود. علت در فایروال پنل ارائهدهنده، DNS یا مسیر شبکه است، و تغییر تنظیمات داخل سرور کمکی نمیکند. اگر بستهها را میبینید، به سرور میرسند و مشکل داخل سرور است: یک قانون deny در ufw، یا برنامهای که جواب نمیدهد.
DNS: آیا دامنه به همین سرور اشاره میکند؟
قبل از هر تغییری در فایروال، مطمئن شوید دامنه به IP درست اشاره میکند. اولی را روی رایانهٔ خودتان و دومی را روی سرور اجرا کنید و نتیجه را مقایسه کنید:
dig +short A panel.example.com
hostname -Iخروجی dig آدرسی است که دامنه به آن اشاره میکند. خروجی hostname -I آدرسهای خود سرور است. اگر این دو یکی نیستند، هر خطایی که مرورگر نشان میدهد دربارهٔ ماشین دیگری است. یک رکورد قدیمی که به سرور قبلی اشاره میکند میتواند -102 بسازد، و یک IP مرده میتواند تایماوت بسازد. در ویندوز بهجای dig از nslookup panel.example.com استفاده کنید.
اگر از داخل ایران تایماوت میگیرید ولی از بیرون باز میشود
اگر همان آدرس از داخل ایران تایماوت میدهد ولی از یک سرور یا سرویس بررسی خارج از ایران باز میشود، مشکل در مسیر شبکه است، نه در سرور شما. دلیلش ساده است: سرور به یک نقطه جواب میدهد و به نقطهٔ دیگر نه، پس خود سرور بخش خراب نیست. تغییر تنظیمات nginx، باز کردن پورت در ufw یا نصب دوبارهٔ برنامه این مشکل را حل نمیکند، چون هیچکدام مسیر بین شما و سرور را عوض نمیکند.
برای اثبات، curl -v را از هر دو نقطه اجرا کنید و خروجیها را نگه دارید. اگر tcpdump روی سرور هنگام درخواست از داخل ایران هیچ بستهای نشان نمیدهد ولی هنگام درخواست از بیرون بستهها را نشان میدهد، تشخیص کامل است. این شواهد را میتوانید برای پشتیبانی ارائهدهندهٔ سرور بفرستید.
ترتیب پیشنهادی تشخیص
- با
digمطمئن شوید دامنه به IP همین سرور اشاره میکند. - از بیرون سرور
curl -vبزنید و مرحلهٔ گیرکرده و کد خروج را یادداشت کنید. - اگر رد شد: روی سرور
ss -ltnpرا بخوانید، ستونPORTSدرdocker psرا ببینید، و دنبال قانونهایrejectروی سرور و در فایروالهای مسیر بگردید. اگرtcpdumpهیچ بستهای روی سرور نشان نمیدهد، جواب رد از قبل از سرور آمده است. - اگر سکوت بود: هنگام درخواست،
tcpdumpرا روی سرور اجرا کنید. اگر بستهای نمیرسد، فایروال پنل ارائهدهنده و مسیر شبکه را بررسی کنید. اگر میرسد،ufw status verboseرا بخوانید. - اگر درخواست فرستاده شد ولی پاسخی نیامد: لاگ برنامه را با
journalctl -uیاdocker logsبخوانید.
این راهنما دربارهٔ وب و پنلها است. اگر همین دو حالت را در SSH و پورت 22 میبینید، راهنمای Connection refused و Connection timed out در SSH همان منطق را برای SSH توضیح میدهد.
FAQ
آیا ERR_CONNECTION_REFUSED یعنی سرور من خاموش است؟
نه لزوماً، ولی -102 هم ثابت نمیکند سرور روشن است. این کد یعنی چیزی تلاش برای اتصال را رد کرد. آن چیز ممکن است خود سرور باشد، یا فایروالی در مسیر که برای ترافیک ردشده بستهٔ TCP RST میفرستد. اگر جواب از خود سرور آمده باشد، علت معمولاً یکی از اینها است: هیچ برنامهای روی آن پورت گوش نمیدهد، برنامه فقط روی 127.0.0.1 گوش میدهد، پورت کانتینر Docker منتشر نشده، یا یک قانون reject در فایروال هست. اگر DNS به IP اشتباه اشاره کند، این جواب ممکن است از ماشین دیگری آمده باشد. پس اول خروجی dig را با IP سرور مقایسه کنید، و هنگام درخواست با tcpdump ببینید بسته اصلاً به سرور میرسد یا نه.
فرق ERR_TIMED_OUT با کد -7 و ERR_CONNECTION_TIMED_OUT با کد -118 چیست؟
در فایل net_error_list.h مرورگر Chromium، کد -118 با توضیح «A connection attempt timed out» دربارهٔ تلاش برای اتصال است. کد -7 با توضیح «An operation timed out» عمومی است و نمیگوید کدام عملیات به مهلت رسید. پس -7 بهتنهایی مرحلهٔ گیرکرده را مشخص نمیکند. با curl -v از بیرون سرور ببینید درخواست در اتصال TCP، دستدادن TLS یا انتظار برای پاسخ متوقف شد.
آیا کد خروج 7 در curl همان خطای -7 مرورگر است؟
نه. این دو، دو سیستم شمارهگذاری جدا هستند. در curl، کد خروج 7 طبق صفحهٔ راهنمای آن یعنی «Failed to connect to host» و کد 28 یعنی مهلت عملیات تمام شد. در Chromium، -7 یعنی TIMED_OUT. شباهت عدد اتفاقی است، پس همیشه ببینید عدد را کدام برنامه چاپ کرده است.
سایتم از داخل ایران باز نمیشود ولی از بیرون باز میشود. مشکل از سرور است؟
نه. اگر همان آدرس از یک نقطهٔ بیرونی جواب میدهد، سرور سالم است و مشکل در مسیر شبکه بین شما و سرور است. تغییر تنظیمات وبسرور یا فایروال سرور این را درست نمیکند. با curl -v از هر دو نقطه و tcpdump روی سرور میتوانید نشان دهید بستههای کدام مسیر به سرور نمیرسند. این شواهد را برای پشتیبانی ارائهدهنده بفرستید.
پنل روی خود سرور با curl باز میشود ولی مرورگر من ERR_CONNECTION_REFUSED میدهد. چرا؟
به احتمال زیاد برنامه فقط روی 127.0.0.1 گوش میدهد، یا پورت کانتینر Docker فقط روی 127.0.0.1 منتشر شده است. ستون آدرس محلی را در sudo ss -ltnp بخوانید: 127.0.0.1 یعنی فقط خود سرور به آن دسترسی دارد و 0.0.0.0 یعنی همهٔ آدرسهای IPv4. برای پنلهای مدیریتی بهتر است برنامه روی 127.0.0.1 بماند و nginx بهعنوان reverse proxy جلوی آن قرار بگیرد.