使用netfilter_queue修改数据包以及需要的环境搭建

环境:ubuntu 16.04 64bit LTS 

下面的内容只是一些安装测试的步骤和方法的记录,并没有什么实质性和原理的说明,主要为作者本人记录的远程笔记,如果有幸对您也有帮助,请您顺手顶一下,如果您觉得您是在看不下去,也请不要喷我,毕竟学习不易,小白辛苦的学习还是需要鼓励的,先谢谢您呐!(滑稽狗头.jpg)

在项目中需要使用netfilter_queue修改数据包,然后习惯性的先找了度娘,看到了大神的博文 这是传送门 

但是奈何对这块的知识一点都不知道,环境也没有配置好,只能一点一点摸索,下面就当是自己的步骤做一个简单的记录。

个人习惯:习惯于将手动下载的,手动安装的程序放置在/opt下,所以操作都是在普通用户下使用sudo命令。

libnetfilter_queue主要依赖于libmnllibnfnetlink以及一些其他的工具等,先进行依赖文件的安装。

一、安装libmnl

1 Ubuntu@songshuai:/opt$ sudo git clone git://git.netfilter.org/libmnl // 下载libmnl
2 Ubuntu@songshuai:/opt$ cd libmnl //完成之后进入到目录libmnl
3 Ubuntu@songshuai:/opt/libmnl$ sudo sh autogen.sh

在这个地方可能会出错,如果提示出现下面的错误

1 Ubuntu@songshuai:/opt/libmnl$ sudo sh autogen.sh
2 ./autogen.sh: 3: ./autogen.sh: autoreconf: not found

是因为缺少系统工具autoconf,直接使用apt-get安装即可。

1 Ubuntu@songshuai:/opt/libmnl$ sudo apt-get install autoconf

继续进行,如果提示下面的错误

1 configure.ac:16: error: possibly undefined macro: AC_DISABLE_STATIC
2       If this token and others are legitimate, please use m4_pattern_allow.
3       See the Autoconf documentation.
4 autoreconf: /usr/bin/autoconf failed with exit status: 1

 这是由于系统没有安装 libtool导致的,安装libtool

1 Ubuntu@songshuai:/opt/libmnl$ sudo apt-get install libtool

然后继续安装libmnl的操作

1 Ubuntu@songshuai:/opt/libmnl$ sudo ./autogen.sh
2 Ubuntu@songshuai:/opt/libmnl$ sudo ./configure
3 Ubuntu@songshuai:/opt/libmnl$ sudo make
4 Ubuntu@songshuai:/opt/libmnl$ sudo make install

完成。

二、安装  libnfnetlink

1 Ubuntu@songshuai:/opt$ sudo git clone git://git.netfilter.org/libnfnetlink
2 Ubuntu@songshuai:/opt$ cd libnfnetlink //进入到目录libnfnetlink
3 Ubuntu@songshuai:/opt/libnfnetlink$ sudo sh ./autogen.sh
4 Ubuntu@songshuai:/opt/libnfnetlink$ sudo ./configure
5 Ubuntu@songshuai:/opt/libnfnetlink$ sudo make
6 Ubuntu@songshuai:/opt/libnfnetlink$ sudo make install

顺利完成!

三、安装libnetfilter_queue

1 Ubuntu@songshuai:/opt$ sudo git clone git://git.netfilter.org/libnetfilter_queue
2 Ubuntu@songshuai:/opt$ cd libnetfilter_queue
3 Ubuntu@songshuai:/opt/libnetfilter_queue$ sudo sh autogen.sh
4 Ubuntu@songshuai:/opt/libnetfilter_queue$ sudo ./configure
5 Ubuntu@songshuai:/opt/libnetfilter_queue$ sudo make
6 Ubuntu@songshuai:/opt/libnetfilter_queue$ sudo make install

顺利完成!

四、测试

安装完成之后,进入到example目录,里面包含了一个测试文件,使用gcc编译并执行,因为例子中使用了libmnl的功能,所以编译需要连接libmnl。

1 Ubuntu@songshuai:/opt/libnetfilter_queue/example$ gcc nf-queue.c -o test -lmnl -lnetfilter_queue

在编译的过程可能会出现如下错误:

1 error while loading shared libraries: libnetfilter_queue.so.1: cannot open shared object file: No such file or directory

本人解决办法:

1 sudo ln -s /usr/local/lib/libnfnetlink.so.0 /lib/libnfnetlink.so.0
2 sudo ln -s /usr/local/lib/libnetfilter_queue.so.1 /lib/libnetfilter_queue.so.1

然后执行 test 文件进行测试

在测试之前需要将数据包入到队列中(本人测试中直接将所有的数据都入到队列8008中)

1 sudo iptables -I INPUT -j NFQUEUE --queue-num 8008

然后执行测试程序,起使用方式为./test queue_num

