Yüksek Bağlantı Sayısı Sorunları: netstat ve ss ile Soket Durumu Analizi

Sunucunda bir şeyler ters gittiğini hissediyorsun: uygulama yavaşlamış, bağlantılar zaman aşımına uğruyor, ya da tamamen hizmet veremiyor. İlk refleks olarak CPU ve RAM’e bakıyorsun, her şey normal görünüyor. Ama sorun ağ katmanında gizleniyor olabilir. Yüksek bağlantı sayısı, soket tükenmesi ya da yarı açık bağlantıların birikmesi, production ortamlarında en sık karşılaşılan ve en çok zaman harcatan sorunların başında geliyor. Bu noktada netstat ve ss araçları sysadmin’in en iyi dostları haline geliyor.

netstat mi, ss mi? Hangisini Kullanmalıyız?

Önce şunu netleştirelim: netstat eski, ss yeni nesil. netstat, net-tools paketinin bir parçası ve birçok modern Linux dağıtımında artık varsayılan olarak kurulu gelmiyor. ss ise iproute2 paketinin içinde geliyor ve doğrudan kernel’ın netlink arayüzünü kullandığı için hem çok daha hızlı hem de çok daha fazla bilgi sunuyor. Yüz binlerce soket açık olduğunda netstat dakikalarca çalışırken ss saniyeler içinde sonuç veriyor.

Ama şunu da söyleyeyim: production ortamlarında hâlâ netstat kurulu olan sistemler var, eski alışkanlıklar kolay gitmiyor. Bu yüzden her iki aracın da nasıl kullanıldığını bilmek gerekiyor. Ben her ikisini de anlatacağım.

Temel Durum Tespiti: İlk Bakış

Bir sunucuya bağlandığında ve “bağlantı sorunu var” dendiğinde ilk yapman gereken şey mevcut soket durumunu genel olarak görmek. Aşağıdaki komut sana toplam bağlantı sayısını duruma göre özetleyerek verir:

ss -s

Bu komutun çıktısı şuna benzer bir şey gösterir:

Total: 1842
TCP:   1756 (estab 1203, closed 412, orphaned 45, timewait 398)

Transport Total     IP        IPv6
RAW       0         0         0
UDP       12        8         4
TCP       1344      1102      242
INET      1356      1110      246
FRAG      0         0         0

Bu çıktıdan birkaç şeyi hemen okuyabilirsin. estab değeri aktif kurulu bağlantı sayısını gösteriyor. timewait değeri yüksekse bu bir sorunun habercisi olabilir. orphaned değeri yüksekse uygulama tarafında soket kapatma problemleri var demektir.

netstat ile benzer özet bilgiye şöyle ulaşırsın:

netstat -s | grep -E "connections|failed|reset|retransmit"

Bağlantı Durumlarını Anlamak

Sorun giderirken bağlantı durumlarını doğru okuyabilmek kritik. Aşağıdaki durumları bilmeden analiz yapamazsın:

  • ESTABLISHED: Aktif, karşılıklı veri alışverişi olan bağlantı
  • TIME_WAIT: Bağlantı kapatıldı, kernel hâlâ bekliyor. Varsayılan olarak 60-120 saniye sürer
  • CLOSE_WAIT: Karşı taraf bağlantıyı kapattı, ama uygulama henüz soketini kapatmadı. Bu genellikle uygulama bug’ı işaretidir
  • SYN_SENT: Bağlantı isteği gönderildi, henüz cevap yok
  • SYN_RECV: SYN paketi alındı, SYN-ACK gönderildi, ACK bekleniyor. Yüksekse SYN flood saldırısı olabilir
  • FIN_WAIT1 / FIN_WAIT2: Bağlantı kapatma sürecinin aşamaları
  • LAST_ACK: Son ACK bekleniyor
  • LISTEN: Servis bağlantı bekliyor

Duruma göre filtrelenmiş çıktı almak için:

ss -tan state time-wait | wc -l
ss -tan state close-wait | wc -l
ss -tan state established | wc -l

Gerçek Dünya Senaryosu 1: TIME_WAIT Patlaması

Bir web sunucusu düşünelim. Nginx arkasında bir uygulama servisi var, her dakika binlerce istek geliyor. Sabah saatlerinde yeni bağlantılar kurulmuyor, 502 Bad Gateway hataları almaya başlıyorsunuz. CPU normal, RAM normal, disk I/O normal. Ne bakacaksın?

ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

