tcpdump ve Wireshark Olmadan Sadece /proc/net ile Ağ Durumunu Analiz Etme

Bir sunucuda acil bir ağ sorunu var, ekip panikliyor ve sen SSH ile bağlısın. tcpdump yok, wireshark zaten yok, netstat bile deprecated uyarısı veriyor. Ne yaparsın? İşte tam bu noktada /proc/net dizini hayat kurtarıcı olur. Linux çekirdeği, ağ durumuna dair inanılmaz miktarda bilgiyi bu sanal dosya sisteminde tutuyor ve bunu okumak için ekstra araç kurmanıza gerek yok, sadece cat, grep, awk ve biraz bilgi yeterli.

Bu yazıda /proc/net altındaki dosyaları gerçek senaryolarla nasıl kullanacağınızı anlatacağım. Hem acil durumlarda hem de rutin izleme süreçlerinde işinize yarayacak pratik bilgiler bunlar.

/proc/net Nedir ve Neden Önemli?

/proc dosya sistemi, Linux çekirdeğinin kullanıcı alanına sunduğu sanal bir arayüzdür. Disk üzerinde gerçek bir dosya yoktur, çekirdek bu dosyaları siz okurken anlık olarak oluşturur. /proc/net ise özellikle ağ katmanına ait istatistiklerin ve durum bilgilerinin tutulduğu alt dizindir.

ss ve ip komutları zaten arka planda bu dosyaları okuyor. Yani aslında her gün dolaylı olarak kullandığınız bir şeyi direkt olarak kullanmayı öğreniyorsunuz. Bunu anlamak, araç bağımlılığınızı azaltır ve sorunları daha derinlemesine kavramanızı sağlar.

ls /proc/net/

Çıktıya baktığınızda onlarca dosya görürsünüz: tcp, tcp6, udp, udp6, unix, arp, dev, if_inet6, route, sockstat, netstat ve daha fazlası. Her biri ayrı bir hikaye anlatır.

Açık Bağlantıları ve Soketleri İncelemek

/proc/net/tcp ve /proc/net/tcp6

Bu iki dosya, sistemdeki tüm TCP soket durumlarını içerir. Ham hali biraz korkutucu görünebilir:

cat /proc/net/tcp

Çıktı şöyle bir şey olur:

  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 0100007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000   101        0 20547 1 0000000000000000 100 0 0 10 0

Bu hex değerler gözünüzü korkutmasın. local_address ve rem_address alanları IP:PORT formatında ama hex olarak yazılmış. st ise soket durumu, yine hex. Ve dikkat: IP adresi little-endian byte sırası ile yazılıyor, yani tersine çevirmeniz gerekiyor.

Durum kodlarını bilmek kritik:

  • 0A: LISTEN
  • 01: ESTABLISHED
  • 06: TIME_WAIT
  • 0B: CLOSE_WAIT
  • 02: SYN_SENT
  • 03: SYN_RECV
  • 08: CLOSE_WAIT

Şimdi bunu insanın okuyabileceği hale getirelim. Aşağıdaki küçük awk betiği, /proc/net/tcp dosyasını parse edip okunabilir çıktı üretir:

awk 'NR>1 {
    split($2, a, ":");
    split($3, b, ":");
    
    # Local IP (little-endian hex to dotted decimal)
    lport = strtonum("0x" a[2]);
    rport = strtonum("0x" b[2]);
    
    # State
    state = $4;
    
    printf "LocalPort: %d | RemotePort: %d | State: %sn", lport, rport, state;
}' /proc/net/tcp

Ama IP adresini de düzgün çözmek istiyorsanız daha gelişmiş bir yaklaşım gerekiyor. Şu Python one-liner çok daha temiz iş yapar:

python3 -c "
import socket, struct

def hex_to_ip(hex_str):
    addr = int(hex_str, 16)
    return socket.inet_ntoa(struct.pack('<I', addr))

def hex_to_port(hex_str):
    return int(hex_str, 16)

