پرش به محتویات

۷. شبکه و عیب‌یابی اتصال

عیب‌یابی شبکه یعنی جداکردن لایه‌ها: اینترفیس ← مسیر ← DNS ← TCP ← TLS ← برنامه. هر لایه را جدا و به ترتیب تست کنید و به لایهٔ بعد نروید تا قبلی سالم نباشد.

راهنمای سریع

فرمان کاربرد ریسک
ip -br a / ip route / ip neigh آدرس، مسیر، ARP بدون تغییر
ping / mtr / traceroute / tracepath دسترسی و مسیر بدون تغییر
ss -lntup / ss -s پورت‌ها و اتصال‌ها بدون تغییر
dig / getent hosts / resolvectl DNS بدون تغییر
nc -vz / curl -v تست TCP / HTTP بدون تغییر
tcpdump ضبط بسته تغییر (بار + داده حساس)
ip addr/route add، nmcli، netplan apply تغییر شبکه مخرب روی اتصال راه دور

IP و مسیر‌یابی

ip -br address
ip address show
ip -br link
ip route
ip route get 1.1.1.1            # از کدام اینترفیس/gateway می‌رود؟
ip neigh                        # جدول ARP/NDP
hostname -I

ip ابزار اصلی مدرن برای بررسی رابط‌ها، مسیرها و همسایه‌های شبکه است (جایگزین ifconfig/route/arp). در ip neigh، وضعیت FAILED یا INCOMPLETE برای gateway یعنی لایهٔ ۲ مشکل دارد.

اتصال و پورت‌ها

ping -c 4 192.0.2.1
tracepath 8.8.8.8
traceroute -n 8.8.8.8
mtr -rwzc 10 8.8.8.8            # ترکیب ping+traceroute با درصد افت هر hop
nc -vz SERVER_IP 443
curl -v --connect-timeout 5 https://example.com/
sudo ss -lntup

موفقیت ping تضمین‌کننده دسترسی به پورت برنامه نیست؛ ممکن است ICMP مسدود باشد (و برعکس، ping ممکن است جواب ندهد ولی سرویس سالم باشد). برای بررسی TCP از nc و برای HTTP(S) از curl استفاده کنید.

فیلتر کردن ss

ss -s                                          # خلاصهٔ تعداد اتصال‌ها بر حسب حالت
ss -tan state established '( dport = :443 or sport = :443 )' | head
ss -tn state established | awk 'NR>1{print $4}' | cut -d: -f1 | sort | uniq -c | sort -nr | head   # بیشترین کلاینت
ss -tan state time-wait | wc -l
ss -ltnp 'sport = :8080'

تعداد بسیار زیاد SYN-RECV ← سیل SYN یا backlog پر؛ CLOSE-WAIT انباشته ← برنامه سوکت را نمی‌بندد (باگ برنامه)؛ TIME-WAIT زیاد معمولاً بی‌خطر است.

معنی خطاها (جداکنندهٔ سریع علت)

پیام یعنی معمولاً علت
Connection refused مقصد رسید و رد شد هیچ سرویسی روی آن پورت گوش نمی‌دهد، یا فایروال با REJECT
Connection timed out هیچ پاسخی نیامد فایروال/SG با DROP، مسیر اشتباه، مقصد خاموش
No route to host ARP/ICMP unreachable همان subnet و ARP ناموفق، یا فایروال ICMP-unreachable
Network is unreachable مسیری در جدول نیست gateway/route ندارید
Name or service not known DNS نتوانست resolve کند DNS/resolv.conf/نام اشتباه
Connection reset by peer مقصد وسط ارتباط قطع کرد proxy/برنامه کرش/IPS/timeout

کدهای خروج curl پرکاربرد: 6 = resolve نشد، 7 = اتصال رد شد، 28 = timeout، 35 = خطای SSL handshake، 60 = گواهی نامعتبر.

DNS

getent hosts example.com
resolvectl status
resolvectl query example.com
resolvectl flush-caches
dig example.com A
dig example.com AAAA
dig +short example.com
dig @1.1.1.1 example.com
nslookup example.com
cat /etc/resolv.conf

