Linux 内核 Netfilter 模块
Alex 6/18/2022 Linux 内核
# 参数配置
#include <linux/netfilter.h>
#include <linux/skbuff.h>
static struct nf_hook_ops hook_ops[] __read_mostly = {
{
.hook = hook,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
.pf = NFPROTO_INET,
#else
.pf = PF_INET,
.owner = THIS_MODULE,
#endif
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 注册
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
nf_register_net_hooks(&init_net, hook_ops, ARRAY_SIZE(hook_ops));
#else
nf_register_hooks(hook_ops, ARRAY_SIZE(hook_ops));
#endif
1
2
3
4
5
2
3
4
5
# 接受数据
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
static u_int32_t hook(void *priv, struct sk_buff *sock_buff, const struct nf_hook_state *state) {
#else
unsigned int hook(const struct nf_hook_ops * hook, struct sk_buff * sock_buff, const struct net_device * in, const struct net_device * out, const struct nf_hook_state * state){
#endif
int source_port;
int dest_port;
char source[32];
char dest[32];
unsigned char *data;
int len;
if (sock_buff == NULL) {
return NF_ACCEPT;
}
ip_header = ip_hdr(sock_buff);
if (!ip_header) {
return NF_ACCEPT;
}
// 解析三层协议
sprintf(source, "%pI4", &ip_header->saddr);
sprintf(dest, "%pI4", &ip_header->daddr);
// 解析四层协议
switch (ip_header->protocol) {
case IPPROTO_TCP:
tcp_header = (struct tcphdr *) (ip_header + 1);
dest_port = htons(tcp_header->dest);
source_port = htons(tcp_header->source);
data = sock_buff->data + ip_header->ihl * 4 + tcp_header->doff * 4;
len = ntohs(ip_header->tot_len) - ip_header->ihl * 4 - tcp_header->doff * 4;
break;
case IPPROTO_UDP:
udp_header = (struct udphdr *) (ip_header + 1);
dest_port = htons(udp_header->dest);
source_port = htons(udp_header->source);
data = sock_buff->data + ip_header->ihl * 4 + 8;
len = ntohs(ip_header->tot_len) - ip_header->ihl * 4 - 8;
break;
default:
reutrn NF_ACCEPT;
}
printk("%s:%d -> %s:%d", source, source_port, dest, dest_port);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, data, len, true);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 注销
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
nf_unregister_net_hooks(&init_net, hook_ops, ARRAY_SIZE(hook_ops));
#else
nf_unregister_hooks(hook_ops, ARRAY_SIZE(hook_ops));
#endif
1
2
3
4
5
2
3
4
5
未完待续....