states = {
    '01': 'ESTABLISHED', '02': 'SYN_SENT', '03': 'SYN_RECV',
    '04': 'FIN_WAIT1', '05': 'FIN_WAIT2', '06': 'TIME_WAIT',
    '07': 'CLOSE', '08': 'CLOSE_WAIT', '09': 'LAST_ACK',
    '0A': 'LISTEN', '0B': 'CLOSING'
}

with open('/proc/net/tcp') as f:
    next(f)
    for line in f:
        parts = line.split()
        local = parts[1].split(':')
        remote = parts[2].split(':')
        state = states.get(parts[3], parts[3])
        lip = hex_to_ip(local[0])
        lport = hex_to_port(local[1])
        rip = hex_to_ip(remote[0])
        rport = hex_to_port(remote[1])
        print(f'{lip}:{lport} -> {rip}:{rport} [{state}]')
"

Bu script sayesinde artık gerçek IP adresleri ve portları görebilirsiniz. Bir web sunucusunda kaç tane ESTABLISHED bağlantı var, kaç tane TIME_WAIT birikmiş, bunları anında görebilirsiniz.

CLOSE_WAIT Kabusunu Tespit Etmek

Gerçek dünyadan bir senaryo: Uygulama yavaşlamış, ekip “sunucu yavaş, ne yapacağız” diye bağırmakta. İlk baktığınız şey şu olmalı:

grep " 08 " /proc/net/tcp | wc -l

08 durumu CLOSE_WAIT demek. Eğer bu sayı yüzlerle, binlerle ifade ediliyorsa sorun açık: Uygulama soketi düzgün kapatmıyor. Bu genellikle Java veya Python uygulamalarında eksik finally bloğundan ya da bağlantı havuzu yönetimindeki hatalardan kaynaklanır. tcpdump’a gerek yok, iki saniyede tespit ettiniz.

Ağ Arayüzü İstatistikleri: /proc/net/dev

Bu dosya, her ağ arayüzü için paket ve byte istatistiklerini tutar. ifconfig veya ip -s link komutlarının gösterdiği şeyin ham kaynağı burası.

cat /proc/net/dev

Çıktı şöyle görünür:

Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:  185432    2156    0    0    0     0          0         0   185432    2156    0    0    0     0       0          0
  eth0: 982451234  847293    0    2    0     0          0         0 123456789  654321    0    0    0     0       0          0

Buradaki errs ve drop sütunları kritik. Sürekli artan hata sayıları, NIC sorununa, kötü kabloya ya da ağ donanımı problemine işaret edebilir.

Bunu izlemek için basit bir döngü yazabilirsiniz:

# eth0 üzerindeki drop sayısını 5 saniyede bir izle
while true; do
    drops=$(awk '/eth0/ {print $5}' /proc/net/dev)
    echo "$(date '+%H:%M:%S') - Drop count: $drops"
    sleep 5
done

Eğer drop sayısı sürekli artıyorsa, bu ethtool ile ring buffer boyutunu artırmanız ya da sysctl ile network ayarlarını yapmanız gerektiğine işaret eder. Ve siz bunu tcpdump çalıştırmadan, sadece /proc/net/dev okuyarak tespit ettiniz.

ARP Tablosunu Okumak: /proc/net/arp

ARP tablosu, IP adresleri ile MAC adresleri arasındaki eşleştirmeleri tutar. Özellikle aynı ağdaki makineler arasında bağlantı sorunu yaşandığında buraya bakın.

cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.1.1      0x1         0x2         aa:bb:cc:dd:ee:ff     *        eth0
192.168.1.50     0x1         0x0         00:00:00:00:00:00     *        eth0

Burada Flags sütununa dikkat edin:

  • 0x2: Geçerli (complete) bir ARP kaydı
  • 0x0: Eksik (incomplete) kayıt, bu cihaza ulaşılamıyor demektir

192.168.1.50 için 0x0 görüyorsanız, o makineye ping atıyorsunuzdur ama ARP cevabı gelmiyor. Makine kapalı, ağ bağlantısı yok ya da firewall ARP paketlerini blokluyordur.

# Erişilemeyen (incomplete) ARP kayıtlarını filtrele
awk '$3 == "0x0" {print "Erişilemiyor:", $1}' /proc/net/arp

