- Installiere die BCC Tools und die Linux Kernel Header für den
aktuell laufenden Kernel (wenn die Linux Kernel Header nicht
gefunden werden, ist der laufende Kernel nicht mehr aktuell. In
diesem Fall die virtuelle Maschine neu starten/reboot und danach
die Linux Kernel Header installieren)
% apt install bpfcc-introspection bpfcc-tools python3-bpfcc
% apt install linux-headers-$(uname -r)
#define KBUILD_MODNAME "filter"
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/udp.h>
int udpfilter(struct xdp_md *ctx) {
bpf_trace_printk("got a packet\n");
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void*)eth + sizeof(*eth) <= data_end) {
struct iphdr *ip = data + sizeof(*eth);
if ((void*)ip + sizeof(*ip) <= data_end) {
if (ip->protocol == IPPROTO_UDP) {
struct udphdr *udp = (void*)ip + sizeof(*ip);
if ((void*)udp + sizeof(*udp) <= data_end) {
if ((udp->dest != ntohs(53)) && (udp->source != ntohs(53))) {
if (udp->dest != udp->source) {
bpf_trace_printk("drop udp src/dest port %d/%d\n", ntohs(udp->source), ntohs(udp->dest));
return XDP_DROP;
}
}
}
}
}
}
return XDP_PASS;
}
- Speichere das eBPF Ladeprogramm (geschrieben in Python) in die
Datei
drop-non-dns-udp.py
.
- Dieses Ladeprogramm compiliert das obige ePBF Programm, lädt
dieses in den Linux-Kernel und verbindet es mit der Loopback
Netzwerk-Schnittstelle (
lo
)
- Während des Übersetzen des C-Quellcodes in eBPF werden Warnungen
welche wir für dieses Beispiel ignorieren können
- Der
virtio
Netzwerk-Treiber auf den virtuellen Lab-Maschinen
erlaubt keine eBPF Programme auf den Netzwerk-Schnittstellen
eth0
und eth1
, daher testen wir mit der Loopback lo
Schnittstelle
#!/usr/bin/env python3
from bcc import BPF
import time
device = "lo"
b = BPF(src_file="drop-non-dns-udp.c")
fn = b.load_func("udpfilter", BPF.XDP)
b.attach_xdp(device, fn, 0)
try:
b.trace_print()
except KeyboardInterrupt:
pass
b.remove_xdp(device, 0)
- Das Ladeprogramm ausführbar machen
% chmod +x drop-non-dns-udp.py
- Das Python Lade-Programm ausführen (die Warnungen können bei diesem
Beispiel ignoriert werden)
% ./drop-non-dns-udp.py
- Verbinde Dich mit der Lab-Maschine mit einer neuen Sitzung (via
tmux
oder mit einem weiteren Login)
- Starte DNS Anfragen an den BIND 9 DNS Server über die Loopback
Schnittstelle. Diese Anfragen sollten nicht geblockt werden.
% dig @localhost isc.org
- Senden wir UDP Pakete (DNS oder andere Protokolle) an einen Port
ungleich 53 so werden diese Pakete noch vor dem Linux TCP/IP Stack
verworfen
% dig -p 5353 @localhost isc.org