Files
bpf-developer-tutorial/12-bindsnoop/bindsnoop.md
2022-12-02 19:18:03 +08:00

95 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## eBPF 入门实践教程:编写 eBPF 程序 Bindsnoopn 监控 socket 端口绑定事件
### 背景
Bindsnoop 会跟踪操作 socket 端口绑定的内核函数,并且在可能会影响端口绑定的系统调用发生之前,打印
现有的 socket 选项。
### 实现原理
Bindsnoop 通过kprobe实现。其主要挂载点为 inet_bind 和 inet6_bind。inet_bind 为处理 IPV4 类型
socket 端口绑定系统调用的接口inet6_bind 为处理IPV6类型 socket 端口绑定系统调用的接口。
```c
SEC("kprobe/inet_bind")
int BPF_KPROBE(ipv4_bind_entry, struct socket *socket)
{
if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;
return probe_entry(ctx, socket);
}
SEC("kretprobe/inet_bind")
int BPF_KRETPROBE(ipv4_bind_exit)
{
if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;
return probe_exit(ctx, 4);
}
SEC("kprobe/inet6_bind")
int BPF_KPROBE(ipv6_bind_entry, struct socket *socket)
{
if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;
return probe_entry(ctx, socket);
}
SEC("kretprobe/inet6_bind")
int BPF_KRETPROBE(ipv6_bind_exit)
{
if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;
return probe_exit(ctx, 6);
}
```
当系统试图进行socket端口绑定操作时, kprobe挂载的处理函数会被触发。在进入绑定函数时`probe_entry`会先被
调用,它会以 tid 为主键将 socket 信息存入 map 中。
```c
static int probe_entry(struct pt_regs *ctx, struct socket *socket)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32)pid_tgid;
if (target_pid && target_pid != pid)
return 0;
bpf_map_update_elem(&sockets, &tid, &socket, BPF_ANY);
return 0;
};
```
在执行完绑定函数后,`probe_exit`函数会被调用。该函数会读取tid对应的socket信息将其和其他信息一起
写入 event 结构体并输出到用户态。
```c
struct bind_event {
unsigned __int128 addr;
__u64 ts_us;
__u32 pid;
__u32 bound_dev_if;
int ret;
__u16 port;
__u16 proto;
__u8 opts;
__u8 ver;
char task[TASK_COMM_LEN];
};
```
当用户停止该工具时,其用户态代码会读取存入的数据并按要求打印。
### Eunomia中使用方式
![result](../imgs/mountsnoop.jpg)
![result](../imgs/bindsnoop-prometheus.png)
### 总结
Bindsnoop 通过 kprobe 挂载点,实现了对 socket 端口的监视,增强了 Eunomia 的应用范围。