ebpf实现防火墙代码示例
时间: 2024-05-06 14:19:58 浏览: 135
下面是一个简单的ebpf程序,用于防止从指定IP地址和端口发送的流量:
```
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
struct bpf_map_def SEC("maps") whitelist = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct in_addr),
.value_size = sizeof(short),
.max_entries = 1024,
};
SEC("filter") int firewall(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
struct iphdr *ip = data + sizeof(struct ethhdr);
struct in_addr src_ip = { .s_addr = ip->saddr };
struct in_addr dst_ip = { .s_addr = ip->daddr };
short *ports;
if (ip->protocol != IPPROTO_TCP)
return XDP_PASS;
if (bpf_map_lookup_elem(&whitelist, &src_ip, &ports) == 0) {
if (*ports == ntohs(((struct tcphdr *)(ip + 1))->dest))
return XDP_PASS;
}
if (bpf_map_lookup_elem(&whitelist, &dst_ip, &ports) == 0) {
if (*ports == ntohs(((struct tcphdr *)(ip + 1))->source))
return XDP_PASS;
}
return XDP_DROP;
}
char _license[] SEC("license") = "GPL";
```
该程序使用了一个hash map来存储允许通过的IP地址和端口。在防火墙函数中,我们首先检查数据包是否是TCP协议,如果不是,则直接通过。然后我们检查源IP地址和目标IP地址是否在白名单中,如果是,则进一步检查端口号是否匹配。如果匹配,则通过数据包,否则丢弃它。
要使用该程序,我们需要先创建一个hash map,并将允许通过的IP地址和端口添加到map中:
```
ip_address=$(ip addr show eth0 | awk '$1 == "inet" { sub("/.*", "", $2); print $2 }')
bpftool map create /sys/fs/bpf/firewall/whitelist type hash key sizeof(struct in_addr) value sizeof(short) max_entries 1024
bpftool map update pinned /sys/fs/bpf/firewall/whitelist key hex $ip_address value hex 80e1
```
这将创建一个名为“whitelist”的hash map,并将IP地址为“$ip_address”的端口“80e1”添加到map中。现在我们可以将ebpf程序加载到内核中:
```
bpftool prog load firewall.o /sys/fs/bpf/firewall
bpftool prog attach xdp pinned /sys/fs/bpf/firewall
```
这将把程序加载到内核中,并将它附加到xdp程序中。现在我们的防火墙就可以工作了,它将阻止从指定IP地址和端口发送的流量。
阅读全文