Scapy sniff() 函数详解

sniff() 是 Scapy 中用于网络抓包的核心函数,支持丰富的参数配置。以下是详细参数说明、语法规则、示例及 filter BPF语句的编写指南。


1 函数语法

from scapy.all import sniff

sniff(
    count=0,         # 抓包数量
    store=True,      # 是否存储捕获的包
    prn=None,        # 每个包触发的回调函数
    filter=None,     # BPF 过滤规则
    iface=None,      # 指定网卡接口
    timeout=None,    # 超时时间(秒)
    lfilter=None,    # Python 函数过滤
    stop_filter=None,# 停止捕获的条件函数
    offline=None,    # 从 pcap 文件读取
    # 其他参数...
)

2 参数说明

1. count
  • 作用:捕获指定数量的数据包后停止。
  • 默认值0(无限捕获,直到手动中断)。
  • 示例
    sniff(count=10)  # 捕获10个包后停止
    
2. store
  • 作用:是否将捕获的包存储在内存中(可通过返回值访问)。
  • 默认值True。若设为 False,需通过 prn 处理包。
  • 示例
    sniff(store=False, prn=lambda x: x.summary())  # 不存储包,仅打印摘要
    
3. prn
  • 作用:为每个包调用指定函数,参数为包对象。此参数较为常用,灵活使用能满足大部分测试需求。
  • 示例
    def print_src(pkt):
        print(pkt.src)
    sniff(prn=print_src)  # 打印每个包的源地址
    
4. filter
  • 作用:使用 BPF(Berkeley Packet Filter)语法 过滤数据包。
  • 语法规则
    • 协议tcp, udp, icmp, arp, ether, ip, ip6 等。
    • 方向src, dst, src or dst, src and dst
    • 逻辑运算符and (&&), or (||), not (!)。
    • 字段匹配:如 port 80, host 192.168.1.1, net 192.168.0.0/24
  • 示例
    sniff(filter="tcp port 80")               # 捕获 HTTP 流量
    sniff(filter="icmp and host 8.8.8.8")     # 捕获到 8.8.8.8 的 ICMP 包
    sniff(filter="src 192.168.1.100 and udp") # 捕获来自 192.168.1.100 的 UDP 包
    
5. iface
  • 作用:指定抓包的网络接口(默认使用系统首选接口)。网络接口为NIC名称,可以在网络适配器属性中查看。
  • 示例
    sniff(iface="eth0")  # 捕获 eth0 接口的流量
    sniff(iface=["eth0", "wlan0"])  # 捕获多接口
    
6. timeout
  • 作用:设置最长抓包时间(秒),超时后停止。
  • 示例
    sniff(timeout=30)  # 捕获30秒后停止
    
7. lfilter
  • 作用:通过 Python 函数过滤包。活性高,但处理速度远低于 BPF,不建议使用。如有需求,可以先通过BPF进行过滤,再通过 Python 函数进行处理。
  • 示例
    def http_filter(pkt):
        return pkt.haslayer(TCP) and pkt[TCP].dport == 80
    sniff(lfilter=http_filter)
    
8. stop_filter
  • 作用:函数返回 True 时停止捕获。
  • 示例
    def stop_after_http(pkt):
        return pkt.haslayer(TCP) and pkt[TCP].dport == 80
    sniff(stop_filter=stop_after_http)  # 捕获到 HTTP 包后停止
    
9. offline
  • 作用:从 pcap 文件读取数据包(代替实时抓包)。
  • 示例
    sniff(offline="capture.pcap")  # 从 capture.pcap 文件读取
    

3 BPF语法

BPF 语法简洁高效,常用于实时过滤。以下是常见用法:

3.1 基础过滤

  • 协议tcp, udp, icmp, arp
    filter="tcp"
    
  • IP 地址host, src, dst
    filter="src 192.168.1.1"
    
  • 端口port, src port, dst port
    filter="dst port 443"
    
  • 网络段net, mask
    filter="net 192.168.0.0/24"
    

3.2 复合逻辑

  • 与操作and&&
    filter="tcp and port 80"
    
  • 或操作or||
    filter="icmp or arp"
    
  • 非操作not!
    filter="not ether host 00:11:22:33:44:55"
    

3.3 BPF语法示例

# 捕获 HTTP 或 HTTPS 流量
filter="(tcp port 80) or (tcp port 443)"

# 捕获来自 192.168.1.100 的非 ICMP 流量
filter="src 192.168.1.100 and not icmp"

# 捕获目标为 8.8.8.8 的 DNS 请求(UDP 53 端口)
filter="udp and dst port 53 and dst host 8.8.8.8"

4 sniff() 使用示例

4.1 捕获并打印 HTTP 请求的源 IP

from scapy.all import sniff, TCP

def http_parser(pkt):
    if pkt.haslayer(TCP) and pkt[TCP].dport == 80:
        print(f"HTTP Request from: {pkt[IP].src}")

sniff(filter="tcp port 80", prn=http_parser, timeout=10)

4.2 捕获 ICMP 包并保存到列表

packets = sniff(filter="icmp", count=5)
print(f"Captured {len(packets)} ICMP packets.")

4.3 组合过滤条件

# 捕获来自 192.168.1.0/24 且目标端口为 22 的 TCP 流量
sniff(filter="tcp dst port 22 and src net 192.168.1.0/24", iface="eth0")

注意事项

  • 性能优化:优先使用 filter 而非 lfilter,BPF 在内核层过滤,效率更高。
  • Windows 支持:需安装 Npcap

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