Bu komut tüm TCP bağlantılarını durumlarına göre sayar ve sıralı şekilde gösterir. Eğer TIME_WAIT satırında 30.000 üzeri bir sayı görüyorsan, sorun açık.

Daha detaylı bakalım, hangi portlar arasında TIME_WAIT bağlantıları birikiyor:

ss -tan state time-wait | awk '{print $4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head -20

Eğer uygulama sunucunun portu (mesela 8080) bu listede üst sıralarda görünüyorsa, Nginx ile uygulama arasındaki bağlantılar düzgün kapatılmıyor ya da yeterince hızlı geri dönüştürülemiyor demektir.

Çözüm için sysctl parametrelerine bakman gerekir:

sysctl net.ipv4.tcp_tw_reuse
sysctl net.ipv4.tcp_fin_timeout
sysctl net.ipv4.ip_local_port_range

tcp_tw_reuse parametresini 1 yaparak TIME_WAIT soketlerinin yeni bağlantılar için yeniden kullanılmasını sağlayabilirsin. tcp_fin_timeout değerini 60’tan 30’a indirerek TIME_WAIT süresini kısaltabilirsin. Bu değişiklikleri yaparken dikkatli ol, yük dengeleyicisi arkasında NAT kullanan ortamlarda tcp_tw_reuse bazen sorun çıkarabilir.

Gerçek Dünya Senaryosu 2: CLOSE_WAIT Kabusu

Bu durum TIME_WAIT’ten daha sinsi. TIME_WAIT zamanla kendiliğinden kapanır. CLOSE_WAIT ise uygulama soketini kapatana kadar bekler. Yani uygulama bug’ı olmadan bu bağlantılar kapanmaz ve zamanla dosya tanımlayıcısı (file descriptor) tükenmesine yol açar.

ss -tnp state close-wait

Bu komuttaki -p parametresi hangi process’in bu soketleri tuttuğunu da gösterir. Çıktıda şuna benzer bir şey göreceksin:

State    Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
CLOSE_WAIT 1     0       192.168.1.10:8080   10.0.0.5:54321    users:(("java",pid=12345,fd=47))

PID’i öğrendikten sonra o process’in kaç tane açık dosya tanımlayıcısı olduğunu görmek için:

ls -l /proc/12345/fd | wc -l
cat /proc/12345/limits | grep "open files"

Eğer açık fd sayısı limite yaklaşıyorsa, uygulama kısa süre içinde yeni bağlantı kabul edemez hale gelecektir. Bu noktada uygulamayı yeniden başlatmak anlık çözüm olabilir, ama asıl sorun koddaki soket kapatma eksikliğidir.

ss Komutunun İleri Seviye Kullanımı

ss aracı çok güçlü filtreleme seçenekleri sunuyor. Günlük işlerde sık kullandığım kombinasyonları paylaşayım.

Belirli bir porta bağlı tüm bağlantıları göster, process bilgisiyle birlikte:

ss -tnp sport = :443

Belirli bir uzak IP adresinden gelen tüm bağlantıları filtrele:

ss -tn dst 10.0.0.0/24

Recv-Q değeri yüksek olan, yani uygulama tarafından okunmayı bekleyen veri birikmiş soketleri bul:

ss -tn | awk '$2 > 0 {print}' | head -20

Recv-Q değeri yüksek olan soketler, uygulamanın gelen veriyi işleyemediğini gösterir. Bu CPU darboğazı, kilit (lock) sorunu ya da thread havuzunun dolmuş olmasından kaynaklanabilir.

Send-Q değeri yüksek olan soketler ise karşı tarafın veriyi okuyamadığını, yani ağ yavaşlığı ya da karşı uygulama sorunu olduğunu gösterir:

ss -tn | awk '$3 > 0 {print}' | head -20

netstat ile Klasik Analiz

netstat hâlâ pek çok ortamda kullanılıyor. Temel parametrelerini hatırlayalım:

  • -t: Sadece TCP bağlantıları
  • -u: Sadece UDP bağlantıları
  • -n: İsimleri çözümleme, sayısal göster (훨씬 hızlı)
  • -p: Process bilgisini göster (root yetkisi gerekir)
  • -a: Tüm bağlantıları göster, LISTEN dahil
  • -l: Sadece LISTEN durumundaki soketleri göster

