Python - 如何在 UDP 数据报中设置 IPv6_HOPLIMIT

Python - how to set IPv6_HOPLIMIT in UDP datagram

如何在 Python 套接字中设置 IPv6 跳数限制?对于 IPv4 TTL,以下代码有效:

import socket
import binascii
ttl=70
target_ip='8.8.8.8'
target_port=53
hexstream='a2d2012000010000000000010377777706676f6f676c6503636f6d00000100010000291000000000000000'
message=binascii.unhexlify(hexstream)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
s.sendto(message, (target_ip, target_port))
data, address = s.recvfrom(4096)
print(f"Received response from {address}")
s.close()

但是当我尝试修改 IPv6 跃点限制时,出现“协议不可用”错误。

import socket
import binascii
hop_limit=61
target_ip="2001:4860:4860::8888"
target_port=53
hexstream='a2d2012000010000000000010377777706676f6f676c6503636f6d00000100010000291000000000000000'
message=binascii.unhexlify(hexstream)
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_IP, socket.IPV6_HOPLIMIT, hop_limit)
s.sendto(message, (target_ip, target_port))
data, address = s.recvfrom(4096)
print(f"Received response from {address}")
s.close()

输出:

>>> s.setsockopt(socket.SOL_IP, socket.IPV6_HOPLIMIT, hop_limit)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 92] Protocol not available

IPv6 的 API 在许多情况下不同于 IPv4 API。对于 IPv6,不可能使用 setsockopt 设置跳数限制。相反,它需要使用 sendmsg.

为每个单独的数据报发送
import socket
import struct

hop_limit = 11
msg = b"test"
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

s.sendmsg([msg],
    [(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, struct.pack("i",hop_limit))],
    0, ('::1',1234))

使用tcpdump验证:

$ sudo tcpdump -i lo -v port 1234
... IP6 (flowlabel 0xfc1e4, hlim 11, ...) ::1.51437 > ::1.1234: ... UDP, length 4
                            ^^^^^^^