Ubuntu@songshuai:/opt/libnetfilter_queue/example$ sudo ./test 8008

在执行的时候可能或出现如下错误:

1 /usr/lib/x86_64-linux-gnu/libnfnetlink.so.0: no version information available (required by /lib/libnetfilter_queue.so.1)

本人解决办法:

1 export LD_LIBRARY_PATH=/usr/local/lib/
2 sudo ldconfig

执行成功如图所示。

五、自己根据需要编写测试例程

测试例程功能简单说明:客户端和服务端通过socket-tcp进行通讯,客户端只负责发送数据,服务端负责接收数据并显示,服务端通过iptables增加数据抓包并且修改其中的数据。

服务端iptables规则设置:

1、将所有输入的协议为tcp、目标端口为9999的数据入到队列号为80的队列

1 sudo iptables -I INPUT -p tcp --dport 9999 -j NFQUEUE --queue-num 80

可以使用指令查看是否插入成功。如果想要删除规则,则将指令中 -I (insert)换成 -D (delete)即可。

然后运行编译好的程序(代码后附)

1 sudo ./nfqueue 80

2、先运行服务端,然后再运行客户端进行连接并发送测试数据

客户端发送的数据

数据抓取成功并且更改成为其他的数据,然后发送到用户空间。

服务端运行成功并且接收到数据。

下面是nfqueue的主要实现的代码:

 1 static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)
 2 {
 3     u_int32_t id = 0, i = 0;
 4     u_int8_t* payload = NULL;
 5     unsigned char *pdata = NULL;
 6     int pdataLen = 0, length = 0;
 7     struct nfqnl_msg_packet_hw *hwph = NULL;
 8     struct nfqnl_msg_packet_hdr *ph = NULL;
 9     struct tcphdr *tcphdrp = NULL;
10     struct udphdr *udphdrp = NULL;
11     struct iphdr *iphdrp = NULL;
12     uint16_t sport = 0, dport = 0;
13     char src_mac[sizeof("ff:ff:ff:ff:ff:ff\0")];
14     unsigned char tmp[1024] = {0};
15     // 提取数据包头信息,包括id,协议和hook点信息
16     ph = nfq_get_msg_packet_hdr(nfa);
17     if (ph) id = ntohl(ph->packet_id);
18     // 获取数据包载荷,data指针指向载荷,从实际的IP头开始
19     pdataLen = nfq_get_payload(nfa, ((unsigned char**)&pdata));
20     if(pdataLen == -1) pdataLen = 0;
21     iphdrp = (struct iphdr *)pdata;
22     // 获取到终端的大小数据
23     ioctl(STDIN_FILENO, TIOCGWINSZ, &size);
24     // 打印出和终端大小一样的框框
25     for(i = 0; i < size.ws_col; i++) printf("*");
26     printf("packet: %u, protocol = %u\n", id, iphdrp->protocol);
27     
28     if(iphdrp->protocol == IPPROTO_TCP)
29     {
30         tcphdrp = (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
31         length = pdataLen - (iphdrp->ihl<<2) - (tcphdrp->doff<<2);
32         payload = (u_int8_t*)( (u_int8_t*)tcphdrp + (tcphdrp->doff<<2) );
33         sport = tcphdrp->source;
34         dport = tcphdrp->dest;
35         printf("len = %d\n", length);
36         /* 修改數據 */
37         for(i = 0; i < (length > 1024 ? 1024 : length); i++) tmp[i] = payload[length - 1];
38         memcpy(payload, tmp, length > 1024 ? 1024 : length);
39     }
40     else if(iphdrp->protocol == IPPROTO_UDP)
41     {
42         udphdrp = (struct udphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
43         length = pdataLen - (iphdrp->ihl<<2) - 8;
44         payload = (u_int8_t*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2) + 8);
45         sport = udphdrp->source;
46         dport = udphdrp->dest;
47     }
48     printf("line = %d, sport = %d, dport = %d\n", __LINE__, sport, dport);
49     
51     /* 如果對數據報進行了修改,那麼必須進行校驗 */
52     set_ip_checksum(iphdrp);
53     if(iphdrp->protocol == IPPROTO_TCP) set_tcp_checksum1(iphdrp);
54     if(iphdrp->protocol == IPPROTO_UDP) set_udp_checksum1(iphdrp);
55     /* 打印出和终端大小一样的框框 */
56     for(i = 0; i < size.ws_col; i++) printf("*");
57     // 设置裁定
58     return nfq_set_verdict(qh, id, NF_ACCEPT, (u_int32_t)pdataLen, pdata);
59 }

如果感兴趣的话可以到去下载,整个测试的代码已经打包上传。下载传送门 如果作为兴趣但是不能下载,可以联系我,提供测试代码,为开源做贡献!

posted @ 2019-11-24 02:04  我就叫宋帅呀  阅读(4016)  评论(11编辑  收藏  举报