使用bcc SKB丢弃TCP数据包



意图:使用bcc工具丢弃tcp/端口数据包

我偶然发现了这个代码

int drop(struct __sk_buff *skb) {
const int l3_off = ETH_HLEN;                       // IP header offset
const int l4_off = l3_off + sizeof(struct iphdr);  // TCP header offset
const int l7_off = l4_off + sizeof(struct tcphdr); // L7 (e.g. HTTP) header offset
void *data = (void*)(long)skb->data;
void *data_end = (void*)(long)skb->data_end;
if (data_end < data + l7_off)
return TC_ACT_OK; // Not our packet, handover to kernel
struct ethhdr *eth = data;
if (eth->h_proto != htons(ETH_P_IP))
return TC_ACT_OK; // Not an IPv4 packet, handover to kernel
struct iphdr *ip = (struct iphdr *)(data + l3_off);
if (ip->protocol != IPPROTO_TCP)
return TC_ACT_OK;
struct tcphdr *tcp = (struct tcphdr *)(data + l4_off);
if (ntohs(tcp->dest) != 80)
return TC_ACT_OK;
return TC_ACT_SHOT;
}

我试着在bcc中实现这个,但由于权限被拒绝,它吐出了错误。我可以查看的任何tcp/端口级别阻塞的示例。

这是我的代码:

from __future__ import print_function
import os
import sys
import time
import atexit
import argparse
from bcc import BPF, BPFAttachType, lib

examples = """examples:
./sockmap.py -c /root/cgroup # attach to /root/cgroup
"""
parser = argparse.ArgumentParser(
description="pipe data across multiple sockets",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
parser.add_argument("-c", "--cgroup", required=True,
help="Specify the cgroup address. Note. must be cgroup2")
bpf_text = '''
#include <net/sock.h>
#include <linux/bpf.h>
#include <linux/pkt_cls.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#define MAX_SOCK_OPS_MAP_ENTRIES 65535
struct sock_key {
u32 remote_ip4;
u32 local_ip4;
u32 remote_port;
u32 local_port;
u32 family;
};
BPF_SOCKHASH(sock_hash, struct sock_key, MAX_SOCK_OPS_MAP_ENTRIES);
.
.
.
int drop(struct __sk_buff *skb) {
const int l3_off = ETH_HLEN;                       // IP header offset
const int l4_off = l3_off + sizeof(struct iphdr);  // TCP header offset
const int l7_off = l4_off + sizeof(struct tcphdr); // L7 (e.g. HTTP) header offset
void *data = (void*)(long)skb->data;
void *data_end = (void*)(long)skb->data_end;
if (data_end < data + l7_off)
return TC_ACT_OK; // Not our packet, handover to kernel
struct ethhdr *eth = data;
if (eth->h_proto != htons(ETH_P_IP))
return TC_ACT_OK; // Not an IPv4 packet, handover to kernel
struct iphdr *ip = (struct iphdr *)(data + l3_off);
if (ip->protocol != IPPROTO_TCP)
return TC_ACT_OK;
struct tcphdr *tcp = (struct tcphdr *)(data + l4_off);
if (ntohs(tcp->dest) != 80)
return TC_ACT_OK;
return TC_ACT_SHOT;
}
'''
args = parser.parse_args()
bpf = BPF(text=bpf_text)
func_sock_ops = bpf.load_func("drop", bpf.SOCK_OPS)
func_sock_redir = bpf.load_func("bpf_redir", bpf.SK_MSG)
# raise if error
fd = os.open(args.cgroup, os.O_RDONLY)
map_fd = lib.bpf_table_fd(bpf.module, b"sock_hash")
bpf.attach_func(func_sock_ops, fd, BPFAttachType.CGROUP_SOCK_OPS)
bpf.attach_func(func_sock_redir, map_fd, BPFAttachType.SK_MSG_VERDICT)
def detach_all():
bpf.detach_func(func_sock_ops, fd, BPFAttachType.CGROUP_SOCK_OPS)
bpf.detach_func(func_sock_redir, map_fd, BPFAttachType.SK_MSG_VERDICT)
print("Detaching...")
atexit.register(detach_all)
while True:
try:
bpf.trace_print()
sleep(1)
except KeyboardInterrupt:
sys.exit(0)

跳过额外的代码,代码模板来自bcc/examples/networking/sockmap.py

您要使用的程序是TC eBPF程序,但您正试图将其附加到cGroup。我建议以tcpperf_event.py为基础,并通过用块程序替换eBPF程序来修改它。(并删除示例中的perf部分(。

最新更新