Soket İstatistikleri Özeti: /proc/net/sockstat

Bu dosya, sistemdeki soketlerin genel istatistiklerini tek bir yerde gösterir. Bir sistemin genel ağ sağlığını hızlıca değerlendirmek için mükemmel bir başlangıç noktasıdır.

cat /proc/net/sockstat
sockets: used 1234
TCP: inuse 89 orphan 3 tw 145 alloc 92 mem 24
UDP: inuse 12 mem 4
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

Bu çıktıdaki önemli değerler:

  • TCP inuse: Aktif kullanımdaki TCP soket sayısı
  • TCP orphan: Sahipsiz TCP soketi (hiçbir process ile ilişkilendirilmemiş), yüksekse sorun var
  • TCP tw: TIME_WAIT durumundaki soket sayısı
  • TCP alloc: Ayrılmış toplam TCP soket sayısı

orphan değeri sürekli yüksekse ve artıyorsa, sistem soketleri düzgün kapatamıyor demektir. Bu genellikle yoğun trafik altındaki web sunucularında görülür ve sysctl net.ipv4.tcp_max_orphans ayarını gözden geçirmeniz gerekebilir.

Routing Tablosunu Okumak: /proc/net/route

ip route komutunun arka planda okuduğu kaynak:

cat /proc/net/route
Iface   Destination Gateway     Flags   RefCnt  Use Metric  Mask        MTU Window  IRTT
eth0    00000000    0101A8C0    0003    0       0   100     00000000    0   0       0
eth0    0000A8C0    00000000    0001    0       0   100     00FFFFFF    0   0       0

Yine hex format. Destination ve Gateway alanları little-endian hex. 00000000 destination ile 0003 flag kombinasyonu default route’u gösterir (UG flag).

Bunu okunabilir hale getirmek için:

awk 'NR>1 {
    cmd = "printf "%d.%d.%d.%d" 0x" substr($2,7,2) " 0x" substr($2,5,2) " 0x" substr($2,3,2) " 0x" substr($2,1,2);
    cmd | getline dest;
    close(cmd);
    
    cmd = "printf "%d.%d.%d.%d" 0x" substr($3,7,2) " 0x" substr($3,5,2) " 0x" substr($3,3,2) " 0x" substr($3,1,2);
    cmd | getline gw;
    close(cmd);
    
    printf "Iface: %s | Dest: %s | GW: %s | Metric: %sn", $1, dest, gw, $7;
}' /proc/net/route

Routing sorunlarında bu dosyayı okumak, default gateway’in yerinde olup olmadığını, beklenmedik route’ların eklenip eklenmediğini anlamanıza yardımcı olur.

Unix Domain Soketleri: /proc/net/unix

Sadece TCP/UDP değil, local Unix soketleri de burada. Özellikle servisler arası iletişimde (örneğin PHP-FPM ve Nginx arasındaki soket bağlantısı) sorun yaşandığında buraya bakın.

cat /proc/net/unix | grep -E "(nginx|php|mysql|postgres)"

Eğer beklediğiniz soket burada görünmüyorsa, servis ya başlamamış ya da soket dosyasını oluşturamamış demektir. systemctl status ile anlamak yerine, direkt çekirdek düzeyinde soket varlığını teyit etmiş olursunuz.

Gerçek Dünya Senaryosu: Uygulamaya Bağlantı Sorunu

Diyelim ki bir microservice geçen geceden beri “bağlantı kurulamıyor” hatası veriyor. Şu adımları /proc/net ile takip edin:

Adım 1: Servisin gerçekten dinliyor olup olmadığını kontrol et.

# Port 8080'i dinleyen soket var mı?
awk 'NR>1 {
    split($2, a, ":");
    port = strtonum("0x" a[2]);
    state = $4;
    if (port == 8080 && state == "0A") print "Port 8080 LISTEN durumunda";
}' /proc/net/tcp

Eğer bu çıktı boşsa, uygulama 8080’i dinlemiyor. Konfigürasyon hatası veya uygulama çökmüş.

Adım 2: Mevcut bağlantı sayısını kontrol et.

