使用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 }

如果感興趣的話可以到去下載,整個測試的代碼已經打包上傳。下載傳送門 如果作為興趣但是不能下載,可以聯系我,提供測試代碼,為開源做貢獻!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM