رفع مشکل

خطای Connection refused؛ چرا سرور اتصال را رد می‌کند و چطور رفعش کنیم

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۷ دقیقه

ERRConnectionrefusedرفع مشکلخطای Connectionrefused؛ چرا سرور اتصال رارد می‌کند و چطور رفعش کنیممجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

Connection refused یعنی بسته به سرور رسیده اما روی آن پورت هیچ برنامه‌ای گوش نمی‌دهد یا فایروال با پیام رد (REJECT) پاسخ داده است. برخلاف timeout، مسیر شبکه سالم است. ابتدا با systemctl status ببینید سرویس اجرا می‌شود، با ss -tlnp بررسی کنید روی کدام آدرس و پورت گوش می‌دهد (127.0.0.1 یا 0.0.0.0) و سپس فایروال و پورت‌های داکر را کنترل کنید.

Connection refused دقیقاً یعنی چه؟

وقتی برنامه‌ای (مرورگر، کلاینت SSH، برنامهٔ اتصال به دیتابیس یا curl) می‌خواهد به یک پورت روی سرور وصل شود، ابتدا بستهٔ شروع اتصال TCP را می‌فرستد. سه حالت ممکن است پیش بیاید:

  1. برنامه‌ای روی آن پورت گوش می‌دهد و اتصال برقرار می‌شود.
  2. هیچ پاسخی برنمی‌گردد؛ بسته در مسیر گم شده یا فایروالی آن را بی‌صدا دور ریخته است. نتیجه: Connection timed out.
  3. سیستم‌عامل سرور فوراً پاسخ «رد» می‌دهد، چون هیچ برنامه‌ای روی آن پورت نیست، یا فایروال صریحاً رد کرده است. نتیجه: Connection refused.

پس خبر خوب این است که در حالت refused، سرور روشن است و مسیر شبکه تا آن کار می‌کند. مشکل تقریباً همیشه روی خود سرور و در سطح سرویس یا تنظیمات است. این تمایز وقت زیادی صرفه‌جویی می‌کند؛ اگر خطای شما timeout است، مقالهٔ رفع خطای Connection timed out در SSH مناسب‌تر است.

refused یا timeout؟
Connection refused
  • پاسخ فوری از سرور
  • سرور روشن و مسیر شبکه سالم
  • سرویسی روی پورت نیست یا REJECT
  • بررسی: systemctl، ss و bind
در برابر
Connection timed out
  • هیچ پاسخی نمی‌رسد
  • فایروال DROP، سرور خاموش یا مسیر مشکل‌دار
  • معمولاً بیرون از سرویس
  • بررسی: فایروال، ping، mtr
شکل ۱ نوع خطا مشخص می‌کند عیب‌یابی را از کجا شروع کنید.

گام ۱: سرویس اجرا می‌شود؟

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

sudo systemctl status nginx
sudo systemctl status ssh          # در AlmaLinux و Rocky: sshd
sudo systemctl status mysql        # یا mariadb یا postgresql
docker ps -a                       # برای سرویس‌های داخل کانتینر

اگر وضعیت inactive یا failed است، لاگ را بخوانید تا علت را بفهمید و سپس اجرا کنید:

sudo journalctl -u nginx -n 50 --no-pager
sudo systemctl start nginx
sudo systemctl enable nginx     # برای اجرای خودکار پس از ری‌استارت

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

گام ۲: روی کدام آدرس و پورت گوش می‌دهد؟

سرویسی که اجرا می‌شود ممکن است روی پورت یا آدرسی غیر از آنچه انتظار دارید گوش دهد. فهرست پورت‌های باز را ببینید:

sudo ss -tlnp

در ستون Local Address:Port سه حالت مهم وجود دارد:

آدرس معنی
0.0.0.0:80 یا *:80 روی همهٔ آدرس‌های IPv4 در دسترس است
[::]:80 روی IPv6 (و معمولاً IPv4) در دسترس است
127.0.0.1:3306 فقط از داخل خود سرور در دسترس است

حالت سوم دلیل بسیار رایج refused هنگام اتصال از بیرون است. برای نمونه، MySQL و PostgreSQL و Redis به‌طور پیش‌فرض فقط روی localhost گوش می‌دهند و این برای امنیت عمداً چنین است. اگر واقعاً نیاز به اتصال از بیرون دارید، در فایل تنظیمات سرویس آدرس bind را تغییر دهید (مثلاً bind-address در MySQL یا listen_addresses در PostgreSQL) و حتماً دسترسی را با فایروال فقط به آی‌پی‌های مشخص محدود کنید.

