Skip to content

Commit 1e93c81

Browse files
wynyibohelight
andauthored
net_watcher:添加端口过滤功能、测试 (#962)
* change structure * add port filter * add port filter * update * add test * update * update * update --------- Co-authored-by: helight <helight@helight.info>
1 parent 2a4c6e5 commit 1e93c81

File tree

9 files changed

+640
-410
lines changed

9 files changed

+640
-410
lines changed

MagicEyes/src/backend/net/net_watcher/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ foreach(app ${apps})
3434
add_dependencies(${app_stem}_skel libbpf-build bpftool-build)
3535
endforeach()
3636

37-
add_executable(${TOOL_NAME} src/${TOOL_NAME}.c)
37+
# add_executable(${TOOL_NAME} src/${TOOL_NAME}.c)
38+
add_executable(${TOOL_NAME}
39+
src/${TOOL_NAME}.c
40+
src/net_watcher_hepler.c
41+
)
3842
foreach (app ${apps})
3943
get_filename_component(app_stem ${app} NAME_WE)
4044
target_link_libraries(${TOOL_NAME} ${app_stem}_skel)

MagicEyes/src/backend/net/net_watcher/bpf/net_watcher.bpf.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ SEC("kprobe/tcp_enter_loss")
227227
int BPF_KPROBE(tcp_enter_loss, struct sock *sk) { return __tcp_enter_loss(sk); }
228228

229229
/* udp */
230+
//收包 udp_rcv-->__udp_enqueue_schedule_skb(数据包排队)
230231
SEC("kprobe/udp_rcv")
231232
int BPF_KPROBE(udp_rcv, struct sk_buff *skb) {
232233
if (udp_info)
@@ -242,7 +243,7 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk,
242243
struct sk_buff *skb) {
243244
return udp_enqueue_schedule_skb(sk, skb);
244245
}
245-
246+
//发包 udp_send_skb-->ip_send_skb(skb 交给 IP 协议层)
246247
SEC("kprobe/udp_send_skb")
247248
int BPF_KPROBE(udp_send_skb, struct sk_buff *skb) {
248249
if (udp_info)

MagicEyes/src/backend/net/net_watcher/bpf/udp.bpf.h

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
// author: blown.away@qq.com
1616

1717
#include "common.bpf.h"
18-
19-
static __always_inline int __udp_rcv(struct sk_buff *skb) {
18+
// receive
19+
static __always_inline int __udp_rcv(struct sk_buff *skb)
20+
{
2021
if (!udp_info || skb == NULL)
2122
return 0;
2223
struct iphdr *ip = skb_to_iphdr(skb);
@@ -27,14 +28,16 @@ static __always_inline int __udp_rcv(struct sk_buff *skb) {
2728
struct ktime_info *tinfo, zero = {0};
2829
tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init(&timestamps,
2930
&pkt_tuple, &zero);
30-
if (tinfo == NULL) {
31+
if (tinfo == NULL)
32+
{
3133
return 0;
3234
}
3335
tinfo->tran_time = bpf_ktime_get_ns() / 1000;
3436
return 0;
3537
}
3638
static __always_inline int udp_enqueue_schedule_skb(struct sock *sk,
37-
struct sk_buff *skb) {
39+
struct sk_buff *skb)
40+
{
3841
if (!udp_info || skb == NULL)
3942
return 0;
4043
struct iphdr *ip = skb_to_iphdr(skb);
@@ -44,14 +47,16 @@ static __always_inline int udp_enqueue_schedule_skb(struct sock *sk,
4447
FILTER
4548
struct ktime_info *tinfo, zero = {0};
4649
tinfo = bpf_map_lookup_elem(&timestamps, &pkt_tuple);
47-
if (tinfo == NULL) {
50+
if (tinfo == NULL)
51+
{
4852
return 0;
4953
}
5054
struct udp_message *message;
5155
struct udp_message *udp_message =
5256
bpf_map_lookup_elem(&timestamps, &pkt_tuple);
5357
message = bpf_ringbuf_reserve(&udp_rb, sizeof(*message), 0);
54-
if (!message) {
58+
if (!message)
59+
{
5560
return 0;
5661
}
5762
message->saddr = pkt_tuple.saddr;
@@ -60,25 +65,27 @@ static __always_inline int udp_enqueue_schedule_skb(struct sock *sk,
6065
message->sport = pkt_tuple.sport;
6166
message->tran_time = bpf_ktime_get_ns() / 1000 - tinfo->tran_time;
6267
message->rx = 1; // 收包
63-
message->len = __bpf_ntohs(BPF_CORE_READ(udp, len));
68+
message->len = __bpf_ntohs(BPF_CORE_READ(udp, len)) - UDP_HEAD;
6469
bpf_ringbuf_submit(message, 0);
6570
return 0;
6671
}
67-
68-
static __always_inline int __udp_send_skb(struct sk_buff *skb) {
72+
// send
73+
static __always_inline int __udp_send_skb(struct sk_buff *skb)
74+
{
6975
if (!udp_info || skb == NULL)
7076
return 0;
7177
struct packet_tuple pkt_tuple = {0};
7278
struct sock *sk = BPF_CORE_READ(skb, sk);
7379
u16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
7480
u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num);
75-
pkt_tuple.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); // 源ip
76-
pkt_tuple.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); // 目的ip
77-
pkt_tuple.sport = sport; // 源端口
78-
pkt_tuple.dport = __bpf_ntohs(dport); // 目的端口并进行字节序转换
81+
pkt_tuple.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
82+
pkt_tuple.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr);
83+
pkt_tuple.sport = sport;
84+
pkt_tuple.dport = __bpf_ntohs(dport);
7985
pkt_tuple.tran_flag = UDP;
8086
FILTER
8187
struct ktime_info *tinfo, zero = {0};
88+
8289
/** 注意:
8390
* bpf_printk在老的Linux内核(在kernel 5.15测试)上,只支持三个以内的参数
8491
* 可查看: https://github.com/libbpf/libbpf-bootstrap/issues/206
@@ -87,15 +94,18 @@ static __always_inline int __udp_send_skb(struct sk_buff *skb) {
8794
// pkt_tuple.sport, pkt_tuple.dport);
8895
bpf_printk("udp_send_skb s&d addr: %d %d", pkt_tuple.saddr, pkt_tuple.daddr);
8996
bpf_printk("udp_send_skb s&d port: %d %d", pkt_tuple.sport, pkt_tuple.dport);
97+
9098
tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init(&timestamps,
9199
&pkt_tuple, &zero);
92-
if (tinfo == NULL) {
100+
if (tinfo == NULL)
101+
{
93102
return 0;
94103
}
95104
tinfo->tran_time = bpf_ktime_get_ns() / 1000;
96105
return 0;
97106
}
98-
static __always_inline int __ip_send_skb(struct sk_buff *skb) {
107+
static __always_inline int __ip_send_skb(struct sk_buff *skb)
108+
{
99109
if (!udp_info || skb == NULL)
100110
return 0;
101111
struct iphdr *ip = skb_to_iphdr(skb);
@@ -105,28 +115,31 @@ static __always_inline int __ip_send_skb(struct sk_buff *skb) {
105115
FILTER
106116
struct ktime_info *tinfo, zero = {0};
107117
tinfo = bpf_map_lookup_elem(&timestamps, &pkt_tuple);
108-
if (tinfo == NULL) {
118+
if (tinfo == NULL)
119+
{
109120
return 0;
110121
}
111122
struct udp_message *message;
112123
struct udp_message *udp_message =
113124
bpf_map_lookup_elem(&timestamps, &pkt_tuple);
114125
message = bpf_ringbuf_reserve(&udp_rb, sizeof(*message), 0);
115-
if (!message) {
126+
if (!message)
127+
{
116128
return 0;
117129
}
118-
udp = skb_to_udphdr(skb);
130+
119131
message->tran_time = bpf_ktime_get_ns() / 1000 - tinfo->tran_time;
120132
message->saddr = pkt_tuple.saddr;
121133
message->daddr = pkt_tuple.daddr;
122134
message->sport = pkt_tuple.sport;
123135
message->dport = pkt_tuple.dport;
124136
message->rx = 0; // 发包
125-
message->len = __bpf_ntohs(BPF_CORE_READ(udp, len));
137+
message->len = __bpf_ntohs(BPF_CORE_READ(udp, len)) - UDP_HEAD;
126138
bpf_ringbuf_submit(message, 0);
127139
return 0;
128140
}
129-
static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
141+
static __always_inline int process_dns_packet(struct sk_buff *skb, int rx)
142+
{
130143
if (skb == NULL)
131144
return 0;
132145
u16 QR_flags;
@@ -160,31 +173,42 @@ static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
160173
1000 0000 0000 0000
161174
&运算提取最高位QR, QR=1 Response QR=0 Request
162175
*/
163-
if (QR_flags & 0x8000) { // 响应
176+
if (QR_flags & 0x8000)
177+
{ // 响应
164178
count_ptr = bpf_map_lookup_elem(&dns_response_count, &key);
165-
if (count_ptr) {
179+
if (count_ptr)
180+
{
166181
response_count = *count_ptr + 1;
167-
} else {
182+
}
183+
else
184+
{
168185
response_count = 1;
169186
}
170187
bpf_map_update_elem(&dns_response_count, &key, &response_count,
171188
BPF_ANY);
172189
// 保留映射中的请求计数值
173190
count_ptr = bpf_map_lookup_elem(&dns_request_count, &key);
174-
if (count_ptr) {
191+
if (count_ptr)
192+
{
175193
request_count = *count_ptr;
176194
}
177-
} else { // 请求
195+
}
196+
else
197+
{ // 请求
178198
count_ptr = bpf_map_lookup_elem(&dns_request_count, &key);
179-
if (count_ptr) {
199+
if (count_ptr)
200+
{
180201
request_count = *count_ptr + 1;
181-
} else {
202+
}
203+
else
204+
{
182205
request_count = 1;
183206
}
184207
bpf_map_update_elem(&dns_request_count, &key, &request_count, BPF_ANY);
185208
// 保留映射中的响应计数值
186209
count_ptr = bpf_map_lookup_elem(&dns_response_count, &key);
187-
if (count_ptr) {
210+
if (count_ptr)
211+
{
188212
response_count = *count_ptr;
189213
}
190214
}
@@ -203,10 +227,12 @@ static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
203227
bpf_ringbuf_submit(message, 0);
204228
return 0;
205229
}
206-
static __always_inline int __dns_rcv(struct sk_buff *skb) {
230+
static __always_inline int __dns_rcv(struct sk_buff *skb)
231+
{
207232
return process_dns_packet(skb, 0); // 0 收
208233
}
209234

210-
static __always_inline int __dns_send(struct sk_buff *skb) {
235+
static __always_inline int __dns_send(struct sk_buff *skb)
236+
{
211237
return process_dns_packet(skb, 1); // 1 发
212238
}

MagicEyes/src/backend/net/net_watcher/include/net_watcher.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,18 @@ typedef unsigned long long u64;
5656
#define MAX_EVENTS 1024
5757
#define CACHEMAXSIZE 5
5858
#define PID 32
59-
#define NS(x) ((x) * 1000000000) // 1 秒等于 10^9 纳秒
59+
#define NS(x) ((x) * 1000000000LL) // 1 秒等于 10^9 纳秒
6060
#define TIME_THRESHOLD_NS NS(10)
61+
#define UDP_HEAD 8
6162

6263
typedef u64 stack_trace_t[MAX_STACK_DEPTH];
6364

65+
typedef struct
66+
{
67+
char key[256];
68+
u32 value;
69+
} kv_pair;
70+
6471
struct conn_t
6572
{
6673
void *sock; // 此tcp连接的 socket 地址
@@ -317,5 +324,4 @@ struct tcp_args_s {
317324
u64 sample_period;
318325
};
319326

320-
321327
#endif /* __NET_WATCHER_H */
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2023 The LMP Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// author: blown.away@qq.com
16+
17+
#ifndef NET_WATCHER_HELPER_H
18+
#define NET_WATCHER_HELPER_H
19+
#include "net_watcher/include/net_watcher.h"
20+
#include <arpa/inet.h>
21+
#include <bpf/bpf.h>
22+
#include <bpf/libbpf.h>
23+
#include <string.h>
24+
25+
// logo
26+
#define LOGO_STRING \
27+
" " \
28+
" __ __ __ " \
29+
" \n" \
30+
" /\\ \\__ /\\ \\__ /\\ \\ " \
31+
" \n" \
32+
" ___ __\\ \\ _\\ __ __ __ __ \\ \\ _\\ ___\\ \\ \\___ " \
33+
" __ _ __ \n" \
34+
"/ _ \\ / __ \\ \\ \\/ /\\ \\/\\ \\/\\ \\ / __ \\ \\ \\ \\/ / ___\\ " \
35+
"\\ _ \\ / __ \\/\\ __\\ \n" \
36+
"/\\ \\/\\ \\/\\ __/\\ \\ \\_\\ \\ \\_/ \\_/ \\/\\ \\_\\ \\_\\ \\ " \
37+
"\\_/\\ \\__/\\ \\ \\ \\ \\/\\ __/\\ \\ \\/ \n" \
38+
"\\ \\_\\ \\_\\ \\____\\ \\__\\ \\_______ / /\\ \\__/\\ \\_\\ \\__\\ " \
39+
"\\____/\\ \\_\\ \\_\\ \\____ \\ \\_\\ \n" \
40+
" \\/_/\\/_/\\/____/ \\/__/ \\/__//__ / \\/_/ \\/_/\\/__/\\/____/ " \
41+
"\\/_/\\/_/\\/____/ \\/_/ \n\n"
42+
//
43+
#define __ATTACH_UPROBE_GENERIC(skel, sym_name, prog_name, is_retprobe) \
44+
do \
45+
{ \
46+
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \
47+
.retprobe = is_retprobe); \
48+
skel->links.prog_name = bpf_program__attach_uprobe_opts( \
49+
skel->progs.prog_name, -1, binary_path, 0, &uprobe_opts); \
50+
if (!skel->links.prog_name) \
51+
{ \
52+
perror("no program attached for " #prog_name); \
53+
return -errno; \
54+
} \
55+
} while (false)
56+
57+
// 入口探针
58+
#define ATTACH_UPROBE(skel, sym_name, prog_name) \
59+
__ATTACH_UPROBE_GENERIC(skel, sym_name, prog_name, false)
60+
61+
// 返回探针
62+
#define ATTACH_URETPROBE(skel, sym_name, prog_name) \
63+
__ATTACH_UPROBE_GENERIC(skel, sym_name, prog_name, true)
64+
65+
// 入口探针,检查是否成功附加
66+
#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) \
67+
__ATTACH_UPROBE_GENERIC(skel, sym_name, prog_name, false)
68+
69+
// 返回探针,检查是否成功附加
70+
#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) \
71+
__ATTACH_UPROBE_GENERIC(skel, sym_name, prog_name, true)
72+
73+
extern struct SymbolEntry symbols[300000];
74+
extern struct SymbolEntry cache[CACHEMAXSIZE];
75+
extern int event_count, num_symbols, cache_size;
76+
extern float ewma_values[NUM_LAYERS];
77+
extern int count[NUM_LAYERS];
78+
79+
int should_filter(const char *src, const char *dst, const char *filter_src_ip, const char *filter_dst_ip);
80+
int process_delay(float layer_delay, int layer_index);
81+
void print_logo();
82+
void bytes_to_str(char *str, unsigned long long num);
83+
void readallsym();
84+
struct SymbolEntry findfunc(unsigned long int addr);
85+
void add_to_cache(struct SymbolEntry entry);
86+
struct SymbolEntry find_in_cache(unsigned long int addr);
87+
int process_delay(float layer_delay, int layer_index);
88+
float calculate_ewma(float new_value, float old_ewma);
89+
int process_redis_first(char flag, char *message);
90+
int create_ring_buffer(struct ring_buffer **rb, int map_fd, void *print_fn, const char *name);
91+
int poll_ring_buffers(struct ring_buffer *buffers[], int num_buffers, int timeout_ms);
92+
void print_domain_name(const unsigned char *data, char *output);
93+
int should_filter_t(const char *src, const char *dst, unsigned short sport, unsigned short dport,const char *filter_src_ip, const char *filter_dst_ip, unsigned short filter_sport, unsigned short filter_dport);
94+
95+
#endif

0 commit comments

Comments
 (0)