getent از مسیر حل نام سیستم (شامل /etc/hosts و nsswitch.conf) استفاده می‌کند؛ dig فقط DNS را می‌پرسد و /etc/hosts را نمی‌بیند. اگر dig جواب می‌دهد ولی getent نه (یا برعکس)، مشکل در لایهٔ NSS/hosts/systemd-resolved است. روی سیستم‌های مدرن /etc/resolv.conf اغلب به 127.0.0.53 (stub محلی) اشاره می‌کند؛ DNS واقعی را با resolvectl status ببینید.

ابزارهای تشخیصی

sudo tcpdump -ni any host 192.0.2.10
sudo tcpdump -ni eth0 -c 100 port 443
sudo tcpdump -ni eth0 -w /var/tmp/cap.pcap -c 5000 host 192.0.2.10   # محدود و فایل‌شده
ethtool eth0 | grep -E 'Speed|Duplex|Link detected'
ip -s link show eth0              # شمارندهٔ errors/drops

Capture ممکن است اطلاعات حساس کاربران را شامل شود. فقط با مجوز و فیلتر مناسب ضبط کنید، حتماً با -c/زمان محدود کنید (دیسک را پر نکند) و فایل pcap را محرمانه نگه دارید و حذف کنید.

MTU و پهنای باند

ping -M do -s 1472 -c 3 SERVER_IP    # 1472+28=1500؛ اگر 'message too long' آمد، MTU مسیر کمتر است
iperf3 -s                            # سمت سرور
iperf3 -c SERVER_IP -t 10            # سمت کلاینت (فقط با هماهنگی؛ شبکه را اشباع می‌کند)
cat /proc/net/bonding/bond0 2>/dev/null   # وضعیت bonding

پیکربندی شبکه

Ubuntu Server معمولاً از Netplan استفاده می‌کند:

ls -l /etc/netplan/
sudo cp -a /etc/netplan /root/netplan.bak.$(date +%F)
sudo netplan get
sudo netplan try          # بعد از ~120 ثانیه بدون تأیید، خودکار برمی‌گردد
sudo netplan apply

روی اتصال راه دور، netplan try از اعمال دائمی اشتباه جلوگیری می‌کند، اما همچنان باید کنسول یا مسیر بازیابی در دسترس باشد. فایل تنظیمات را قبل از تغییر کپی کنید.

RHEL-family از NetworkManager استفاده می‌کند:

nmcli device status
nmcli connection show
nmcli connection show "CONN" | grep -E 'ipv4|connection.autoconnect'
sudo nmcli connection modify "CONN" ipv4.addresses 192.0.2.10/24 ipv4.gateway 192.0.2.1 ipv4.dns 1.1.1.1 ipv4.method manual
sudo nmcli connection up "CONN"      # روی اتصال راه دور: قطع‌شدن لحظه‌ای ممکن است

تغییر موقت (با ریبوت از بین می‌رود، برای تست):

sudo ip addr add 192.0.2.10/24 dev eth0
sudo ip route add 198.51.100.0/24 via 192.0.2.1

تشخیص IP تکراری: sudo arping -D -I eth0 -c 3 192.0.2.10 (اگر جواب آمد، IP دیگری استفاده‌شده).

مسیر‌یابی و اتصال کاربردی

curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null
ip route get 192.0.2.67

برای عیب‌یابی مرحله‌ای، ابتدا DNS، سپس مسیر، اتصال TCP، TLS و در نهایت پاسخ برنامه را جداگانه بررسی کنید.

عیب‌یابی اتصال گام‌به‌گام

  1. لایهٔ محلی: ip link · ip -br a — آیا اینترفیس UP است و IP دارد؟ (ethtool eth0 برای لینک)
  2. Gateway: ip route · ping -c 3 $(ip route | awk '/default/ {print $3; exit}')
  3. DNS: getent hosts example.com · در صورت شکست dig @8.8.8.8 example.com
  4. مسیر تا مقصد: traceroute -n TARGET یا mtr -rwzc 10 TARGET
  5. پورت مقصد: nc -vz TARGET 443 یا curl -vI https://TARGET
  6. برنامه: لاگ سمت سرور با همان timestamp
# خلاصه وضعیت شبکه در یک نگاه
ip -br link
ip -br addr
ip route
resolvectl status 2>/dev/null || cat /etc/resolv.conf
sudo ss -lntup | head -40

