我正在 Linux 网络命名空间中测试 iproute2 的本机 GRE 隧道功能。模拟设置涉及 3 个不同的命名空间、2 个网桥和 4 个 veth 对。
请参阅下面的部分以完全重新创建设置。
一个网络命名空间包含具有单个 veth 接口的纯 IPv6 网络,另一个网络命名空间包含具有单个 veth 接口的纯 IPv4 网络,第三个网络命名空间包含具有两个不同 veth 接口(IPv4 和 IPv6)的双堆栈网络。
两个 IPv6 veth 对等点连接到一个网桥,而另外两个 IPv4 veth 对等点连接到另一个网桥。使用此配置,我可以使用双栈网络命名空间中 IPv4 veth 接口的远程地址在 IPv4 网络命名空间上设置 GRE 隧道。
我还更新了 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。一旦在主机上可用,您就可以从模拟命名空间中运行 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
根据下面 Tom 的回答,我已将设置脚本更新为以下脚本:
#!/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
ip -n sim-ipv4-stack link set dev lo up
ip -n sim-ipv6-stack link set dev lo up
ip -n sim-dual-stack link set dev lo 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
SIM_DUAL_TUN6_ADDR=fc00::26
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/128 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/128 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/128 dev sim-ipv4-gre0
ip -n sim-ipv4-stack link set dev sim-ipv4-gre0 up
ip -n sim-ipv4-stack route add $SIM_DUAL_TUN6_ADDR dev sim-ipv4-gre0
ip -n sim-ipv4-stack route add $SIM_IPV6_ADDR dev sim-ipv4-gre0
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
ip -n sim-dual-stack link set dev sim-dual-gre0 up
ip -n sim-dual-stack route add $SIM_IPV4_TUN6_ADDR dev sim-dual-gre0
ip -n sim-dual-stack route add $SIM_IPV6_ADDR dev sim-dual-veth1p
ip -n sim-ipv6-stack route add $SIM_DUAL_IPV6_ADDR dev sim-ipv6-veth0p
ip -n sim-ipv6-stack route add $SIM_IPV4_TUN6_ADDR dev sim-ipv6-veth0p via $SIM_DUAL_IPV6_ADDR
# Ensure that forwarding is enabled (necessary only for the sim-dual-stack namespace).
ip -n sim-ipv4-stack netns exec sysctl -w net.ipv4.conf.all.forwarding=1
ip -n sim-ipv4-stack netns exec sysctl -w net.ipv6.conf.all.forwarding=1
ip -n sim-ipv6-stack netns exec sysctl -w net.ipv4.conf.all.forwarding=1
ip -n sim-ipv6-stack netns exec sysctl -w net.ipv6.conf.all.forwarding=1
ip -n sim-dual-stack netns exec sysctl -w net.ipv4.conf.all.forwarding=1
ip -n sim-dual-stack netns exec sysctl -w net.ipv6.conf.all.forwarding=1
set +x
我必须确保在sim-dual-stack
命名空间中启用转发(即使在主机中启用转发,情况并非如此),使用:
sysctl -w net.ipv4.conf.all.forwarding=1
sysctl -w net.ipv6.conf.all.forwarding=1
完成此操作后,我可以使用以下命令sim-ipv6-stack
从sim-ipv4-stack
命名空间成功 ping 通:
ip netns exec sim-ipv4-stack ping -6 -c 10 fc00::6
更新后的脚本包括每个网络命名空间的 sysctl 更新。
首先,您只设置了隧道的一端:
您需要在以下位置设置另一端
sim-dual-stack
:SIM_IPV4_TUN6_ADDR
您还需要一个“主机路由”sim-dual-stack
:请注意,
SIM_DUAL_TUN6_ADDR
您的脚本中没有定义。sim-dual-gre0
但实际上,考虑到您当前的“想法”,您并不完全需要在 上分配 IP 。(实际上,我认为这更多地与 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。)