İçeriğe geç
NetDevOps
6 dk okuma Ağ Yönetimi

eBPF XDP ile Linux'de Yuksek Performansli Paket Isleme

Linux'un standart ağ yığını paketleri DMA transferinden sonra sk_buff yapısına alır, sonra netfilter, TCP/IP stack ve socket katmanlarından geçirir. Her katman gecikme ve CPU yükü ekler. eBPF tabanlı XDP (eXpress Data Path) paketi NIC sürücüsünde, sk_buff ayrılmadan önce yakalar. Bu erken noktada karar milisaniyeler yerine mikrosaniyelerle alınır.

Linux 4.18 ile gelen bpfilter çekirdek alt sistemi iptables uyumlu kuralları eBPF bayt koduna çevirir. Her paket için sırayla kural zinciri taramak yerine bpfilter kuralları yüklenme sırasında optimize edilmiş bayt koduna derlenir. Paket başına işlem süresi beş ila on kat düşer. Ama bpfilter hâlâ deneysel; NAT, mangle tablosu ve karmaşık eşleştirme uzantıları desteklenmez. Genel amaçlı güvenlik duvarı için nftables ile BPF kombinasyonu daha olgun bir seçenek.

XDP nasil calisiyor

Bir NIC veri çerçevesini DMA ile aldığında sürücü önce descriptor ring'i okur. XDP bu noktada devreye girer. Paket ham tampon bellekte dururken eBPF programı başlar. Çekirdeğin ağ katmanı tarafından ayrıştırılmış meta veri henüz mevcut değildir.

eBPF doğrulayıcısı programı çekirdeğe yüklemeden önce statik analiz yapar. Sonsuz döngüleri, sınır dışı bellek erişimlerini ve geçersiz talimatları reddeder. Bir program sınır denetimi atlarsa doğrulayıcı reddeder ve program yüklenmez.

Üç mod var. Native modda program ağ arabirim kartının kendi sürücüsünde çalışır, en yüksek performansı sunar ama tüm sürücüler desteklemez (ixgbe, i40e, mlx5, virtio_net, veth destekler). Generic modda çekirdeğin ağ yığını XDP programını emüle eder, sk_buff zaten ayrılmıştır ama tüm ağ arabirimleriyle çalışır. Offloaded modda program doğrudan NIC üzerinde çalışır, CPU'ya yük binmez, Netronome NFP ve NVIDIA BlueField gibi SmartNIC'ler destekler.

Dort donus kodu

Bir XDP programı paket üzerinde dört karar verebilir.

XDP_DROP paketi en erken aşamada düşürür. DDoS koruması için temel mekanizma. Yalnızca birkaç yüz CPU çevrimi harcar.

XDP_PASS normal çekirdek ağ yığına gönderir. Program paket içeriğini değiştirdikten sonra bu aksiyonu dönebilir.

XDP_TX paketi aynı NIC üzerinden geri gönderir. ICMP echo-request'i echo-reply'e çevirip aynı arabirimden yollamak gibi senaryolarda kullanılır.

XDP_REDIRECT paketi başka bir NIC'e veya AF_XDP soketine yönlendirir. Load balancer yazılıyorsa bu en iyi seçenektir.

XDP_ABORTED hata durumu, XDP_DROP gibi işlenir ama bir izleme olayı tetikler.

Kod ornegi

XDP programları C dilinde yazılır, clang ile eBPF bayt koduna derlenir. En basit örnek tüm ICMP paketlerini düşürür:

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(key_size, sizeof(__u32));
    __uint(value_size, sizeof(__u64));
    __uint(max_entries, 1);
} icmp_drops SEC(".maps");