Hangi process hangi portu dinliyor, sık sorulan bir soru:

netstat -tlnp

Bir porta özel bakış:

netstat -tnp | grep :3306

Bağlantı durumlarını say ve sırala, klasik netstat yöntemiyle:

netstat -tan | awk '{print $6}' | sort | uniq -c | sort -rn

SYN Kuyruğu ve Backlog Sorunu

Yüksek trafikli sistemlerde sık karşılaşılan ama fark edilmesi zor bir sorun: SYN kuyruğunun dolması. Kernel, gelen SYN paketleri için bir kuyruk tutar. Bu kuyruk dolduğunda yeni bağlantılar reddedilir ya da sessizce düşürülür.

ss -lnt

Bu komutun çıktısında Recv-Q sütunu, LISTEN durumundaki soketlerde o anki SYN kuyruğu uzunluğunu gösterir. Send-Q ise maksimum backlog değerini. Eğer Recv-Q, Send-Q’ya yaklaşıyorsa sorun var demektir.

watch -n 1 'ss -lnt | grep :80'

Bu komutu çalıştırarak Recv-Q değerini gerçek zamanlı izleyebilirsin. Değer sürekli Send-Q’nun %70-80’ine yakınsa backlog değerini artırman gerekiyor. Nginx için listen direktifindeki backlog parametresini, sistem genelinde ise net.core.somaxconn sysctl değerini artırabilirsin.

Otomatik İzleme Script’i

Manuel komutlarla tek seferlik analiz yapabilirsin, ama production’da sürekli izleme için bir script işine yarar. İşte basit ama etkili bir izleme script’i:

#!/bin/bash

LOG_FILE="/var/log/socket_monitor.log"
THRESHOLD_TIMEWAIT=20000
THRESHOLD_CLOSEWAIT=500
THRESHOLD_ESTABLISHED=10000

timestamp=$(date '+%Y-%m-%d %H:%M:%S')

tw_count=$(ss -tan state time-wait | wc -l)
cw_count=$(ss -tan state close-wait | wc -l)
est_count=$(ss -tan state established | wc -l)
syn_recv=$(ss -tan state syn-recv | wc -l)

echo "[$timestamp] TW:$tw_count CW:$cw_count EST:$est_count SYN_RECV:$syn_recv" >> $LOG_FILE

if [ "$tw_count" -gt "$THRESHOLD_TIMEWAIT" ]; then
    echo "[$timestamp] UYARI: TIME_WAIT sayisi yuksek: $tw_count" >> $LOG_FILE
    ss -tan state time-wait | awk '{print $4}' | cut -d: -f2 | 
        sort | uniq -c | sort -rn | head -5 >> $LOG_FILE
fi

if [ "$cw_count" -gt "$THRESHOLD_CLOSEWAIT" ]; then
    echo "[$timestamp] KRITIK: CLOSE_WAIT sayisi yuksek: $cw_count" >> $LOG_FILE
    ss -tnp state close-wait | awk '{print $6}' | sort | uniq -c | sort -rn | head -5 >> $LOG_FILE
fi

if [ "$syn_recv" -gt 1000 ]; then
    echo "[$timestamp] KRITIK: SYN_RECV yuksek, SYN flood olmali: $syn_recv" >> $LOG_FILE
fi

Bu script’i crontab’a ekleyerek her dakika çalıştırabilirsin:

* * * * * /usr/local/bin/socket_monitor.sh

Bağlantı Yoğunluğunu IP Bazında Analiz Etme

Bir sunucuya çok sayıda bağlantı açan istemcileri bulmak istiyorsun, belki bir DDoS durumu söz konusu ya da runaway bir uygulama sürekli bağlantı açıyor:

ss -tn state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

Bu komut hangi uzak IP adresinin kaç tane bağlantısı olduğunu gösterir. Eğer tek bir IP’den 500-1000 bağlantı geliyorsa bu olağandışıdır.

Benzer şeyi netstat ile yapmak istersen:

netstat -tn | awk '/ESTABLISHED/ {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

Şüpheli bir IP bulduğunda anlık olarak ss ile tüm bağlantı detaylarını inceleyebilirsin:

ss -tnp dst 192.168.1.100

UDP Soketleri ve Recv-Q Dolması