اگر پورتی که انتظار دارید در فهرست نیست، برنامه روی پورت دیگری تنظیم شده است. مثلاً پس از تغییر پورت SSH، اتصال به پورت ۲۲ refused می‌شود؛ باید با ssh -p پورت جدید را بدهید.

root@server: ~
$ ss -tlnp | grep -E ':22|:80|:3306'LISTEN 0 128      0.0.0.0:22     0.0.0.0:*  users:(("sshd",...))LISTEN 0 511      0.0.0.0:80     0.0.0.0:*  users:(("nginx",...))LISTEN 0 151    127.0.0.1:3306   0.0.0.0:*  users:(("mysqld",...))$ 
شکل ۲ SSH و Nginx روی همهٔ آدرس‌ها گوش می‌دهند، اما MySQL فقط روی localhost است؛ اتصال از بیرون به آن refused می‌شود.

گام ۳: از داخل سرور تست کنید

برای جدا کردن مشکل سرویس از مشکل شبکه یا فایروال، اتصال را از خود سرور امتحان کنید:

curl -I http://127.0.0.1
nc -vz 127.0.0.1 22
  • اگر از داخل سرور هم refused است، مشکل قطعاً در خود سرویس است (گام ۱ و ۲).
  • اگر از داخل کار می‌کند ولی از بیرون refused است، یا سرویس فقط روی localhost است یا فایروال با REJECT پاسخ می‌دهد.

گام ۴: فایروال

فایروال‌ها دو رفتار دارند: DROP (دور ریختن بی‌صدا که به timeout می‌انجامد) و REJECT (رد صریح که به refused می‌انجامد). UFW به‌طور پیش‌فرض DROP می‌کند، اما قوانین reject یا فایروال‌های دیگر ممکن است رد صریح بفرستند. وضعیت را بررسی کنید:

sudo ufw status verbose
sudo iptables -L -n --line-numbers | head -n 40
sudo nft list ruleset | head -n 60

اگر پورت مورد نظر باز نیست، آن را باز کنید؛ آموزش کامل در فایروال UFW در اوبونتو آمده است. علاوه بر فایروال سیستم‌عامل، برخی ارائه‌دهندگان فایروال شبکه‌ای (Security Group) در پنل دارند که آن را هم باید بررسی کنید.

گام ۵: سرویس‌های داخل داکر

در داکر چند حالت خاص باعث refused می‌شود:

  • پورت منتشر نشده: اگر کانتینر را بدون -p اجرا کرده‌اید، پورتش از بیرون کانتینر در دسترس نیست. ستون PORTS در docker ps را ببینید.
  • برنامه داخل کانتینر روی 127.0.0.1 گوش می‌دهد: در این حالت حتی با انتشار پورت هم اتصال refused یا قطع می‌شود. برنامه باید داخل کانتینر روی 0.0.0.0 گوش دهد.
  • پورت روی 127.0.0.1 میزبان منتشر شده: با -p 127.0.0.1:8080:80 پورت فقط از داخل سرور در دسترس است؛ این برای پشت Nginx گذاشتن درست است، اما برای دسترسی مستقیم از بیرون نه.
  • کانتینر در حال ری‌استارت: وضعیت Restarting یعنی برنامه پیوسته خطا می‌دهد؛ docker logs را ببینید.

وقتی پورت توسط برنامهٔ دیگری اشغال شده است

گاهی سرویس شما اجرا نمی‌شود چون برنامهٔ دیگری زودتر همان پورت را گرفته است. در لاگ سرویس پیامی مثل Address already in use یا bind() failed می‌بینید. نمونهٔ کلاسیک آن نصب هم‌زمان Apache و Nginx است: هر دو می‌خواهند روی پورت ۸۰ گوش دهند و هرکدام زودتر اجرا شود، دیگری شکست می‌خورد. حالت مشابه وقتی پیش می‌آید که یک کانتینر داکر پورتی را منتشر کرده که سرویس اصلی سرور هم به آن نیاز دارد.

با sudo ss -tlnp | grep ':80 ' ببینید کدام فرایند پورت را گرفته است. سپس تصمیم بگیرید کدام برنامه باید روی آن پورت باشد: سرویس اضافه را متوقف و غیرفعال کنید (systemctl disable --now apache2) یا پورت یکی از آن‌ها را تغییر دهید. پس از رفع تداخل، سرویس اصلی را دوباره اجرا کنید و با ss مطمئن شوید روی پورت درست گوش می‌دهد.

سناریوهای رایج بر اساس سرویس

