设置IP头的标志字段

5 投票
3 回答
6369 浏览
提问于 2025-04-15 12:27

我有一个简单的Python脚本,它使用socket模块来发送UDP数据包。这个脚本在我的Windows电脑上运行得很好,但在我的Ubuntu Linux电脑上,发送的数据包稍微有点不同。在Windows上,IP头中的标志字段是零,但在Linux上用同样的代码创建的数据包,标志字段却是4。我想修改我的脚本,让它在Windows和Linux上表现一致。

有没有办法在socket模块中控制标志字段?还是说这是我需要在Linux上更改的设置?

3 个回答

1

你可以试试construct,它可能能帮你解决问题。

6

我最后走的这条路是这样的。我跟着SashaN在D.Shwley的回答评论中发的链接,了解了一下为什么Linux的UDP数据包会设置“不要分片”这个标志。结果发现,这和PMTU发现有关。简单来说,你可以通过在Python中使用socket对象的setsockopts函数,来清除UDP数据包中的“不要分片”标志。

import socket
IP_MTU_DISCOVER   = 10
IP_PMTUDISC_DONT  =  0  # Never send DF frames.
IP_PMTUDISC_WANT  =  1  # Use per route hints.
IP_PMTUDISC_DO    =  2  # Always DF.
IP_PMTUDISC_PROBE =  3  # Ignore dst pmtu.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("10.0.0.1", 8000))
s.send("Hello World!") # DF bit is set in this packet
s.setsockopt(socket.SOL_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT)
s.send("Hello World!") # DF bit is cleared in this packet
2

我猜这个标志字段实际上是设置为2,也就是二进制的010,而不是4,因为标志等于4是一个无效的IP数据包。记住,标志是IP头部中的一个3位值。我预计会看到UDP数据报的标志值是2,这表示“不要分片”。

至于你的问题,我认为没有办法直接设置IP标志,除非你使用原始套接字。其实也不用太担心,因为大多数应用程序并没有太多理由去直接修改IP或者UDP/TCP的头部。

撰写回答