python-3.4 Scapy 嗅探

python-3.4 Scapy sniffing

我在 运行 这个脚本时出错:

from scapy.all import *
sn = sniff(filter="http", count=30)
wireshark(sn)

这是错误:

WARNING: No route found for IPv6 destination :: (no default route?)
WARNING: Please, report issues to https://github.com/phaethon/scapy
Traceback (most recent call last):
File "arp1.py", line 2, in <module>
sn = sniff(filter="http", count=30)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/scapy/sendrecv.py", line 566, in sniff
s = L2socket(type=ETH_P_ALL, *arg, **karg)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/scapy/arch/pcapdnet.py", line 276, in __init__
self.ins.setfilter(filter)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/scapy/arch/pcapdnet.py", line 236, in setfilter
error("Could not compile filter expression %s" % f)
NameError: name 'error' is not defined

当运行这个脚本时,一切正常:

from scapy.all import *
sn = sniff(filter="icmp and host 66.35.250.151", count=4)
wireshark(sn)

Scapy 使用 BPF syntax 进行过滤。此语法不支持指定 "http" 作为过滤器以过滤 HTTP 流量。


但是,可以过滤所有发往或源自端口 80 的流量,该端口通常用于 HTTP。上面的 link 提出了以下过滤器:

To capture all IPv4 HTTP packets to and from port 80, i.e. print only packets that contain data, not, for example, SYN and FIN packets and ACK-only packets. (IPv6 is left as an exercise for the reader.)

tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)

This Whosebug answer 清楚地解释了此过滤器背后的技术细节。简而言之,它计算数据包携带的应用层负载的字节长度,并验证它不为 0(因此为正):

  • IP 数据包长度 - IP 报头长度 - TCP 报头长度 != 0

由于文件 /etc/services 将端口号 80 分配给服务名称 http ,因此可以按如下方式重写先前的过滤器:

tcp port http and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)

为了完整性,建议也过滤端口 8080(http-alt in /etc/services)。


当然,这并不能保证过滤后的流量确实是 HTTP 流量或未过滤的流量不包含 HTTP交通。这种努力需要更复杂的过滤器。他们将检查应用层有效负载的内容,以试图推断出正在使用的底层协议。

一个简单的 google 搜索会根据您的最终目标提供多种用于各种目的的替代过滤器。例如,This Whosebug answerHTTP 的基本方法建议过滤器:一个用于 HTTP GET 方法,另一个用于 HTTP POST 方法。