SSH: پس از تغییر پورت در sshd_config، یا وقتی سرویس به‌دلیل خطای پیکربندی اجرا نشده. از کنسول وب ارائه‌دهنده وارد شوید، sshd -t بگیرید و سرویس را اجرا کنید. اگر سرور تازه ساخته شده، ممکن است نصب سیستم‌عامل هنوز تمام نشده باشد؛ چند دقیقه صبر کنید.

وب‌سایت (پورت ۸۰ و ۴۴۳): Nginx یا Apache متوقف است، یا گواهی SSL تنظیم نشده و Nginx روی ۴۴۳ گوش نمی‌دهد. اگر سایت پشت CDN است و CDN خطا می‌دهد، راهنمای قطعی سایت بعد از فعال‌سازی CDN را بخوانید.

دیتابیس: تقریباً همیشه به‌خاطر bind روی localhost. پیشنهاد امن‌تر از باز کردن پورت دیتابیس، استفاده از تونل SSH است: ssh -L 5432:127.0.0.1:5432 root@203.0.113.10 و سپس اتصال برنامهٔ مدیریت دیتابیس به 127.0.0.1:5432 روی کامپیوتر خودتان.

برنامهٔ Node.js یا پایتون پشت Nginx: اگر Nginx خطای 502 می‌دهد و در لاگش Connection refused نوشته شده، برنامه روی پورت مورد انتظار اجرا نیست. روند کامل در رفع خطای 502 Bad Gateway آمده است.

پنج سؤال برای رفع refused
  1. سرویس اجرا می‌شود؟

    systemctl status یا docker ps.

  2. روی کدام آدرس و پورت؟

    ss -tlnp؛ 127.0.0.1 یعنی فقط داخلی.

  3. از داخل سرور کار می‌کند؟

    curl یا nc به 127.0.0.1.

  4. فایروال چه می‌گوید؟

    ufw status و قوانین iptables یا nftables.

  5. داکر درست منتشر شده؟

    ستون PORTS و گوش دادن برنامه روی 0.0.0.0 داخل کانتینر.

شکل ۳ با این ترتیب، علت تقریباً همهٔ خطاهای refused پیدا می‌شود.

جمع‌بندی

Connection refused خبر از سرور روشن و شبکهٔ سالم می‌دهد؛ مشکل در «چه کسی پشت این پورت است» است. به ترتیب: سرویس اجرا می‌شود؟ روی کدام آدرس و پورت؟ از داخل سرور کار می‌کند؟ فایروال چه می‌گوید؟ اگر داکر است، پورت منتشر شده و برنامه روی 0.0.0.0 است؟ با همین پنج سؤال تقریباً همهٔ موارد حل می‌شود. برای مرور دستورهای مدیریتی که در این مسیر به کار رفت، دستورات پرکاربرد لینوکس را ببینید و اگر روی سرورهای کلودیفای هستید، وضعیت کلی شبکه را پیش از تیکت در صفحهٔ وضعیت سرویس‌ها بررسی کنید.

سؤالات متداول

تفاوت Connection refused و Connection timed out چیست؟

در refused سرور فوراً پاسخ رد می‌دهد؛ یعنی سرور روشن است و شبکه کار می‌کند اما روی آن پورت سرویسی نیست. در timeout هیچ پاسخی نمی‌رسد؛ معمولاً به‌خاطر فایروالی که بسته را دور می‌ریزد، خاموش بودن سرور یا مشکل مسیر شبکه.

چرا دیتابیس از روی سرور کار می‌کند ولی از بیرون refused می‌دهد؟

دیتابیس‌ها به‌طور پیش‌فرض فقط روی 127.0.0.1 گوش می‌دهند. یا آدرس bind را تغییر دهید و پورت را فقط برای آی‌پی‌های مشخص باز کنید، یا امن‌تر، از تونل SSH استفاده کنید.

سرور تازه ساخته شده و SSH خطای refused می‌دهد؛ چرا؟

در دقیقه‌های اول نصب سیستم‌عامل هنوز تمام نشده و سرویس SSH اجرا نشده است. چند دقیقه صبر کنید و دوباره تلاش کنید. اگر ادامه داشت، از کنسول وب ارائه‌دهنده وضعیت سرویس را بررسی کنید.

چطور بفهمم کدام برنامه روی یک پورت گوش می‌دهد؟

دستور sudo ss -tlnp فهرست پورت‌های TCP باز را همراه با نام و شناسهٔ فرایند نشان می‌دهد. برای یک پورت خاص می‌توانید خروجی را با grep فیلتر کنید.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.