awk 'NR>1 {
    split($2, a, ":");
    port = strtonum("0x" a[2]);
    state = $4;
    if (port == 8080) states[state]++;
} END {
    for (s in states) print s": "states[s];
}' /proc/net/tcp

Adım 3: Drop sayısını anlık izle.

watch -n 1 'awk "/eth0/ {print "RX drops:", $5, "TX drops:", $16}" /proc/net/dev'

Bu üç adımla tcpdump çalıştırmadan paketin nerede kaybolduğunu ya da soketin neden cevap vermediğini büyük ölçüde anlayabilirsiniz.

/proc/net/netstat ve /proc/net/snmp

Bu iki dosya, TCP/IP yığınının detaylı istatistiklerini içerir. netstat -s komutunun arka planda kullandığı kaynaklardır.

grep -E "^TcpExt" /proc/net/netstat | head -1  # Alan adları
grep -E "^TcpExt" /proc/net/netstat | tail -1  # Değerler

Özellikle şu değerlere dikkat edin:

# Retransmit sayısı
grep "RetransSegs" /proc/net/snmp

# SYN Cookie kullanımı (SYN flood göstergesi)
grep "SyncookiesSent" /proc/net/netstat

# Out of memory durumları
grep "TCPMemoryPressures" /proc/net/netstat

Eğer SyncookiesSent değeri artıyorsa, sunucunuz SYN flood saldırısı altında olabilir ya da çok fazla yarım kalmış bağlantı birikmiştir. RetransSegs artıyorsa ağ kalitesi kötüdür.

Pratik Bir İzleme Betiği

Tüm bunları bir araya getiren, günlük izlemede kullanabileceğiniz basit bir betik:

#!/bin/bash
# /proc/net quickcheck - Hızlı ağ durumu özeti

echo "=== Soket Özeti ==="
cat /proc/net/sockstat | grep -E "^(TCP|UDP|sockets)"

echo ""
echo "=== TCP Durum Dağılımı ==="
states=("01:ESTABLISHED" "06:TIME_WAIT" "08:CLOSE_WAIT" "0A:LISTEN" "02:SYN_SENT")
for pair in "${states[@]}"; do
    code="${pair%%:*}"
    name="${pair##*:}"
    count=$(grep -c " $code " /proc/net/tcp 2>/dev/null || echo 0)
    echo "  $name: $count"
done

echo ""
echo "=== Arayüz Hataları ==="
awk 'NR>2 {
    gsub(/:/, " ");
    if ($5 > 0 || $4 > 0) 
        printf "  %s -> RX errors: %s, drops: %sn", $1, $4, $5;
}' /proc/net/dev

echo ""
echo "=== Eksik ARP Kayıtları ==="
awk '$3 == "0x0" {print "  Erişilemiyor:", $1}' /proc/net/arp

Bu betiği cron ile dakikada bir çalıştırıp çıktısını loglamak, size zaman serisi verisi sağlar. Sorun olduğunda “o saatte ne oluyordu?” sorusuna cevap verebilirsiniz.

Sonuç

/proc/net dizini, Linux’un ağ altyapısına açılan doğrudan bir penceredir. tcpdump, wireshark, hatta netstat olmadan ciddi bir ağ analizi yapabilirsiniz. Bunun için gereken tek şey, çekirdek veri yapılarını nasıl okuyacağınızı bilmek ve biraz awk/python ile bu ham veriyi anlamlı hale getirebilmek.

Acil durumlarda araç eksikliği sizi çaresiz bırakmamalı. Gerçek şu ki, “araç yok” demek aslında “bilgi yok” anlamına geliyor çoğu zaman. /proc/net her sistemde var, çekirdek 2.6’dan beri bu dosyalar bu formatta mevcut. Bir sonraki ağ sorununda, önce buraya bakın. Çoğu zaman ihtiyacınız olan her şeyi burada bulacaksınız.

Son bir not: Bu dosyaları okurken anlık snapshot aldığınızı unutmayın. Ağ durumu sürekli değişiyor, bu yüzden watch ile periyodik okuma yapmak veya betiklerinizde zaman damgası kullanmak, doğru analiz için kritik önem taşıyor.

Bir yanıt yazın

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