Ubuntu 22.04
我正在 Linux 中试验IPv6
协议栈,并试图找出哪些协议被支持作为 L3 层协议IPv6
。根据IANA
我运行了以下简单代码来检查定义的每个协议号的回复:
for i in range(1, 148):
send(IPv6(src="::1", dst="::1", nh = i))
sleep(1)
我发现sudo tcpdump ip6 -n -vvv -i lo
大多数协议都不受支持,例如:
00:31:12.081361 IP6 (hlim 64, next-header unknown (37) payload length: 0)
::1 > ::1: ip-proto-37 0
00:31:12.081371 IP6 (flowlabel 0x11111, hlim 64, next-header ICMPv6 (58) payload length: 48)
::1 > ::1: [icmp6 sum ok] ICMP6, parameter problem, next header - octet 6
这意味着 LinuxIPv6
协议栈实现不理解协议号(在本例中是37
)。
除扩展头号码外,唯一支持的数字是:
TCP, next header = 6
UDP, next header = 17
ICMPv6, next header = 58
PIM, next header = 103
UDPLite, next header = 136
请注意,即使IPv6, next header = 41
没有被识别。这是否意味着Linux的IPv6
实现在某种意义上不符合要求RFC 8200
?
我怀疑您没有加载必要的内核模块,或者您正在运行已编译这些功能的内核。
看起来
ip6_tunnel
模块是实现“原始 IP6-in-IP6”(协议 41)隧道类型的地方。(IP6-in-IP4 等效物,Linux 称之为sit
,实际上更常用。)通常,创建“ip6tnl”隧道接口会导致模块自动加载 - 这种“按需”机制之所以有效,是因为如果没有隧道接口,内核无论如何都不会接受这种隧道数据包。对于通用的 anyIP-in-anyIP 隧道,通常会使用 GRE(协议 47),它也绝对受到所有 Linux 版本的支持 - 但同样
ip6_gre
在大多数发行版上可作为模块()使用,并在您创建“gre”或“ip6gre”类型的隧道接口时自动加载。Linux 还支持 ESP(协议 50)和 AH(协议 51)作为其 IPsec 实现的一部分;当通过 strongSwan 之类的程序设置IPsec转换时,这些协议会被加载。
同样,还有几种很少使用的传输协议,例如 SCTP(协议 132)或 DCCP(协议 33),它们没有加载到内核中,因为典型的台式电脑上几乎没有任何东西使用它们。打开 SCTP 套接字将触发模块加载,并使内核开始识别协议 132 数据包。
一些其他协议,例如 OSPF(协议 89),由用户空间(Bird 或 FRR ospfd)
SOCK_RAW
使用所需的 IPPROTO_* 值打开套接字来处理。