awk ile Firewall Log Verilerinden Port Tarama ve Yetkisiz Erişim Girişimi Tespiti

Firewall loglarına baktığınızda genellikle şöyle bir his oluşur: binlerce satır, anlamsız görünen IP adresleri, port numaraları ve timestamp’ler. Oysa bu log satırlarının içinde çok değerli güvenlik bilgileri gizli. Birisi sisteminizi tarıyor mu? Hangi portlara erişmeye çalışıyor? Belirli bir IP’den anormal miktarda bağlantı denemesi var mı? Tüm bu soruların cevabı log dosyalarının içinde, sadece doğru araçla bakmanız gerekiyor. Bu yazıda awk komutunu kullanarak firewall loglarından port tarama tespiti ve yetkisiz erişim girişimlerini nasıl analiz edeceğimizi gerçek dünya senaryolarıyla ele alacağız.

Firewall Log Formatını Anlamak

Analiz yapmadan önce neyle çalıştığımızı anlamamız gerekiyor. Linux sistemlerde en yaygın firewall log formatları iptables/nftables logları ve ufw loglarıdır. Tipik bir iptables log satırı şöyle görünür:

Jan 15 03:24:11 webserver kernel: [UFW BLOCK] IN=eth0 OUT= MAC=... SRC=192.168.1.105 DST=10.0.0.1 LEN=44 TOS=0x00 PREC=0x00 TTL=241 ID=54321 PROTO=TCP SPT=54321 DPT=22 WINDOW=1024 RES=0x00 SYN URGP=0

Bu satırda işimize yarayacak alanlar şunlar:

  • SRC: Kaynak IP adresi
  • DST: Hedef IP adresi
  • PROTO: Protokol (TCP, UDP, ICMP)
  • SPT: Kaynak port
  • DPT: Hedef port (destination port)
  • SYN: TCP SYN flag (bağlantı başlatma)

awk bu yapıyı işlemek için biçilmiş kaftan çünkü alan bazlı parsing konusunda son derece güçlü. Hem whitespace hem de özel delimiter’larla rahatlıkla çalışabiliyor.

Temel awk Yapısı ile Log Parsing

Önce basit bir başlangıç yapalım. Log dosyasından sadece bloke edilen bağlantıları çekelim ve kaynak IP ile hedef portu gösterelim:

awk '/UFW BLOCK/ {
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    }
    print src, dpt
}' /var/log/ufw.log

Bu basit script bile size bloke edilen her bağlantının kaynak IP ve hedef portunu verir. Ama biz daha ileri gideceğiz. substr($i, 5) kullanımı burada kritik: SRC= 4 karakter olduğu için 5. karakterden itibaren okuyoruz, yani = işaretinden sonrasını alıyoruz.

Port Tarama Tespiti: Bir IP’den Gelen Farklı Port Denemeleri

Port taraması tespitinin temel mantığı şu: Normal bir kullanıcı belirli bir porta bağlanır, işini yapar, gider. Ama port tarayan biri kısa sürede onlarca farklı porta bağlanmaya çalışır. Bunu tespit etmek için bir IP adresinin kaç farklı porta erişim denediğini saymamız lazım:

awk '/UFW BLOCK/ && /PROTO=TCP/ {
    src = ""; dpt = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    }
    if(src != "" && dpt != "") {
        key = src ":" dpt
        if(!seen[key]++) {
            port_count[src]++
        }
    }
}
END {
    for(ip in port_count) {
        if(port_count[ip] >= 10) {
            print port_count[ip], "ports ->", ip
        }
    }
}' /var/log/ufw.log | sort -rn

Bu script her IP’nin kaç farklı porta dokunduğunu sayıyor ve 10 veya daha fazla porta deneyen IP’leri listeliyor. seen[key]++ kısmı aynı IP’nin aynı porta birden fazla denemesini tekrar saymıyor, sadece benzersiz port sayısını tutuyoruz.

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

87 ports -> 185.220.101.45
43 ports -> 91.108.56.33
28 ports -> 194.165.16.11

İlk satırdaki IP 87 farklı porta deneme yapmış. Bu kesinlikle port taraması.

Zaman Bazlı Analiz: Kısa Sürede Yoğun Deneme Tespiti

Port taramasının bir diğer belirtisi kısa sürede çok fazla deneme yapılmasıdır. Bir IP’nin dakika başına kaç bağlantı denemesi yaptığını görelim:

