مشاهده تعداد کانکشن و IPهای فعال در لینوکس با netstat و ss
لود سرور ناگهان بالا رفته، سایت کند شده یا اصلاً بالا نمیآید و اولین سؤالی که باید جوابش را پیدا کنید این است: همین الان چند کانکشن به سرور باز است و کدام IP بیشترین سهم را دارد؟ جواب این سؤال با چند دستور تکخطی در ترمینال به دست میآید و برای تشخیص حملههایی مثل DDoS اولین قدم است.
کلاسیکترین ابزار این کار netstat (کوتاهشدهٔ network statistics) است. این دستور کانکشنهای ورودی و خروجی TCP و UDP، جدول روتینگ، آمار پروتکلها و وضعیت اینترفیسهای شبکه را نشان میدهد و در خانوادهٔ یونیکس (Linux، macOS، Solaris)، در BSDها و در ویندوز وجود دارد.
پیش از شروع: netstat یا ss؟
در لینوکس، netstat بخشی از بستهٔ net-tools است که سالهاست توسعهٔ فعال ندارد و در توزیعهای امروزی — AlmaLinux و Rocky Linux و RHEL نسخهٔ ۸ به بعد، و نصبهای تازهٔ Debian و Ubuntu — بهصورت پیشفرض نصب نیست. جایگزین رسمی آن ss از بستهٔ iproute2 است که پیشفرض روی همهٔ این توزیعها نصب است، اطلاعات را مستقیم از kernel میخواند و روی سروری با دهها هزار سوکت بهمراتب سریعتر از netstat جواب میدهد.
اگر روی سرور شما netstat نصب نیست و میخواهید همان دستورهای قدیمی را اجرا کنید:
# AlmaLinux / Rocky Linux / RHEL 8 و بالاتر sudo dnf install net-tools # CentOS 7 sudo yum install net-tools # Debian / Ubuntu sudo apt update && sudo apt install net-tools
در ادامه هر دستور را هم با netstat (چون هنوز در بیشتر آموزشها همین شکل نوشته شده) و هم با معادل درست و امروزیاش در ss میبینید. یک نکتهٔ کوچک: سوییچ -H در ss خط سرصفحه را حذف میکند؛ اگر نسخهٔ iproute2 روی سرور شما این سوییچ را نداشت، بهجای آن | tail -n +2 بگذارید.
تعداد کل کانکشنهای سرور
دستوری که تقریباً همهجا بهعنوان «تعداد کانکشن کلی به سرور» معرفی شده این است:
netstat -an | wc -l
این دستور کار میکند اما عدد بزرگتری از واقعیت میدهد، چون netstat -an در لینوکس علاوه بر سوکتهای شبکه، UNIX domain socketها (سوکتهای داخلی سیستم مثل ارتباط PHP-FPM با وبسرور) و چند خط سرصفحه را هم چاپ میکند. برای شمارش دقیق فقط کانکشنهای TCP، دو خط سرصفحه را حذف کنید و -a را بردارید:
netstat -nt | tail -n +3 | wc -l
و معادل امروزیاش:
ss -Htn | wc -l
اگر -a را اضافه کنید (netstat -nat یا ss -Htan)، پورتهایی که در حالت Listen هستند هم در شمارش میآیند؛ برای سنجش بار روی سرور معمولاً همان کانکشنهای برقرارشده ملاک است.
خلاصهٔ کلی وضعیت سوکتها را هم با یک دستور کوتاه میگیرید:
ss -s
تعداد کانکشن روی یک پورت خاص
نسخهٔ رایج این دستور برای پورت ۸۰ چنین است:
netstat -an | grep 80 | wc -l
به این شکل ننویسید. grep 80 هر خطی را که رشتهٔ «۸۰» در آن باشد میشمارد: پورت ۸۰۸۰، پورت ۳۰۸۰، پورت مبدأ تصادفی ۵۴۸۰۱ و حتی IPهایی مثل 80.191.x.x یا 1.2.80.4. عدد نهایی میتواند چند برابر واقعیت باشد. شکل دقیق، محدود کردن تطبیق به فیلد آدرس محلی (فیلد چهارم خروجی netstat) و انتهای رشته است:
netstat -nt | awk '$4 ~ /:80$/' | wc -l
با ss اصلاً نیازی به grep نیست، چون خود ابزار فیلتر پورت دارد:
ss -Htn sport = :80 | wc -l
در ss، sport یعنی پورت سمت خودِ سرور و dport یعنی پورت سمت طرف مقابل. هر دو دستور بالا فقط کانکشنهای برقرارشده را میشمارند و خودِ سوکت Listen را حساب نمیکنند؛ اگر آن را هم میخواهید -a اضافه کنید (netstat -nat یا ss -Htan sport = :80).
تعداد کانکشن از هر IP (پیدا کردن IP مهاجم)
این همان دستوری است که برای تشخیص حملههایی مثل DDoS به آن نیاز دارید؛ خروجی، فهرست IPها به همراه تعداد کانکشن هرکدام است:
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
دو نکته: اول اینکه دو خط اول خروجی netstat سرصفحه است و به شکل ردیفهای بیمعنی در نتیجه ظاهر میشود، پس بهتر است حذفشان کنید. دوم اینکه sort -n در انتها لیست را صعودی مرتب میکند و پرترافیکترین IP در پایین خروجی مینشیند؛ با sort -rn برعکس میشود و مهمترین ردیف بالای صفحه میآید:
netstat -ntu | tail -n +3 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
در بعضی آموزشها همین کار با -p نوشته میشود:
netstat -anp | grep 'tcp|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
این دستور هم جواب میدهد، ولی سوییچ -p فقط برای نمایش نام و PID پروسه است و اجرایش دسترسی root میخواهد؛ برای صرفاً شمردن کانکشنها لازم نیست و grep 'tcp|udp' هم اضافه است، چون همان netstat -ntu بالا دقیقاً همین خروجی را میدهد. -p را وقتی بیاورید که واقعاً میخواهید بدانید کدام سرویس پشت این کانکشنهاست.
نسخهٔ ss که هم سریعتر است و هم روی آدرسهای IPv6 درست کار میکند (در IPv6 خود آدرس پر از دونقطه است و cut -d: -f1 آن را خراب میکند):
ss -Htn | awk '{print $5}' | sed 's/:[^:]*$//' | sort | uniq -c | sort -rn | head -20
دیدن IP همراه با پورتی که به آن وصل شده
دستور زیر در بسیاری از آموزشها بهعنوان «تعداد کانکشن هر IP همراه با پورت» معرفی شده است:
netstat -na | awk '{print $5}' | cut -d "." -f1,2,3,4 | sort | uniq -c | sort -nr
این نسخه یادگار خروجی netstat در BSD و macOS است که آدرس و پورت را با نقطه جدا میکند (1.2.3.4.54801)؛ در لینوکس جداکنندهٔ پورت دونقطه است، پس cut -d "." -f1,2,3,4 عملاً کل رشته را دستنخورده برمیگرداند. ضمناً فیلد پنجم در لینوکس آدرس طرف مقابل است، یعنی خروجی این دستور IP کلاینت بههمراه پورت مبدأ اوست، نه پورتی از سرور شما که به آن وصل شده. چون پورت مبدأ هر کانکشن معمولاً یکتاست، تقریباً همهٔ ردیفها عدد ۱ میگیرند و عملاً چیزی نمیشمارد. اگر میخواهید بدانید کدام IP روی کدام پورت سرور شما نشسته، این را اجرا کنید:
ss -Htn | awk '{ l=$4; sub(/.*:/,"",l); p=$5; sub(/:[^:]*$/,"",p); print p, l }' | sort | uniq -c | sort -rn | head -20
خروجی به شکل «تعداد — IP کلاینت — پورت سرور» است و دقیقاً به شما میگوید حجم کانکشن روی کدام سرویس (۸۰، ۴۴۳، ۳۳۰۶، ۲۲ و…) و از طرف چه کسی است.
تعداد کانکشن روی هر پورت
برای اینکه ببینید بار روی کدام پورت سرور متمرکز شده:
netstat -tuna | awk -F':+| +' 'NR>2{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
این دستور به موقعیت فیلدها تکیه میکند و روی خطوط IPv6 — که خودشان دونقطه دارند — جابهجا میشود و عدد اشتباه میدهد. نسخهٔ مطمئن با ss:
ss -Htn | awk '{p=$4; sub(/.*:/,"",p); print p}' | sort | uniq -c | sort -rn
و اگر میخواهید بدانید کدام سرویس روی پورت پرترافیک نشسته است (نمایش نام پروسه به دسترسی root نیاز دارد):
sudo ss -Htnp sport = :80
بررسی وضعیت کانکشنها و تشخیص SYN Flood
تعداد کل کانکشنها بهتنهایی گمراهکننده است؛ مهم این است که این کانکشنها در چه وضعیتی هستند. توزیع وضعیتها را با این دستور ببینید:
netstat -ant | tail -n +3 | awk '{print $6}' | sort | uniq -c | sort -rn
ss -Htan | awk '{print $1}' | sort | uniq -c | sort -rn
اگر تعداد زیادی SYN_RECV دیدید (در ss به شکل SYN-RECV)، یعنی کلاینتها دستدادن سهمرحلهای TCP را شروع کردهاند و تمام نکردهاند — الگوی کلاسیک SYN flood:
ss -Htn state syn-recv | wc -l
یک نکته: اگر روی سرور net.ipv4.tcp_syncookies فعال باشد (که روی توزیعهای امروزی پیشفرض است)، کرنل در فشار بالا بهجای نگهداشتن سوکت نیمهباز از SYN cookie استفاده میکند و شمار SYN-RECV آنقدر که انتظار دارید بالا نمیرود. پس عدد پایین این دستور بهتنهایی به معنی نبودن حمله نیست؛ لاگ کرنل (dmesg) و نرخ ترافیک ورودی را هم ببینید.
تعداد بالای TIME_WAIT معمولاً نگرانکننده نیست و نتیجهٔ طبیعی بسته شدن کانکشنهای کوتاه است. تعداد بالای ESTABLISHED از یک IP خاص، آن IP را کاندیدای بررسی میکند.
برای پایش زنده هم میتوانید هر چند ثانیه یکبار خلاصه را تازه کنید:
watch -n 2 'ss -s'
IP مشکوک را پیدا کردید؛ حالا چطور مسدودش کنیم؟
قبل از هر چیز یک هشدار: تعداد زیاد کانکشن از یک IP همیشه به معنی حمله نیست. IP یک CDN یا reverse proxy، خروجی NAT یک شرکت یا اپراتور موبایل، سرویس مانیتورینگ خودتان و ربات موتورهای جستوجو همگی طبیعی است که کانکشن زیاد بسازند. پیش از بلاک کردن، IP را بررسی کنید.
هشدار دوم و مهمتر: مطمئن شوید IPی که میخواهید ببندید، IP خودتان یا IP دفتر/VPN شما نیست — چون معمولاً همان IP بیشترین کانکشن SSH و پنل را به سرور دارد و بستنش یعنی قفل شدن بیرونِ سرور. آدرس فعلی خودتان را با who یا ss -Htn sport = :22 ببینید و کنار بگذارید. اگر به کنسول اضطراری (KVM/VNC یا Rescue Mode) دسترسی ندارید، قبل از اعمال قانون فایروال یک نشست SSH باز را نبندید تا در صورت اشتباه بتوانید قانون را برگردانید.
اگر مطمئن شدید که باید مسدود شود، بسته به فایروال سرور:
# firewalld — AlmaLinux / Rocky / RHEL / CentOS 7 و بالاتر firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='1.2.3.4' reject" firewall-cmd --reload # ufw — Ubuntu / Debian (فقط وقتی ufw فعال است؛ با ufw status چک کنید) ufw deny from 1.2.3.4 # CSF csf -d 1.2.3.4
با iptables هم میشود، اما این قانون موقتی است و با ریستارت سرور از بین میرود مگر اینکه ذخیرهاش کنید:
iptables -I INPUT -s 1.2.3.4 -j DROP # برداشتن همین قانون در صورت اشتباه iptables -D INPUT -s 1.2.3.4 -j DROP # ذخیرهٔ دائمی در Debian / Ubuntu (با نصب iptables-persistent) netfilter-persistent save
روی توزیعهای جدید، پشتصحنهٔ فایروال nftables است ولی دستور iptables از طریق لایهٔ سازگاری همچنان کار میکند. توصیه این است که بهجای دست زدن مستقیم به iptables، از firewalld یا ufw استفاده کنید تا قانونها دائمی و قابلمدیریت بمانند.
یک نکتهٔ مهم دیگر: این روش فقط برای حملههای لایهٔ اپلیکیشن و حجمهای کوچک جواب میدهد. در حملهٔ حجمی که پهنای باند ورودی سرور را اشباع میکند، ترافیک پیش از رسیدن به فایروال سرور شما مسیر را پر کرده و بلاک کردن IP روی خود سرور کمکی نمیکند؛ چنین حملهای باید در سطح بالادست (شبکهٔ دیتاسنتر یا سرویس فیلترینگ) مهار شود.
جدول سوییچهای netstat
در دستورهای بالا سوییچهایی مثل -a (نمایش همهٔ کانکشنهای TCP و UDP)، -n (خروجی عددی) و -t و -u را دیدید. فهرست کاملتر سوییچها و اینکه کدامیک مخصوص کدام سیستمعامل است:
| -a | نمایش همهٔ کانکشنهای فعال بهعلاوهٔ پورتهای TCP و UDP که سیستم روی آنها در حال Listen است. |
| -n | نمایش آدرسها و شماره پورتها به شکل عددی، بدون تلاش برای تبدیل به نام (DNS reverse). خروجی را بسیار سریعتر میکند. |
| -t (لینوکس) | فقط کانکشنهای TCP. |
| -u (لینوکس) | فقط سوکتهای UDP. |
| -l (لینوکس) | فقط سوکتهایی که در حالت Listen هستند. |
| -p (لینوکس) | نمایش اینکه کدام پروسه صاحب کدام سوکت است (معادل -b در ویندوز). به دسترسی root نیاز دارد. |
| -i (غیر از ویندوز) | نمایش اینترفیسهای شبکه و آمار هرکدام. |
| -r | نمایش محتوای جدول روتینگ IP (معادل route print در ویندوز). |
| -s | نمایش آمار به تفکیک پروتکل؛ بهصورت پیشفرض TCP، UDP، ICMP و IP. قابل ترکیب با -p برای محدود کردن به یک پروتکل. |
| -e | نمایش آمار Ethernet مثل تعداد بایتها و پکتهای ارسالی و دریافتی. قابل ترکیب با -s. |
| -g | نمایش اطلاعات عضویت در گروههای multicast برای IPv4 و IPv6. |
| -m | نمایش آمار حافظهٔ مصرفی بخش شبکهٔ کرنل (در Solaris آمار STREAMS). |
| -b (ویندوز) | نمایش نام فایل اجراییای که هر کانکشن یا پورت Listen را ساخته است. |
| -b (macOS، NetBSD) | باعث میشود -i مجموع بایتهای ترافیک را هم گزارش کند. |
| -o (ویندوز) | نمایش PID پروسهٔ هر کانکشن؛ با همان PID میتوانید برنامه را در تب Details ویندوز تسکمنیجر پیدا کنید. قابل ترکیب با -a، -n و -p. |
| -f (ویندوز) | نمایش نام دامنهٔ کامل (FQDN) برای آدرسهای طرف مقابل. |
| -f address family (FreeBSD) | محدود کردن خروجی به یک خانوادهٔ آدرس: unix، inet، inet6. |
| -p protocol (ویندوز و BSD) | نمایش کانکشنهای یک پروتکل مشخص: tcp، udp، tcpv6، udpv6. اگر همراه -s بیاید، icmp، ip، icmpv6 و ipv6 هم پذیرفته میشود. |
| -P protocol (Solaris) | نمایش کانکشنهای پروتکل مشخصشده: ip، ipv6، icmp، icmpv6، igmp، udp، tcp، rawip. |
| -v (ویندوز) | همراه با -b، زنجیرهٔ کامل کامپوننتهایی را که در ساخت کانکشن دخیل بودهاند نمایش میدهد. |
| -W (FreeBSD) | خروجی عریض؛ نام هاستها و آدرسهای IPv6 را کوتاه نمیکند. |
| Interval | عددی که بعد از سوییچها میآید و باعث میشود خروجی هر چند ثانیه یکبار تازه شود. با Ctrl+C متوقف میشود. اگر نیاید، netstat فقط یکبار خروجی میدهد. |
| -h (یونیکس) / /? (ویندوز) | نمایش راهنمای دستور. |
همین کار روی ویندوز سرور
برخلاف لینوکس، netstat در ویندوز هنوز ابزار استاندارد و پشتیبانیشده است. برای دیدن کانکشنهای یک پورت بههمراه PID:
netstat -ano | findstr :80
اما در PowerShell ابزار دقیقتری در اختیار دارید که خروجیاش شیء است و لازم نیست با متن کلنجار بروید. شمارش کانکشنهای یک پورت:
@(Get-NetTCPConnection -LocalPort 80 -ErrorAction SilentlyContinue).Count
و پیدا کردن پرکانکشنترین IPها — همان کاری که در لینوکس با awk و uniq انجام دادیم:
Get-NetTCPConnection -State Established | Group-Object RemoteAddress | Sort-Object Count -Descending | Select-Object -First 20 -Property Count, Name
و برای مسدود کردن IP مهاجم با فایروال ویندوز:
New-NetFirewallRule -DisplayName "Block 1.2.3.4" -Direction Inbound -RemoteAddress 1.2.3.4 -Action Block
جمعبندی
برای شمردن کانکشنها روی سرور لینوکسی، ss را پیشفرض خود بگذارید و netstat را فقط جایی به کار ببرید که مجبورید. ترتیب کار در یک بحران لود چنین است: اول ss -s برای دیدن حجم کلی، بعد توزیع وضعیتها برای تشخیص SYN flood، سپس شمارش به تفکیک IP برای پیدا کردن مبدأ، و در آخر — فقط بعد از اطمینان از اینکه IP واقعاً مهاجم است و IP خودتان نیست — مسدودسازی با firewalld یا ufw.