Firewall و NAT در مسیر

اگر پینگ جواب می‌دهد ولی پورت باز نیست:

  • فایروال میزبان (ufw / nft / firewalld)
  • Security Group ابری
  • DNAT / port-forward روی روتر یا load balancer
  • Docker/iptables (Docker)
sudo nft list ruleset 2>/dev/null | head -80
sudo firewall-cmd --list-all 2>/dev/null
sudo ufw status verbose 2>/dev/null

لینک و لایهٔ ۲ (عمیق‌تر)

وقتی «گاهی کند است یا قطع می‌شود» می‌شنوید، اول شمارنده‌های لینک را ببینید؛ قبل از هر حدس دربارهٔ نرم‌افزار:

ethtool eth0 | grep -E 'Speed|Duplex|Auto-negotiation|Link detected'
ethtool -S eth0 | grep -Ei 'err|drop|crc|miss|fifo|carrier'   # شمارندهٔ سخت‌افزار (نام‌ها به NIC بستگی دارد)
ip -s -s link show eth0                                         # دو بار -s: جزئیات خطا
sudo dmesg -T | grep -iE 'link is (up|down)|NIC Link'           # flap شدن لینک
شمارنده / نشانه معنی اقدام
crc، rx_errors در حال افزایش کابل/SFP/پورت سوئیچ خراب یا کثیف جابه‌جایی کابل/ماژول، شمارندهٔ پورت سوئیچ
Speed کمتر از انتظار (100Mb/s یا Half) auto-negotiation نامتقارن هر دو سر را یکسان کنید؛ دستی فقط وقتی هر دو طرف دستی باشند
rx_missed / rx_dropped افزایشی NIC از CPU عقب است (ring کوچک یا CPU اشباع) ethtool -g eth0 ، بررسی softirq با mpstat -P ALL 1
carrier / flap مکرر در dmesg لینک فیزیکی ناپایدار کابل/ماژول؛ مقایسه با لاگ سوئیچ

VLAN، Bond و Bridge

بررسی وضعیت (بدون تغییر):

ip -d link show bond0.20 | grep -E 'vlan|bond'    # VLAN ID واقعی
cat /proc/net/bonding/bond0                       # MII Status هر slave، mode، Aggregator ID
bridge link; bridge fdb show br br0 | head        # عضو bridge و جدول MAC

در bond حالت 802.3ad (LACP) باید سوئیچ هم LACP باشد؛ اگر در /proc/net/bonding/bond0 برای slaveها Aggregator ID متفاوت است یا Partner Mac Address صفر است، طرف سوئیچ LACP نگفته است. حالت active-backup به تنظیم سوئیچ نیاز ندارد و امن‌ترین شروع است.

نمونهٔ Netplan (bond فعال/پشتیبان + VLAN 20):

network:
  version: 2
  ethernets:
    eno1: {}
    eno2: {}
  bonds:
    bond0:
      interfaces: [eno1, eno2]
      parameters: { mode: active-backup, mii-monitor-interval: 100 }
  vlans:
    bond0.20:
      id: 20
      link: bond0
      addresses: [192.0.2.10/24]
      routes:
        - to: default
          via: 192.0.2.1

معادل NetworkManager:

sudo nmcli con add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100"
sudo nmcli con add type ethernet slave-type bond con-name bond0-eno1 ifname eno1 master bond0
sudo nmcli con add type ethernet slave-type bond con-name bond0-eno2 ifname eno2 master bond0
sudo nmcli con add type vlan con-name bond0.20 ifname bond0.20 dev bond0 id 20 \
     ipv4.method manual ipv4.addresses 192.0.2.10/24 ipv4.gateway 192.0.2.1

فقط با کنسول

تغییر bond/VLAN روی اینترفیسی که با آن SSH زده‌اید قطع‌شدن اتصال است. از روش «برگشت خودکار» پایین استفاده کنید.

خواندن tcpdump (الگوهای تشخیصی)

همیشه ترافیک SSH خودتان را حذف کنید، وگرنه ضبط بی‌معنی و حجیم می‌شود:

