为什么在使用 iproute2 进行 GRE 隧道传输时会观察到 ICMP 目标端口不可达(类型 3,代码 3)?

为什么在使用 iproute2 进行 GRE 隧道传输时会观察到 ICMP 目标端口不可达(类型 3,代码 3)?

我正在 Linux 网络命名空间中测试 iproute2 的原生 GRE 隧道功能。模拟设置涉及 3 个不同的命名空间,其中有 2 个网桥和 4 个 veth 对。

请参阅下面的部分来完全重新创建设置。

一个网络命名空间包含一个具有单个 veth 接口的纯 IPv6 网络,另一个网络命名空间包含一个具有单个 veth 接口的纯 IPv4 网络,第三个网络命名空间包含一个具有两个不同 veth 接口(IPv4 和 IPv6)的双栈网络。

两个 IPv6 veth 对等体连接到一个网桥,而另外两个 IPv4 veth 对等体连接到另一个网桥。使用此配置,我能够在 IPv4 网络命名空间上设置 GRE 隧道,并使用双栈网络命名空间中 IPv4 veth 接口的远程地址。

我还更新了 IPv4 网络命名空间中的路由,以便对所有 IPv6 地址使用 GRE 隧道设备。但是,当对 IPv6 地址执行单个 ping 时,我观察到数据包已使用 GRE(以太网 > IPv4 > GRE > IPv6 > ICMPv6)正确封装和发送,但会自动返回 ICMP 目标端口不可达(类型 3,代码 3)消息。测试 TCP 连接时,我得到了相同的响应。

在此上下文中,此错误意味着什么?是否存在配置错误?我应该注意,从远程网络命名空间,我能够毫无问题地 ping IPv6 目标地址。我对 GRE 隧道还不太熟悉,因此可能存在一些概念上的误解。


要重新创建设置,您可以运行以下脚本:

#!/usr/bin/env bash

set -x

# Create network namespaces
ip netns add sim-ipv4-stack
ip netns add sim-ipv6-stack
ip netns add sim-dual-stack

# Create and configure bridge links
ip link add sim-ipv4-br0 type bridge
ip link add sim-ipv6-br0 type bridge

ip link set dev sim-ipv4-br0 up
ip link set dev sim-ipv6-br0 up

# Create and configure veth links
ip link add sim-ipv4-veth0 type veth peer sim-ipv4-veth0p
ip link add sim-ipv6-veth0 type veth peer sim-ipv6-veth0p
ip link add sim-dual-veth0 type veth peer sim-dual-veth0p
ip link add sim-dual-veth1 type veth peer sim-dual-veth1p

ip link set dev sim-ipv4-veth0 master sim-ipv4-br0
ip link set dev sim-ipv6-veth0 master sim-ipv6-br0
ip link set dev sim-dual-veth0 master sim-ipv4-br0
ip link set dev sim-dual-veth1 master sim-ipv6-br0

ip link set dev sim-ipv4-veth0p netns sim-ipv4-stack
ip link set dev sim-ipv6-veth0p netns sim-ipv6-stack
ip link set dev sim-dual-veth0p netns sim-dual-stack
ip link set dev sim-dual-veth1p netns sim-dual-stack

ip link set dev sim-ipv4-veth0 up
ip link set dev sim-ipv6-veth0 up
ip link set dev sim-dual-veth0 up
ip link set dev sim-dual-veth1 up

ip -n sim-ipv4-stack link set dev sim-ipv4-veth0p up
ip -n sim-ipv6-stack link set dev sim-ipv6-veth0p up
ip -n sim-dual-stack link set dev sim-dual-veth0p up
ip -n sim-dual-stack link set dev sim-dual-veth1p up

SIM_IPV4_ADDR=172.20.0.4
SIM_IPV6_ADDR=fc00::6
SIM_DUAL_IPV4_ADDR=172.20.0.14
SIM_DUAL_IPV6_ADDR=fc00::16
SIM_IPV4_TUN6_ADDR=fc00::4

ip -n sim-ipv4-stack addr add $SIM_IPV4_ADDR/24 dev sim-ipv4-veth0p
ip -n sim-ipv6-stack addr add $SIM_IPV6_ADDR/64 dev sim-ipv6-veth0p
ip -n sim-dual-stack addr add $SIM_DUAL_IPV4_ADDR/24 dev sim-dual-veth0p
ip -n sim-dual-stack addr add $SIM_DUAL_IPV6_ADDR/64 dev sim-dual-veth1p