SEC("xdp")
int drop_icmp(struct xdp_md *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;

    if ((void *)(eth + 1) > data_end)
        return XDP_PASS;

    if (eth->h_proto != htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > data_end)
        return XDP_PASS;

    if (ip->protocol == IPPROTO_ICMP) {
        __u32 key = 0;
        __u64 *n = bpf_map_lookup_elem(&icmp_drops, &key);
        if (n)
            __sync_fetch_and_add(n, 1);
        return XDP_DROP;
    }

    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

Derleme ve yükleme:

clang -O2 -g -target bpf -c xdp_drop.c -o xdp_drop.o
ip link set dev eth0 xdpgeneric obj xdp_drop.o sec xdp

Geliştirme ortamı için clang, llvm, libbpf, libxdp ve bpftool gerekir. Debian tabanlı sistemlerde:

apt-get install clang llvm libbpf-dev libxdp-dev xdp-tools bpftool

Durumu kontrol etmek için ip link show eth0 çıktısında xdp/id:XXX ibaresi görülür. bpftool prog show çalışan programları listeler.

Rakamlarla performans

Bir sunucu üzerinde test ettiğimde şöyle sonuçlar aldım. İptables aynı koşullarda saniyede 3 milyon paketi zor işliyordu. XDP ile on milyonlarca paketi düşürmek aynı donanımda mümkün. Tabii bu basit drop mantığı için geçerli; karmaşık paket ayrıştırma ekleyince rakamlar düşer.

Modern donanımda native XDP ile saniyede 10 ila 25 milyon paket düşürmek mümkün. Aynı ortamda iptables 0,5 ila 2 milyon paketle sınırlı kalır. XDP bu farkı tamamen erken noktada karar alarak elde ediyor.

Sinirlari

XDP her sorunun çözümü değil. Karmaşık stateful mantık, uygulama katmanı incelemesi veya bağlantı izleme gerektiren senaryolarda nftables veya iptables hâlâ daha uygun. XDP en erken aşamada çalıştığı için bağlantı takibi yapamaz; bağlantı durumu paketlerin sırasını ve durum bilgisini gerektirir ve bu bilgi henüz ayrıştırılmamıştır. Stateful fallback için XDP'yi TC veya netfilter ile kombinasyon kullanmak gerekir.

Üretimde kullanmak için tek başına bpftool yeterli değil. Cilium, Katran, Cloudflare L4Drop gibi projeler bir daemon ile BPF haritasını yönetir. Bu daemon filtre kurallarını haritaya yazar, XDP programı paket başına haritadan okur. Kuralları güncellemek daemon'u yeniden başlatmadan map güncellemesiyle olur.

Bir sunucu yeniden başlattığında XDP programını otomatik yüklemesi gerekiyorsa systemd servisi veya udev kuralı kullanılabilir. Kalıcılık için programı /sys/fs/bpf/ dizinine pinlemek gerekir. Ayrıca her netdev'e yalnızca bir XDP programı bağlanabilir; ikinci bir program yüklenince birincisi sessizce değiştirilir. Birden fazla alt program gerekiyorsa bpf_tail_call ile dağıtım yapılır.

Güvenlik tarafı güçlü. eBPF doğrulayıcısı çekirdeğin kararlılığını tehlikeye atmadan kullanıcı tanımlı kod çalıştırmayı garanti eder. Sınırsız döngü, kontrolsüz bellek erişimi veya geçersiz talimat yüklenmeyi reddeder. Bu mekanizma sayesinde çekirdek modülü yazmadan doğrudan NIC sürücüsüne programlanabilir kanca eklemek mümkün.

ctCertWatch

SSL sertifika yayınlarını gerçek zamanlı takip eden bir izleme servisi. Regex filtreleme, DNS çözümleme ve webhook uyarıları ile phishing domainlerini, marka taklidini ve yetkisiz sertifikaları anında…

Rust

ipReconary

IP aralıkları, alt ağlar ve ASN bilgilerine dayalı olarak host, domain ve servis keşfi yapan bir ağ keşif (recon) aracı. Güvenlik uzmanları ve OSINT araştırmacıları için ağ altyapısını hızlı ve güveni…

Rust

Wireguard-Server-Panel

Web arayüzüne sahip, kendi sunucunuzda barındırılan bir WireGuard VPN servisi. İstemci yönetimi, mobil bağlantı için QR kod desteği, gerçek zamanlı trafik istatistikleri ve bağlantı kayıtları sunar. T…

LoadAlertTracker

Sistem yükünü neredeyse hiç kaynak tüketmeden izleyen, hafif bir servis. Belirlenen eşikler aşıldığında Telegram, Discord ve Mattermost gibi platformlara gerçek zamanlı uyarı gönderir.

Rust

Trustsslroot

Tek komutla eksiksiz bir özel PKI yapısı (Kök CA → Ara CA → sunucu ve istemci sertifikaları) oluşturan araç. Farklı formatlarda (p12/bks/jks) paketler üretir ve kullanıma hazır çıktı klasörleri sunar.

Go

DDNS-FW

Değişken IP adresini DDNS üzerinden gerçek zamanlı takip eden, hafif ve güvenilir bir araç. İzin verilen IP listelerini otomatik güncelleyerek kesintisiz erişim ve güvenlik sağlar. Tek dosyadan çalışı…

Rust

Cloudfiltred

Sunucu üzerinde 80/443 portlarına erişimi yalnızca Cloudflare IP aralıklarıyla sınırlandıran, tek dosyadan çalışan bir Linux servisi. Kendini kurar, sistem servisi olarak çalışır ve IP listelerini düz…

Rust

node_exporter

Linux için geliştirilmiş, hafif ve tek dosyadan çalışan, güvenli erişim kontrollü bir sistem metrikleri servisi.

Rust