TCP kadar dramatik değil ama UDP soketlerinde de sorun yaşanabilir. UDP Recv-Q dolduğunda paketler sessizce düşer, uygulama fark bile etmez. DNS sunucuları, log toplama sistemleri ve monitoring agent’ları bu durumdan sık etkilenir.

ss -unp

Recv-Q değeri sürekli yüksekse, ya uygulama pakatleri yeteri kadar hızlı işleyemiyor ya da SO_RCVBUF değeri çok küçük. İkinci durumda:

sysctl net.core.rmem_max
sysctl net.core.rmem_default

Bu değerleri artırarak UDP alım tampon boyutunu büyütebilirsin. Ama bu semptom giderme, uygulama neden pakatleri işleyemiyor sorusunu da araştırman gerekiyor.

Kernel İstatistikleriyle Derinlemesine Analiz

ss -s çıktısının ötesine geçmek istiyorsan, kernel’ın TCP istatistik sayaçlarına doğrudan bakabilirsin:

cat /proc/net/sockstat

Bu dosyanın çıktısı şuna benzer:

sockets: used 2145
TCP: inuse 1203 orphan 45 tw 398 alloc 1344 mem 892
UDP: inuse 8 mem 4
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

orphan değeri burada önemli. Orphan soketler, bir process’e bağlı olmayan ama kernel tarafından hâlâ tutulan TCP soketleridir. Yüksek orphan sayısı genellikle hızlı bağlantı kapama gerektiren yük altında, kernel’ın soketleri temizleyemediği durumlarda oluşur. net.ipv4.tcp_max_orphans sysctl değeri bu sayıyı sınırlar, aşıldığında kernel soketleri zorla kapatır ve log’a “too many orphaned sockets” yazar.

Daha detaylı TCP istatistikleri için:

ss -ti state established | head -30

Bu komut her bağlantı için RTT, yeniden gönderme sayısı, pencere boyutu gibi TCP seviyesi istatistikleri gösterir. Yüksek retransmit değerleri ağ kalitesi sorununa işaret eder.

Sorun Giderme Akışı

Yüksek bağlantı sayısı sorunuyla karşılaştığında izlemen gereken genel akış şu şekilde:

  • Önce ss -s ile genel duruma bak, hangi durum öne çıkıyor?
  • TIME_WAIT yüksekse: kaynak port tükenmesi mi, yoksa yavaş kapanma mı? ip_local_port_range ve tcp_fin_timeout değerlerini kontrol et
  • CLOSE_WAIT yüksekse: ss -tnp state close-wait ile hangi uygulama tuttuğunu bul, o uygulamanın kod gözden geçirilmesi şart
  • ESTABLISHED yüksekse: meşru trafik mi yoksa bağlantı sızıntısı mı? IP bazlı analiz yap
  • SYN_RECV yüksekse: SYN flood ihtimalini değerlendir, syncookies‘i kontrol et (sysctl net.ipv4.tcp_syncookies)
  • Recv-Q doluysa: uygulama performans sorunu, thread havuzu ya da işlem gecikmesi araştır
  • Orphan soket yüksekse: sistem geneli yük ve tcp_max_orphans değerini değerlendir

Sonuç

Ağ bağlantı sorunları, sistem yöneticilerinin en çok zaman harcadığı konulardan biri. Bunun temel nedeni, sorunun birçok farklı katmanda gizlenebilmesi. Uygulama seviyesi, kernel parametreleri, ağ altyapısı ya da karşı taraf sistemler: hepsi birbiriyle bağlantılı.

ss ve netstat, bu labirentin içinde sana net bir harita sunuyor. Bağlantı durumlarını doğru okumayı öğrendiğinde, TIME_WAIT ve CLOSE_WAIT arasındaki farkı kavradığında ve Recv-Q/Send-Q değerlerinin ne anlattığını anladığında, sorun giderme süresi dramatik şekilde kısalıyor.

Asıl önemli olan şu: bu araçları sadece sorun çıktığında değil, periyodik olarak kullan. Sisteminizin normal durumunda bu sayaçların ne gösterdiğini biliyor olmak, anormal durumu çok daha hızlı fark etmeni sağlar. Monitoring stack’ine soket durum istatistiklerini ekle, baseline oluştur ve sapmalar olduğunda haberdar ol. Yangın çıktıktan sonra koşmak yerine dumanı önceden görmek her zaman daha iyidir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir