Python3 Scapy - 嗅探分段 IP 数据包

标签 python network-programming ip scapy packet-sniffers

我尝试通过以下设置来简化我的问题。

  • 本地接口(interface) (192.168.183.130) 上端口 1337 上的简单 netcat UDP 监听器
  • 一个简单的 netcat UDP 客户端连接到端口 1337 上的监听器(来自 192.168.183.128)
  • 在 192.168.183.130 上运行的非常基本的 scapy 嗅探器

Scapy 嗅探器以 root 权限运行:

from scapy.all import sniff, IP, UDP

def print_package(packet):
    packet.show()


sniff(filter="ip dst host 192.168.183.130 and dst port 1337", iface="ens33", prn=print_package)

发送具有 1500 字节 MTU 限制的 IP 数据包/UDP 帧就像一个魅力,数据包按预期打印到标准输出。一旦我成功限制并且 IP 协议(protocol)创建片段,嗅探器仅捕获第一个数据包(正确的标志、长度等)

在下面的示例中,我先从 nc 客户端向监听器发送了一个简单的字符串“下一条消息将是 3200 *“A””,然后再使用 netcat 发送 3200 *“A”。在 netcat 使用的 UDP 套接字接收数据包之前,该数据包被分成三个 IP 数据包并由堆栈正确地重新组装,因此一切都按照我期望的网络方式运行。 Scapy 只嗅探三个数据包中的第一个,我不明白为什么会发生这种情况。

屏幕截图显示了wireshark中对文本消息和三个IP片段的预期/正确处理:

Expected behavior in wireshark

以下代码片段显示了 scapy 输出到 stdout 的情况:

sudo python3 scapy_test.py 
    
    ###[ Ethernet ]### 
      dst       = 00:0c:29:fa:93:72
      src       = 00:0c:29:15:2a:11
      type      = IPv4
    ###[ IP ]### 
         version   = 4
         ihl       = 5
         tos       = 0x0
         len       = 59
         id        = 18075
         flags     = DF
         frag      = 0
         ttl       = 64
         proto     = udp
         chksum    = 0x3c3
         src       = 192.168.183.128
         dst       = 192.168.183.130
         \options   \
    ###[ UDP ]### 
            sport     = 59833
            dport     = 1337
            len       = 39
            chksum    = 0xdaa0
    ###[ Raw ]### 
               load      = 'next message will be 3200 * "A"\n'
    
    ###[ Ethernet ]### 
      dst       = 00:0c:29:fa:93:72
      src       = 00:0c:29:15:2a:11
      type      = IPv4
    ###[ IP ]### 
         version   = 4
         ihl       = 5
         tos       = 0x0
         len       = 1500
         id        = 20389
         flags     = MF
         frag      = 0
         ttl       = 64
         proto     = udp
         chksum    = 0x1518
         src       = 192.168.183.128
         dst       = 192.168.183.130
         \options   \
    ###[ UDP ]### 
            sport     = 59833
            dport     = 1337
            len       = 3209
            chksum    = 0x25bd
    ###[ Raw ]### 
               load      = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'

为什么其他 IP 片段丢失以及如何嗅探它们? 我知道 sniff 中的 session 参数,但我没有使用 session=IPSession 实际重新组装数据包。 (无论如何,这不是我想要实现的目标,对于我的应用程序,我想嗅探所有片段,更改其中的一部分并将它们转发到另一个地址/套接字。)

最佳答案

我终于自己弄清楚了,所以我要留下答案:

问题出在嗅探器的过滤器上:

sniff(filter="ip dst host 192.168.183.130 and dst port 1337", iface="ens33", prn=print_package)

第一个之后的 IP 片段没有 UDP 部分,因此没有目标端口,因此 scapy 过滤器不会捕获它们。为了解决这个问题,我扩展了过滤器以捕获 dst 端口 1337 或具有偏移量的片段。我偶然发现了这个备忘单https://github.com/SergK/cheatsheat-tcpdump/blob/master/tcpdump_advanced_filters.txt ,它为这个问题提供了有效的伯克利语法,并最终得到了这个过滤器(对于简化的问题)。

sniff(filter="ip dst host 192.168.183.130 and ((src port 1337) or (((ip[6:2] > 0) or (ip[7] > 0)) and (not ip[6] = 64))", iface="ens33", prn=print_package)

这会检查数据包的分段偏移量是否>0(第六个字节(标志)或第七个字节的前三位之后的任何内容都>0)以及是否未设置“不分段”位。如果这是真的,那么它是一个 IP 片段,嗅探器将嗅探它。

关于Python3 Scapy - 嗅探分段 IP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66478735/

相关文章:

azure - MS Azure 应用服务出站 IP 地址多久更改一次?

python - 异常类型: MissingSchema/beautifulsoup

python - pandas groupby 日期在一个季度内

c++ - 在 Qt 中获取本地 IP 地址

javascript - 仅使用 JavaScript 正则表达式检查 IP 地址范围

c - 如何将基于 DPDK 的应用程序移植到 Netmap?

python - Databricks 中的 PySpark 将表转换为 pandas 时出错

python - 如何抑制 Pandas Future 警告?

c - 如何在不使用原始套接字的情况下读取应用层中的 tcp/udp header ?

linux - sendmsg 系统调用是否验证添加到辅助数据中的 IPv6 源地址?