awk '/UFW BLOCK/ {
    # Timestamp parse: "Jan 15 03:24:11"
    timestamp = $1 " " $2 " " $3
    src = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
    }
    # Sadece saat ve dakikayı al (saniyeyi bırak)
    split($3, time_parts, ":")
    minute_key = $1 " " $2 " " time_parts[1] ":" time_parts[2]
    if(src != "") {
        attempts[src][minute_key]++
    }
}
END {
    for(ip in attempts) {
        for(minute in attempts[ip]) {
            count = attempts[ip][minute]
            if(count >= 20) {
                printf "%-20s %-20s %d attempts/minn", ip, minute, count
            }
        }
    }
}' /var/log/ufw.log | sort -k3 -rn

Dakikada 20 ve üzeri deneme yapan IP’ler gerçekten ciddi bir tehdit sinyali. Bu threshold’u ortamınıza göre ayarlayabilirsiniz.

SSH Brute Force Tespiti

SSH brute force saldırıları firewall loglarında çok belirgin görünür. Port 22’ye yönelik yoğun bloke işlemleri var mı bakalım:

awk '/UFW BLOCK/ && /DPT=22/ {
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
    }
    if(src != "") ssh_attempts[src]++
}
END {
    print "SSH Brute Force Suspects:"
    print "========================="
    for(ip in ssh_attempts) {
        if(ssh_attempts[ip] >= 5) {
            printf "%-20s %d blocked attemptsn", ip, ssh_attempts[ip]
        }
    }
}' /var/log/ufw.log | sort -k2 -rn

Bu basit ama etkili bir script. Çıktıda gördüğünüz her IP için fail2ban veya manuel iptables -A INPUT -s -j DROP ile aksiyon alabilirsiniz.

Gerçek Dünya Senaryosu: Gece Yarısı Saldırısı Analizi

Diyelim ki sabah geldiniz, monitoring sisteminden alert aldınız. Gece 02:00-04:00 arasında yoğun firewall aktivitesi var. Logları belirli zaman dilimine göre filtreleyelim ve ne olduğunu anlayalım:

awk '
/UFW BLOCK/ {
    # Saat bilgisini al
    split($3, t, ":")
    hour = t[1] + 0
    
    # Gece 02:00-04:00 arası mı?
    if(hour >= 2 && hour < 4) {
        src = ""; dpt = ""; proto = ""
        for(i=1; i<=NF; i++) {
            if($i ~ /^SRC=/) src = substr($i, 5)
            if($i ~ /^DPT=/) dpt = substr($i, 5)
            if($i ~ /^PROTO=/) proto = substr($i, 6)
        }
        if(src != "") {
            ip_stats[src]["count"]++
            ip_stats[src]["proto_" proto]++
            port_list[src] = port_list[src] " " dpt
        }
    }
}
END {
    print "=== Gece 02:00-04:00 Aktivite Raporu ==="
    for(ip in ip_stats) {
        count = ip_stats[ip]["count"]
        if(count >= 15) {
            printf "nIP: %s | Toplam Deneme: %dn", ip, count
            printf "TCP: %d | UDP: %dn", 
                ip_stats[ip]["proto_TCP"]+0, 
                ip_stats[ip]["proto_UDP"]+0
        }
    }
}' /var/log/ufw.log

Bu script size gece o saatlerde kim ne yapıyordu sorusunun cevabını verir. +0 kullanımı AWK’ta tanımsız bir array elemanını sayısal 0 olarak kullanmak için güzel bir trick.

Hedef Port Dağılımı: Hangi Servisler Hedef Alınıyor?

Saldırganların hangi portları hedef aldığını bilmek savunma stratejinizi şekillendirir. En çok hedef alınan portları bulmak için:

awk '/UFW BLOCK/ {
    dpt = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    }
    if(dpt != "") port_hits[dpt]++
}
END {
    # Port servis isimlerini manuel map edelim
    services[22]   = "SSH"
    services[80]   = "HTTP"
    services[443]  = "HTTPS"
    services[3306] = "MySQL"
    services[5432] = "PostgreSQL"
    services[6379] = "Redis"
    services[8080] = "HTTP-Alt"
    services[27017]= "MongoDB"
    services[3389] = "RDP"
    services[23]   = "Telnet"
    services[21]   = "FTP"
    
    for(port in port_hits) {
        svc = (port in services) ? services[port] : "Unknown"
        printf "%6d hits | Port %-6s | %sn", port_hits[port], port, svc
    }
}' /var/log/ufw.log | sort -rn | head -20