# Configure GRE tunnel
ip -n sim-ipv4-stack tunnel add sim-ipv4-gre0 mode gre remote $SIM_DUAL_IPV4_ADDR
ip -n sim-ipv4-stack addr add $SIM_IPV4_TUN6_ADDR/64 dev sim-ipv4-gre0
ip -n sim-ipv4-stack link set dev sim-ipv4-gre0 up

set +x

要拆除这个模拟设置,您可以运行:

#!/usr/bin/env bash

set -x

# Destroy veth links
ip link del sim-ipv4-veth0
ip link del sim-ipv6-veth0
ip link del sim-dual-veth0
ip link del sim-dual-veth1

# Destroy bridge links
ip link del sim-ipv4-br0
ip link del sim-ipv6-br0

# Destroy namespaces
ip netns del sim-ipv4-stack
ip netns del sim-ipv6-stack
ip netns del sim-dual-stack

set +x

成功创建设置后,您可以sim-ipv4-stack使用以下命令进入命名空间:

ip netns exec sim-ipv4-stack bash

您应该在该命名空间中打开两个单独的终端,一个用于观察流量,另一个用于发送流量。

为了观察流量,您应该下载并安装术语鲨鱼。一旦您在主机上可以使用它,您就可以在模拟命名空间内运行 termshark,如下所示:

ip netns exec sim-ipv4-stack bash
termshark -i sim-ipv4-veth0p

然后,您可以使用以下命令从命名空间中的另一个 shell 发送流量sim-ipv4-stack

ip netns exec sim-ipv4-stack bash
ping -6 -c 1 fc00::16

查看 termshark,您应该观察到最初发送了一个封装的 ICMPv6 数据包,然后发送了一个类型/代码为目标端口不可达的响应 ICMP 数据包。

我不确定为什么目的地被视为无法到达,因为您可以从双栈命名空间 ping IPv6 命名空间,如下所示:

ip netns exec sim-dual-stack ping -6 -c 10 fc00::6

类似地,您可以从双栈命名空间 ping IPv4 命名空间,如下所示:

ip netns exec sim-dual-stack ping -c 10 172.20.0.4

答案1

首先,您只设置了隧道的一端:

ip -n sim-ipv4-stack tunnel add sim-ipv4-gre0 mode gre remote $SIM_DUAL_IPV4_ADDR

您需要设置另一端sim-dual-stack

ip -n sim-dual-stack tunnel add sim-dual-gre0 mode gre remote $SIM_IPV4_ADDR
ip -n sim-dual-stack addr add $SIM_DUAL_TUN6_ADDR/128 dev sim-dual-gre0 # You probably shouldn't use /64 here
ip -n sim-dual-stack link set dev sim-dual-gre0 up

SIM_IPV4_TUN6_ADDR而且您还需要一个“主机路由” sim-dual-stack

ip -6 r add fc00::4/128 dev sim-dual-gre0

请注意,SIM_DUAL_TUN6_ADDR脚本中未定义。但事实上,根据您当前的“想法”,您确实不需要在 上分配 IP sim-dual-gre0。(实际上,我认为这与 GRE 隧道是 L3/点对点隧道这一事实有关。)

我说的“想法”是指,您使用一个子网 ( fc00::16/64) 作为设置的“IPv6 部分”和 GRE 隧道(“嵌套”在“IPv4 部分”中)。由于我不知道您的最终目标到底是什么(好吧,我猜您想将其用作 的sim-dual-stack某种“IPv6 中继” sim-ipv4-stack),我想我应该就此打住,但您应该知道 中的主机在sim-ipv6-stack“定位” 时会遇到问题SIM_IPV4_TUN6_ADDR,至少在您设置 中的“NDP 代理”(假设有这样的代理)之前是这样sim-dual-stack

PS 由于 GRE 隧道是 L3/点对点隧道,显然就像 IPv4 的情况一样,其中没有利用 ARP,对于 IPv6 NDP 也不会被利用。换句话说,路由到隧道的任何东西都会到达另一端,并且不需要在任何路由中指定路由器/网关。(不过我可能是错的,因为我真的不了解 IPv6。)

相关内容