我在通过以下方式将虚拟机连接到 IPv6 互联网时遇到问题虚拟分接设备在主机上。即,我无法 ping ipv6.google.com 或公共 IPv6 主机全局主接口地址。前任:
-bash-4.2$ ping6 ipv6.google.com
PING ipv6.google.com(sea15s11-in-x0e.1e100.net) 56 data bytes
From 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c icmp_seq=1 Destination unreachable: Address unreachable
From 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c icmp_seq=2 Destination unreachable: Address unreachable
From 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c icmp_seq=3 Destination unreachable: Address unreachable
^C
--- ipv6.google.com ping statistics ---
4 packets transmitted, 0
received, +3 errors, 100% packet loss, time 3082ms
或者到主机的全局 ipv6 地址,我得到同样的错误。
简单拓扑:
router -----(eth0)----- host ----(tap device)---- vm
主机上的邻居发现似乎存在一些问题,当我从主机的 Tap 端点 tcpdump Tap 接口时,我收到了请求消息,但没有返回任何内容:
[user ~]$ sudo tcpdump ip6 -vv -i tp-0gn-0000go-0
tcpdump: listening on tp-0gn-0000go-0, link-type EN10MB (Ethernet), capture size 262144 bytes
01:45:16.596378 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c > ff02::1:ff00:200e: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has sea15s11-in-x0e.1e100.net
source link-address option (1), length 8 (1): 02:fc:80:d4:52:b6
0x0000: 02fc 80d4 52b6
01:45:17.610410 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c > ff02::1:ff00:200e: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has sea15s11-in-x0e.1e100.net
source link-address option (1), length 8 (1): 02:fc:80:d4:52:b6
0x0000: 02fc 80d4 52b6
01:45:18.634402 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c > ff02::1:ff00:200e: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has sea15s11-in-x0e.1e100.net
source link-address option (1), length 8 (1): 02:fc:80:d4:52:b6
0x0000: 02fc 80d4 52b6
注意:我可以从主机 ping ipv6.google.com:
[user ~]$ ping6 ipv6.google.com
PING ipv6.google.com(sea15s11-in-x0e.1e100.net (2607:f8b0:400a:808::200e)) 56 data bytes
64 bytes from sea15s11-in-x0e.1e100.net (2607:f8b0:400a:808::200e): icmp_seq=1 ttl=39 time=9.93 ms
64 bytes from sea15s11-in-x0e.1e100.net (2607:f8b0:400a:808::200e): icmp_seq=2 ttl=39 time=10.1 ms
64 bytes from sea15s11-in-x0e.1e100.net (2607:f8b0:400a:808::200e): icmp_seq=3 ttl=39 time=10.1 ms
邻居发现似乎存在问题。我不确定我是否面临 DAD、NUD 或其他问题,或者可能根本不是邻居发现问题?
我目前只有 中的路由器ip -6 neigh show
,但我对邻居发现缓存的印象只是一个缓存,并且路由应该仍然完整且可发现(尽管这是我非常有限的理解)。也许我缺少一些邻居发现/广告内核参数?
[user ~]$ ip -6 neigh show
fe80::460:a1ff:fec3:9cb6 dev eth0 lladdr 06:60:a1:c3:9c:b6 router STALE
我有预感,我net.ipv6
在这里缺少一些内核参数,但我不太确定从哪里开始修改它们。非常感谢任何建议。完整的网络设置信息可以在下面找到。请注意,我手动配置了虚拟机全局地址,因此它与主机非常相似,一个是:XXXb/128,一个是:XXXc/128。
VM端点-接口:
-bash-4.2$ ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:fc:80:d4:52:b6 brd ff:ff:ff:ff:ff:ff
inet 169.254.18.177/30 brd 169.254.18.179 scope global eth0
valid_lft forever preferred_lft forever
inet6 2600:1f14:680:xxxx:66a3:79d5:6c1d:14c/128 scope global
valid_lft forever preferred_lft forever
inet6 fe80::fc:80ff:fed4:52b6/64 scope link
valid_lft forever preferred_lft forever
以及相关的VM路由:
-bash-4.2$ ip -6 r s
2600:1f14:680:6f00:66a3:79d5:6c1d:14c dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth1 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default dev eth0 metric 1024 pref medium
主机 - 分接头和主接口如下所示:
[user ~]$ ip a s tp-0gn-0000go-0
2393: tp-0gn-0000go-0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether d2:d5:4e:f3:de:ab brd ff:ff:ff:ff:ff:ff
inet 169.254.18.178/30 scope global tp-0gn-0000go-0
valid_lft forever preferred_lft forever
inet6 fe80::d0d5:4eff:fef3:deab/64 scope link
valid_lft forever preferred_lft forever
[user ~]$ ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 06:b6:f7:16:ac:04 brd ff:ff:ff:ff:ff:ff
inet 172.30.255.4/28 brd 172.30.255.15 scope global dynamic eth0
valid_lft 2994sec preferred_lft 2994sec
inet6 2600:1f14:680:6f00:66a3:79d5:6c1d:14b/128 scope global dynamic
valid_lft 405sec preferred_lft 105sec
inet6 fe80::4b6:f7ff:fe16:ac04/64 scope link
valid_lft forever preferred_lft forever
以及相关路线:
[user ~]$ ip -6 r s
2600:1f14:680:6f00:66a3:79d5:6c1d:14b dev eth0 proto kernel metric 256 expires 389sec pref medium
2600:1f14:680:6f00:66a3:79d5:6c1d:14c dev tp-0gn-0000go-0 metric 1024 pref medium
2600:1f14:680:6f00::/64 dev eth0 proto kernel metric 256 pref medium
unreachable 3ffe:ffff::/32 dev lo metric 1024 error 4294967183 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fe80::460:a1ff:fec3:9cb6 dev eth0 proto ra metric 1024 expires 1798sec hoplimit 64 pref medium
ip6tables 过滤器允许一切
[user ~]$ sudo ip6tables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
主机是amazon-linux,类似于centos/rhel/fedora,cat /etc/os-release
:
NAME ="Amazon Linux"
VERSION="2"
ID_LIKE="centos rhel fedora"
非常感谢任何建议。如果我遗漏了任何必要的信息或任何概念性的信息,请告诉我。提前致谢。
更新:另外我应该注意到,当侦听主机的 eth0 并尝试从虚拟机 ping ipv6.google.com 时,我没有收到任何 tcpdump 数据包。从第一个 tcpdump 中可以看出,数据包首先被发送到所有节点请求多播地址,该地址应该通过 eth0 路由(基于本地路由表),但我从未看到数据包通过 tcpdump 通过 eth0。我目前有net.ipv6.conf.all.forwarding=1
、net.ipv6.conf.all.accept_ra=2
、 和net.ipv6.conf.all.accept_ra_from_local=1
。
更新#2:我遇到了这文章。我添加net.ipv6.conf.all.proxy_ndp=1
并添加了一个代理邻居,ip -6 neigh add proxy <host eth0 global ip6 addr> dev <tap device>
它允许我从虚拟机 ping 主机的 eth0 全局地址。尽管我觉得我已经接近了,但仍然无法从虚拟机连接到 ipv6.google.com。
更新#2.5:我认为之前的更新是无关紧要的。我认为问题的核心是虚拟机不知道任何路由器,因此它会发出邻居请求以获取全局 ipv6 地址。我认为情况不应该如此,但这只是我的预感。我还没有找到一个很好的资源,明确说明何时应发送邻居请求、路由器请求和回显请求。
更新#3:我取消了手动分配地址的操作,并尝试让虚拟机与 DHCP 服务器(顺便说一句,这是在 EC2 vpc 中)通信以获得其地址。我在主机中添加了 DHCPv6 中继,但是中继消息似乎被发送到 DHCPv6 服务器并且永远不会返回。如果其他人感兴趣,我很乐意发布有关此的更多信息/tcpdump。
答案1
以下是我认为错误的地方以及解决方法。
虚拟机端
第一个问题是虚拟机上的这个问题:
default dev eth0 metric 1024 pref medium
这使得人们相信虚拟机的路由堆栈整个互联网都可以直接在链接上使用以太网0。因此对于任何IPv6 目的地它将发送 NDP 请求,但没有任何东西(包括主机)会回答它。
要解决此问题,虚拟机只需使用主机作为路由器及其本地链路地址。它可以简单地在虚拟机上手动配置:
ip -6 route delete default dev eth0
ip -6 route add default via fe80::d0d5:4eff:fef3:deab dev eth0
对于VM 端来说就是这样。
虚拟机(和主机)上的备用设置TP-0gn-0000go-0)
如果您不想使用链接本地地址(例如:如果由于主机上的随机 MAC 地址而导致重新启动时该地址可能会更改)TP-0gn-0000go-0),您可以通过将主机的全局 IP 地址复制到TP-0gn-0000go-0。
在主机上,还要添加其 IP 地址TP-0gn-0000go-0作为/128(或者如果noprefixroute
已经不仅仅是一个/128):
ip -6 address add 2600:1f14:680:6f00:66a3:79d5:6c1d:14b/128 dev tp-0gn-0000go-0
在虚拟机上,而不是上面:
ip -6 route delete default dev eth0
ip -6 route add 2600:1f14:680:6f00:66a3:79d5:6c1d:14b/128 dev eth0
ip -6 route add default via 2600:1f14:680:6f00:66a3:79d5:6c1d:14b dev eth0
主机端(上以太网0)
主机自己的路由器不知道虚拟机,因为虚拟机在主机的路由器上不存在以太网0边。当来自互联网的数据包到达主机的路由器时,它会执行以下操作:邻居恳求,但没有任何东西可以回答它,包括主机(当然,除非可以以其他方式配置该路由器,这会简化一切)。主机必须配置为ND代理实际回答这个请求,以便最终它将数据包发送到主机。
为此,请在主机上启用proxy_ndp
在以太网0,和proxy_ndp
添加特定的 NDP 代理条目(仅当在接口上启用时才有效):
sysctl -w net.ipv6.conf.eth0.proxy_ndp=1
ip -6 neighbour add proxy 2600:1f14:680:6f00:66a3:79d5:6c1d:14c dev eth0
(邻居代理条目可以通过 来显示ip neighbour show proxy
和删除ip neighbour flush proxy
。默认情况下不通过 来显示ip neighbour
或删除ip neighbour flush all
)
主机现在将接收数据包2600:1f14:680:6f00:66a3:79d5:6c1d:14c
并将其路由到虚拟机(如其路由表中所定义)。
现在两个方向都已正确转发:它应该可以工作。
我没有尝试使用路由器广告守护进程之类的东西(radvd
)自动配置虚拟机的路由,因为它与SLAAC它应该用于不小于 /64 的东西,我不确定它是否会起作用。
更新:正如 @uMdRupert 所提到的,只要激活转发(net.ipv6.conf.all.forwarding=1
),如果由路由器通告配置,主机上也需要此设置:
sysctl -w net.ipv6.conf.eth0.accept_ra=2
原因是默认情况下 Linux IPv6 路由器会忽略路由通告(我猜原因是:因为它已经配置为路由器,所以无需更改此配置)。所以只需激活 IPv6转发在通过路由器通告接收其默认路由的主机上(如此类路由中所示proto ra [...] expires 1798sec
),可能会在一段时间后(或配置更改后重新启动时)丢失该路由并变得无法访问。这必须被否决,以仍然允许接受此类 RA以太网0经过设置accept_ra
为 2。
答案2
您可以创建一座桥并将您的eth0
和连接tp-0gn-0000go-0
到它。
ip link add name br0 type bridge
ip link set dev br0 up
ip link set dev eth0 master br0
ip link set dev tp-0gn-0000go-0 master br0
(小心,当eth0
加入网桥时,它会丢失 IP,如果您是远程执行此操作,则必须确保它会获得一个)
此时桥已搭建完毕。现在,您可以使用您正在使用的任何方法分配地址eth0
(如果是 SLAAC,那么您无需执行任何操作),如果是 DCHPv4 dhcp eth0
,那么...
启动虚拟机,您应该已准备就绪。