Çıktıdan şöyle bir tablo ortaya çıkabilir ve Redis veya MongoDB portlarına çok fazla deneme varsa bu ciddi bir uyarı işareti.

Coğrafi Dağılım İçin IP Prefix Analizi

Tam bir GeoIP entegrasyonu olmadan bile IP adreslerinin /24 subnet dağılımına bakarak saldırıların belirli ağlardan gelip gelmediğini anlayabilirsiniz:

awk '/UFW BLOCK/ {
    src = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
    }
    if(src != "") {
        # /24 subnet al (ilk 3 octet)
        n = split(src, octets, ".")
        if(n == 4) {
            subnet = octets[1] "." octets[2] "." octets[3] ".0/24"
            subnet_count[subnet]++
        }
    }
}
END {
    print "En Cok Saldiri Yapan Subnetler:"
    print "================================"
    for(subnet in subnet_count) {
        if(subnet_count[subnet] >= 10) {
            printf "%-20s %d attacksn", subnet, subnet_count[subnet]
        }
    }
}' /var/log/ufw.log | sort -k2 -rn | head -15

Eğer belirli bir /24 bloğundan yüzlerce saldırı geliyorsa, tüm o subnet’i bloklayabilirsiniz. Bu özellikle Tor exit node’ları veya bilinen kötü niyetli ASN’lerden gelen trafiği temizlemek için işe yarar.

Otomasyon: Günlük Güvenlik Raporu Script’i

Şimdiye kadar öğrendiklerimizi bir araya getirelim ve her gün otomatik çalışacak bir rapor script’i yazalım:

#!/bin/bash
# /usr/local/bin/firewall-daily-report.sh

LOGFILE="/var/log/ufw.log"
REPORT_DATE=$(date '+%Y-%m-%d')
REPORT_FILE="/var/log/security-reports/fw-report-${REPORT_DATE}.txt"

mkdir -p /var/log/security-reports

{
echo "========================================"
echo "Firewall Guvenlik Raporu: $REPORT_DATE"
echo "========================================"

echo ""
echo "--- PORT TARAMA SUPHELILERI (10+ farkli port) ---"
awk '/UFW BLOCK/ && /PROTO=TCP/ {
    src = ""; dpt = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    }
    if(src != "" && dpt != "") {
        key = src ":" dpt
        if(!seen[key]++) port_count[src]++
    }
}
END {
    for(ip in port_count)
        if(port_count[ip] >= 10)
            printf "%-20s %d unique portsn", ip, port_count[ip]
}' "$LOGFILE" | sort -k2 -rn | head -10

echo ""
echo "--- SSH BRUTE FORCE (5+ deneme) ---"
awk '/UFW BLOCK/ && /DPT=22/ {
    for(i=1; i<=NF; i++)
        if($i ~ /^SRC=/) src = substr($i, 5)
    if(src != "") count[src]++
}
END {
    for(ip in count)
        if(count[ip] >= 5)
            printf "%-20s %d attemptsn", ip, count[ip]
}' "$LOGFILE" | sort -k2 -rn | head -10

echo ""
echo "--- EN COK HEDEFLENEN PORTLAR ---"
awk '/UFW BLOCK/ {
    for(i=1; i<=NF; i++)
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    if(dpt != "") hits[dpt]++
}
END {
    for(p in hits) printf "%6d %sn", hits[p], p
}' "$LOGFILE" | sort -rn | head -10

echo ""
echo "--- OZET ISTATISTIKLER ---"
awk '/UFW BLOCK/ {total++}
     END {print "Toplam bloke edilen baglanti:", total}' "$LOGFILE"

} > "$REPORT_FILE"

# Mail gondermek istiyorsaniz:
# mail -s "Firewall Raporu $REPORT_DATE" [email protected] < "$REPORT_FILE"

echo "Rapor olusturuldu: $REPORT_FILE"

Bu script’i crontab’a ekleyin:

# Her sabah 07:00'de calistir
0 7 * * * /usr/local/bin/firewall-daily-report.sh

Pratik Ipuçları ve Dikkat Edilmesi Gerekenler

Gerçek ortamda bu script’leri kullanırken birkaç önemli noktaya dikkat etmeniz gerekiyor.

