add runtime code
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
#include "sockmap.h"
|
||||
#include "target_ip_map.h"
|
||||
@@ -0,0 +1,76 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "common.h"
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
SEC("sk_msg")
|
||||
int bpf_redir(struct sk_msg_md *msg)
|
||||
{
|
||||
struct sock_key key = {
|
||||
.sip = msg->remote_ip4,
|
||||
.dip = msg->local_ip4,
|
||||
.dport = bpf_htonl(msg->local_port), /* convert to network byte order */
|
||||
.sport = msg->remote_port,
|
||||
.family = msg->family,
|
||||
};
|
||||
|
||||
int ret = bpf_msg_redirect_hash(msg, &sock_ops_map, &key, BPF_F_INGRESS);
|
||||
if (ret == SK_DROP) {
|
||||
bpf_printk("redirect from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d failed\n",
|
||||
key.sip & 0xff, (key.sip >> 8) & 0xff,
|
||||
(key.sip >> 16) & 0xff, (key.sip >> 24) & 0xff,
|
||||
bpf_ntohl(key.sport),
|
||||
key.dip & 0xff, (key.dip >> 8) & 0xff,
|
||||
(key.dip >> 16) & 0xff, (key.dip >> 24) & 0xff,
|
||||
bpf_ntohl(key.dport));
|
||||
}
|
||||
|
||||
// 无论是否重定向成功,都返回 SK_PASS。这样失败的重定向还可以使用其他方法处理
|
||||
return SK_PASS;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
struct sock_key {
|
||||
__u32 sip;
|
||||
__u32 dip;
|
||||
__u32 sport;
|
||||
__u32 dport;
|
||||
__u32 family;
|
||||
};
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKHASH);
|
||||
__uint(max_entries, 65535);
|
||||
__type(key, struct sock_key);
|
||||
__type(value, int);
|
||||
} sock_ops_map SEC(".maps");
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
// 存储需要contrack的IP地址
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u32); // key 类型(目标 IP 地址)
|
||||
__type(value, __u8); // value 类型(标志位,无实际用途,设置为 1 表示存在)
|
||||
__uint(max_entries, 1024); // 最多存储 1024 个目标 IP
|
||||
} target_ip_map SEC(".maps");
|
||||
Reference in New Issue
Block a user