sudo tcpdump -ni eth0 -c 50 'host 192.0.2.10 and tcp port 443 and not port 22'
sudo tcpdump -ni eth0 -c 50 'tcp[tcpflags] & tcp-syn != 0 and host 192.0.2.10'   # فقط SYN / SYN-ACK
sudo tcpdump -ni eth0 -c 50 'tcp[tcpflags] & tcp-rst != 0'                       # فقط RST
sudo tcpdump -ni eth0 -c 50 'arp or icmp'

پرچم‌ها: [S] = SYN، [S.] = SYN-ACK، [.] = ACK، [P.] = داده، [F.] = بستن، [R]/[R.] = ریست.

آنچه می‌بینید تفسیر
[S] تکراری، هیچ [S.] برنمی‌گردد بسته می‌رسد ولی پاسخ نمی‌آید: DROP روی مقصد/مسیر، یا مسیر برگشت اشتباه
[S] ← بلافاصله [R.] پورت بسته است (refused)؛ سرویس نیست یا REJECT
[S.] از مقصد می‌آید ولی ACK ارسال نمی‌شود/می‌رسد مسیر نامتقارن، NAT یا rp_filter
handshake کامل، بستهٔ بزرگ ارسال می‌شود و تکرار می‌شود، بستهٔ کوچک رد می‌شود MTU / PMTUD (ping -M do -s)
بسته‌های تکراری با فاصلهٔ ۱، ۲، ۴ ثانیه افت بسته و retransmit؛ ss -ti را ببینید

وضعیت TCP، backlog و retransmit

ss -lnt                        # روی LISTEN: Recv-Q = صف فعلی accept، Send-Q = حداکثر backlog
ss -ti dst 192.0.2.10          # rtt، cwnd، retrans برای اتصال‌های آن مقصد
nstat -az | grep -Ei 'TcpRetransSegs|ListenOverflows|ListenDrops|TcpExtTCPTimeouts'
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog

اگر Recv-Q روی LISTEN به Send-Q نزدیک است یا ListenOverflows بالا می‌رود، برنامه accept() را به‌موقع انجام نمی‌دهد (کندی برنامه/نبود worker)؛ بالا بردن somaxconn به‌تنهایی مشکل را حل نمی‌کند، فقط صف را بزرگ‌تر می‌کند.

conntrack و NAT

روی سرورهایی که NAT، Docker، Kubernetes یا فایروال stateful دارند، پر شدن جدول conntrack علتِ کلاسیک «بعضی اتصال‌ها بی‌دلیل می‌افتند» است:

sudo conntrack -C                                  # تعداد فعلی
sysctl net.netfilter.nf_conntrack_max              # سقف
sudo dmesg -T | grep -i 'nf_conntrack: table full' # نشانهٔ قطعی دور ریختن بسته
sudo conntrack -S | head                           # شمارندهٔ drop و insert_failed
# بیشترین مبدأها (چه کسی جدول را پر می‌کند؟)
sudo conntrack -L 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/){print $i; break}}' | sort | uniq -c | sort -nr | head

اگر جدول واقعاً پر است: اول علت را پیدا کنید (اسکنر، برنامهٔ نشت‌کنندهٔ اتصال، timeout بلند)، بعد سقف را ببرید بالا. هر ورودی مقداری RAM می‌خورد، پس با حافظهٔ آزاد هماهنگ کنید:

echo 'net.netfilter.nf_conntrack_max = 262144' | sudo tee /etc/sysctl.d/90-conntrack.conf
sudo sysctl --system

مسیر نامتقارن و rp_filter

علامت: درخواست از eth1 وارد می‌شود ولی پاسخ از eth0 (به‌خاطر default route) خارج می‌شود. سرور مقصد یا خود هسته (rp_filter) آن را دور می‌ریزد.

sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.eth1.rp_filter   # 1=strict، 2=loose، 0=خاموش
ip rule; ip route show table all | head -30
ip route get 203.0.113.50 from 198.51.100.10 iif eth1             # مسیر برگشت چیست؟

راه‌حل درست خاموش‌کردن rp_filter نیست؛ policy routing است: هر اینترفیس جدول مسیر خودش را دارد.

