之前讲了关于netfilter和iptables的一些简单的原理和用法,对于iptables来说,如果只能对封包进行DROP、ACCEPT操作,那么就显得太弱了,其实在我看来iptables里面filter表中最牛逼的就在于QUEUE(NFQUEUE)这个target了。
那么当iptables将封包插入QUEUE后,用户态又能用什么方法才能读到queue中的数据呢?
这里介绍两种方法,一种是C语言中使用的libipq,一种是python中使用的nfqueue。
libipq
libipq是一个对开发者提供的用于读取iptables queue的C库,具体的用法可以参看和的用法,需要注意的是在我的机器中必须得再加三个头文件:
#include#include #include
另外编译出来的文件必须得用sudo执行!!!
这里主要用了一个数据结构
1 2 3 |
struct ipq_handle *h; h = ipq_create_handle(0, PF_INET); |
另外需要设置一个模式,这里是IPQ_COPY_PACKET,即是将queue中的封包的payload和header一起拷贝到用户空间:
1
|
status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE); |
之后通过:
1
|
status = ipq_read(h, buf, BUFSIZE, 0); |
将queueu中的封包一个一个拷贝到用户空间,由用户进行操作,用户可以通过:
1
|
ipq_message_type(buf) |
得到包的类型,可能是NLMSG_ERROR,也有可能是IPQM_PACKET,如果是后者,即为一个正常的封包,可以通过类似于如下的代码对封包进行操作:
7 8 9 10 11 12 13 14 15 |
case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); struct iphdr *ip = (struct iphdr*) m->payload; struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl)); int port = htons(tcp->dest); status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); break; } } |
上段代码的意思是先从buf中获得整个封包m,之后可以通过struct iphdr和struct tcphdr获得ip包头和tcp包头,最后有一个最关键的代码:
1
|
status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL); |
这里的意思相当于原来在规则中target设为ACCEPT,当然也可以设置成NF_DROP等。
在这里我有一个疑问,就是这里除了获得struct tcphdr之外,我没有找到和TCP的payload相关的结构,不知道该如何获得。
nfqueue
和C的libipq比起来,支持python的nfqueue会显得强大很多,特别是和scapy结合起来用的时候。
首先需要说明的是在iptables中的target除了之前提到的五项(ACCEPT,DROP,RETURN,QUEUE,other_chain)之外,还有一个叫NFQUEUE,它是QUEUE的扩展。相比于QUEUE,它可以由用户指定不同的queue number。
在使用nfqueue之前,需要安装如下的包:
$ sudo aptitude install libnetfilter-queue-dev $ sudo aptitude install nfqueue-bindings-python $ sudo aptitude install python-scapy
之后就可以采用python对NFQUEUE进行操作了。
假设我们将封包从主机A(192.168.1.1)传输到主机B(192.168.1.2)时,需要对封包进行分析,如果是TCP协议的包,并且其flags为 ACK|PSH 的话,则将其payload进行修改(比如替换成“hack”):
首先,需要先在主机A中对iptables进行操作:
$ sudo iptables -A OUTPUT -d 192.168.1.2 -p tcp -j NFQUEUE
这里用到了scapy这个非常牛逼的模块,它可以直接通过如IP(),TCP()等直接对包进行解释和操作,非常方便,具体的可以参看它的文档。这里只是说明下它的安装方式:
$ wget scapy.net $ mv index.html scapy-latest.zip $ chmod +x scapy-latest.zip $ mv scapy-latest.zip /usr/local/bin/scapy
然后就可以运行:
$ sudo scapy
直接开启scapy的交互模式了。