Log rotasyonu: UFW ve iptables logları genellikle /var/log/ufw.log, /var/log/ufw.log.1, /var/log/ufw.log.2.gz gibi rotate edilir. Birden fazla dosyayı analiz etmek için:

# Guncel ve bir onceki log dosyasini birlikte analiz et
awk '/UFW BLOCK/ {print}' /var/log/ufw.log /var/log/ufw.log.1 | 
awk '{
    for(i=1; i<=NF; i++)
        if($i ~ /^SRC=/) count[substr($i,5)]++
}
END {
    for(ip in count)
        if(count[ip] > 50) print count[ip], ip
}' | sort -rn

False positive yönetimi: Bazı IP’ler monitoring sistemleri veya CDN’ler olabilir. Bu IP’leri whitelist’e almak için:

awk 'BEGIN {
    # Bilinen guvenli IP'leri atla
    whitelist["10.0.0.1"] = 1
    whitelist["192.168.1.1"] = 1
}
/UFW BLOCK/ {
    src = ""
    for(i=1; i<=NF; i++)
        if($i ~ /^SRC=/) src = substr($i, 5)
    if(src != "" && !(src in whitelist))
        count[src]++
}
END {
    for(ip in count)
        if(count[ip] > 100) print count[ip], ip
}' /var/log/ufw.log | sort -rn

Performans: Büyük log dosyalarında (100MB+) awk oldukça hızlı çalışır ama gereksiz yere tüm alanları parse etmekten kaçının. Sadece ihtiyacınız olan alanları işleyin.

nftables logları: Eğer modern sistemlerde nftables kullanıyorsanız log formatı biraz farklıdır. IN=, SRC=, DPT= alanları benzer şekilde yer alır ama prefix farklı olabilir. Script’lerinizi test ortamında mutlaka doğrulayın.

Tespit Sonrası Aksiyon

Şüpheli IP’leri tespit ettikten sonra ne yapacaksınız? awk çıktısını doğrudan iptables kurallarına besleyebilirsiniz:

# Port tarama tespiti yap ve otomatik blokla
awk '/UFW BLOCK/ && /PROTO=TCP/ {
    src = ""; dpt = ""
    for(i=1; i<=NF; i++) {
        if($i ~ /^SRC=/) src = substr($i, 5)
        if($i ~ /^DPT=/) dpt = substr($i, 5)
    }
    key = src ":" dpt
    if(src != "" && !seen[key]++) port_count[src]++
}
END {
    for(ip in port_count)
        if(port_count[ip] >= 15) print ip
}' /var/log/ufw.log | while read suspicious_ip; do
    echo "Blocking: $suspicious_ip"
    ufw deny from "$suspicious_ip" to any
done

Bu komutu doğrudan production’da çalıştırmadan önce mutlaka dry-run yapın. Whitelist’inizi kontrol edin, kendi IP’nizi bloklamak istemezsiniz.

Sonuç

awk ile firewall log analizi yapmak, pahalı SIEM çözümlerine muhtaç kalmadan oldukça güçlü güvenlik görünürlüğü sağlar. Öğrendiğimiz teknikleri özetlersek:

  • Tek bir IP’den gelen farklı port denemelerini sayarak port tarama tespiti yapabilirsiniz.
  • Zaman bazlı analiz ile kısa süredeki yoğun aktiviteyi yakalayabilirsiniz.
  • SSH, veritabanı ve diğer kritik servisler için hedef bazlı izleme kurabilirsiniz.
  • Tüm bunları birleştirerek otomatik günlük raporlar üretebilirsiniz.
  • Tespit edilen IP’leri otomatik olarak bloklama sürecine dahil edebilirsiniz.

awk öğrenme eğrisi biraz dikkat gerektiriyor ama bir kez kavrayınca log analizi için vazgeçilmez bir araç haline geliyor. Üstelik her Linux sistemde hazır bulunuyor, ek kurulum gerektirmiyor. Güvenlik olaylarında ilk müdahale sırasında bu tür basit ama etkili araçlara sahip olmak gerçekten hayat kurtarıcı olabiliyor.

Kendi script’lerinizi geliştirirken küçük başlayın, test ortamında doğrulayın ve yavaş yavaş karmaşıklaştırın. Log formatları sistem ve dağıtıma göre değişebildiğinden, script’lerinizi kendi ortamınızdaki gerçek log örnekleri üzerinde test etmeyi unutmayın.

Bir yanıt yazın

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