Linux 内核 Netfilter 模块

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

# 注册

#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

# 接受数据

#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

# 注销

#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

未完待续....

Last Updated: 6/2/2023, 7:17:11 AM