eBPF/XDP实现Conntrack功能

3 篇文章 1 订阅

项目背景

连接跟踪(conntrack)是网络应用非常非常的基础,比如有状态防火墙 (firewall),网络地址转换(nat),负载均衡(lb)。Linux conntrack 是 基于 netfilter 实现的,如图所示,分别在 PREROUTING, POSTROUTING 位置前 和后对网络报文进行跟踪;
在这里插入图片描述
但是 XDP 位置在进入网络栈之前,无法利用到内核栈的 conntrack 能力, Cilium 应该遇到同样的问题, 所以 Cilium 基于 eBPF 实现了 conntrack;如 图所示,
在这里插入图片描述

换句话说,只要具备 Hook 能力,能拦截进出主机的每个报文,完全可以实 现一套连接跟踪功能, 这个该项目的核心思路。结果如图:

{
    "code":200,
    "traceId":"0ed9b475-eb36-454d-91eb-e3c283ed3df9",
    "Conn":[
        "icmp est period=0 src=172.20.56.105 dst=172.30.56.105 sport=0 dport=23362 rxbytes=4508 rxpkts=46 rxrelbytes=0 rxrelpkts=0 est period=0 src=172.30.56.105 dst=172.20.56.105 sport=23362 dport=0 txbytes=4508 txpkts=46 txrelbytes=0 txrelpkts=0"
    ]
}

项目设计

从网络数据路径上分析, Linux XDP HOOK 只能处理入向报文,无法处理 主机主动出向报文,所以该项目只能做网络数据转发。网络报文是双向的, 为 了区分出入向流量,需要两张网络设备,如图所示:

在这里插入图片描述

要实现连接跟踪,首先要解析网络报文,提取 Flow 项(五元组),然后建 立连接信息数据库(conntrack table),最后拦截网络报文信息,不断更新数 据库。如图所示
在这里插入图片描述

将 eBPF 程序挂载到网络设备上,Parse-Match Action-Deparse 每一个网 络报文,遇到处理不了的可以送到内核栈处理,可以成为网络栈的一种延伸。

Conntrack Tableebpf map
Parer/Deparserbpf_tail_call

BPF Map 定义

  • meta : 存储元数据,每个序号都要含义,比如 Index:0 表示系统启动时 间 ktime
  • jt : Jump Table, 用于 bpf_tail_call 程序跳转
  • ctt : Conntrack Table 存储 flow
struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, __u32);
	__type(value,__u64);
	__uint(max_entries, 4);
} meta SEC(".maps"); //meta table
struct {
	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
	__type(key, 0x04);
	__type(value, 0x04);
	__uint(max_entries, 30);
} jt SEC(".maps"); //jump table
struct {
	__uint(type, BPF_MAP_TYPE_LRU_HASH);
	__type(key, struct ipv4_ct_tuple);
	__type(value, struct ipv4_ct_entry);
	__uint(max_entries, 1024);
} ctt SEC(".maps"); //conntrack table

BPF Prog 定义

PROG(ingress)(struct xdp_md *ctx) {
// 处理入向报文
}
PROG(egress)(struct xdp_md *ctx) {
// 处理出向报文
}
PROG(prs_eth)(struct xdp_md *ctx) {
// 解析以太网协议
}
PROG(prs_ipv4)(struct xdp_md *ctx) {
// 解析IPv4协议
}
PROG(prs_icmp)(struct xdp_md *ctx) {
// 解析ICMP协议
}
PROG(prs_tcp)(struct xdp_md *ctx) {
// 解析TCP协议
}
PROG(prs_udp) (struct xdp_md *ctx) {
// 解析UDP协议
}
PROG(ct)(struct xdp_md *ctx) {
// 处理CT
}
PROG(prs_end)(struct xdp_md *ctx) {
// Deparser
}

Parser 逐层解析报文,例如,解析以太网、解析 IPv4、解析 ICMP/TCP/UDP 报文。每个 Prog eBPF 程序入参是 struct xdp_md *ctx,是如何在 PROG(prs_ipv4) 中避免重复解析 eth。 基于 bpf_xdp_adjust_meta 函 数在报文前扩展内置协议。此项目,扩展内置协议是 struct flow 存储 Flow 需要 的参数。

在这里插入图片描述

struct xdp_buff {
	void *data;
	void *data_end;
	void *data_meta;
	void *data_hard_start;
	struct xdp_rxq_info *rxq;
};
struct flow {
	__be32 sip;
	__be32 dip;
	__be32 sport:16,
	dport:16;
	__u32 proto:8,
	delta:8,
	bytes:16;
	__u32 urg:1,
	ack:1,
	psh:1,
	rst:1,
	syn:1,
	fin:1,
	rel:1,
	dir:1,
	reserved:24;
} __attribute__((packed));

CT 状态转换

CT 状态转换跟踪 flow 信息,像 UDP,ICMP 等无状态相对 TCP 更简单,TCP 本身面向连接且有状态转换相对复杂。UDP 报文需要注意related 报文。每个conntrack状态需要设置过期时间。TCP 的连接跟踪状态转换图如下:
在这里插入图片描述

实验环境

系统版本

ubuntu 21.10

Namespace 网络环境

#创建 namespace
ip netns del ns1
ip netns del ns2
ip netns add ns1
ip netns add ns2
8
#创建veth 虚拟网络设备
ip link add ns1-wan type veth peer name ns1-lan
ip link add ns2-wan type veth peer name ns2-lan
ip link set ns1-lan up
ip link set ns1-wan up
ip link set ns2-lan up
ip link set ns2-wan up
ip link set ns1-wan netns ns1
ip link set ns2-wan netns ns2
ip netns exec ns1 ip link set dev ns1-wan up
ip netns exec ns2 ip link set dev ns2-wan up
ip addr add 172.20.56.1/24 brd 172.20.56.255 dev ns1-lan
ip addr add 172.30.56.1/24 brd 172.30.56.255 dev ns2-lan
sysctl -w net.ipv4.conf.all.forwarding=1
sysctl -w net.ipv6.conf.all.forwarding=1
ip netns exec ns1 ip addr add 172.20.56.105/24 brd 172.20.56.255 dev ns1-wan
ip netns exec ns1 ip route add default via 172.20.56.1 dev ns1-wan
ip netns exec ns2 ip addr add 172.30.56.105/24 brd 172.30.56.255 dev ns2-wan
ip netns exec ns2 ip route add default via 172.30.56.1 dev ns2-wan

安装CT程序

dpkg -i ct-0.0.1-0-x86_64.deb
systemctl start ct

挂载 eBPF 程序

ip link set dev ns1-lan xdp pinned /sys/fs/bpf/prog/xdp_0
ip link set dev ns2-lan xdp pinned /sys/fs/bpf/prog/xdp_1

后记

购买文档 免费送源代码
购买文档 免费送源代码
购买文档 免费送源代码

加vx, 免费一次答疑

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cugriver

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值