# موقت و برای آزمایش (شمارهٔ جدول دلخواه)
sudo ip route add default via 198.51.100.1 dev eth1 table 100
sudo ip rule add from 198.51.100.10/32 lookup 100

برای ماندگاری از routing-policy در Netplan یا ipv4.routing-rules در NetworkManager استفاده کنید.

IPv4 در برابر IPv6

اگر «اتصال چند ثانیه گیر می‌کند و بعد وصل می‌شود»، احتمالاً AAAA وجود دارد ولی مسیر IPv6 خراب است:

curl -4 -sS -o /dev/null -w '%{time_total}\n' https://example.com/
curl -6 -sS -o /dev/null -w '%{time_total}\n' https://example.com/
ip -6 route; ping -6 -c 3 2001:db8::1

تغییر امن شبکه روی سرور راه دور (برگشت خودکار)

netplan try فقط Netplan را پوشش می‌دهد. الگوی عمومی که با هر ابزار کار می‌کند: قبل از تغییر، یک تایمر برگشت بسازید؛ بعد از تأیید سالم‌بودن، آن را لغو کنید.

sudo tar czf /root/netplan.bak.tgz -C /etc netplan
sudo systemd-run --on-active=5m --unit=net-rollback \
  bash -c 'rm -rf /etc/netplan && tar xzf /root/netplan.bak.tgz -C /etc && netplan apply'

# ... تغییر را اعمال کنید (netplan apply) ...

# اگر هنوز SSH دارید و همه‌چیز سالم است، برگشت را لغو کنید:
sudo systemctl stop net-rollback.timer

اگر دسترسی قطع شد، پس از ۵ دقیقه تنظیمات قبلی خودکار برمی‌گردد. قبل از تغییر مطمئن شوید systemd-run در دسترس است و ساعت سرور درست است.

خطاهای رایج

نشانه علت احتمالی روش بررسی
ping موفق، سرویس نه فایروال/پورت/برنامه nc -vz ، ss -lntp
فقط از یک شبکه در دسترس route/ACL/NAT ip route get ، traceroute
بعضی سایت‌ها باز می‌شوند، بعضی نه (hang) MTU/PMTUD ping -M do -s
DNS کند (۵ ثانیه تأخیر) nameserver اول مرده resolvectl status ، dig @NS
اتصال‌های متناوب قطع duplicate IP، لینک بد، drop arping -D ، ip -s link ، ethtool
بعد از netplan apply دسترسی قطع تنظیم اشتباه کنسول؛ برگرداندن کپی
اتصال‌های جدید گاهی می‌افتند (NAT/Docker) جدول conntrack پر conntrack -C ، dmesg \| grep conntrack
rx_errors/crc رو به افزایش کابل/SFP/duplex ethtool -S ، شمارندهٔ پورت سوئیچ
درخواست می‌رسد، پاسخ نه (چند اینترفیس) مسیر نامتقارن / rp_filter ip route get ... from ... iif
اتصال چند ثانیه گیر می‌کند AAAA خراب (IPv6) curl -4 در برابر curl -6

نکات عملیاتی

  • آدرس‌های خصوصی (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) از اینترنت route نمی‌شوند؛ برای دسترسی از بیرون به VPN یا bastion نیاز دارید.
  • تغییر دائمی شبکه در Ubuntu جدید اغلب با netplan است (/etc/netplan/*.yaml)؛ بعد از ویرایش: sudo netplan try.
  • در RHEL-family از NetworkManager (nmcli) استفاده کنید.
  • هر تغییر شبکه روی سرور راه دور: کنسول آماده + تایمر برگشت خودکار (بخش «تغییر امن شبکه روی سرور راه دور»).

خلاصهٔ اجرایی

  1. لایه به لایه: لینک ← gateway ← DNS ← پورت ← برنامه.
  2. «refused» = فعالانه رد شد؛ «timed out» = ساکت دور ریخته شد.
  3. dig و getent را هر دو بگیرید؛ تفاوتشان سرنخ است.
  4. تغییر شبکه راه دور بدون کنسول و rollback ممنوع.
  5. قبل از حدس دربارهٔ نرم‌افزار، شمارندهٔ لینک (ethtool -S) و conntrack را ببینید؛ tcpdump را با فیلتر و -c بگیرید.