77 lines
1.8 KiB
C
77 lines
1.8 KiB
C
#include "common.h"
|
|
|
|
enum filter_ret_code {
|
|
// 不处理当前连接
|
|
PASS = 0,
|
|
// 处理当前连接
|
|
STORE = 1,
|
|
};
|
|
|
|
|
|
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
|
|
|
static inline
|
|
void store_sock_ops(struct bpf_sock_ops *skops)
|
|
{
|
|
struct sock_key key = {
|
|
.dip = skops->remote_ip4,
|
|
.sip = skops->local_ip4,
|
|
.sport = bpf_htonl(skops->local_port), /* convert to network byte order */
|
|
.dport = skops->remote_port,
|
|
.family = skops->family,
|
|
};
|
|
|
|
int ret = bpf_sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST);
|
|
if (ret != 0) {
|
|
bpf_printk("sock_hash_update() failed, ret: %d\n", ret);
|
|
}
|
|
|
|
}
|
|
|
|
// 判断传入连接是否需要处理
|
|
static inline
|
|
__u8 sock_filter(struct bpf_sock_ops *skops)
|
|
{
|
|
if (skops->family != 2){ // AF_INET
|
|
return PASS;
|
|
}
|
|
/*
|
|
local traffic only, so check both local and remote IPs
|
|
*/
|
|
__u32 remote_ip = skops->remote_ip4;
|
|
__u32 local_ip = skops->local_ip4;
|
|
|
|
// 检查 remote_ip 是否在目标 map 中
|
|
if (!bpf_map_lookup_elem(&target_ip_map, &remote_ip)) {
|
|
return PASS;
|
|
}
|
|
|
|
// 如果是本地流量,大概率remote ip 和 local ip 是相同的,此时可以省去一次 map 查询
|
|
if (remote_ip == local_ip) {
|
|
return STORE;
|
|
}
|
|
|
|
// 检查 local_ip 是否在目标 map 中
|
|
if (!bpf_map_lookup_elem(&target_ip_map, &local_ip)) {
|
|
return PASS;
|
|
}
|
|
|
|
return STORE;
|
|
}
|
|
|
|
SEC("sockops")
|
|
int bpf_sockops_handler(struct bpf_sock_ops *skops)
|
|
{
|
|
// only interested in established events
|
|
if (skops->op != BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB &&
|
|
skops->op != BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {
|
|
return BPF_OK;
|
|
}
|
|
if (sock_filter(skops)){ // AF_INET
|
|
store_sock_ops(skops); // 将 socket 信息记录到到 sockmap
|
|
}
|
|
|
|
return BPF_OK;
|
|
}
|
|
|