我有以下设置:
- 具有静态 IPv6 /64 的远程服务器
- 本地(目前)仅 IPv4 家庭网络,带有服务器
- IPv4 OpenVPN 连接在两台服务器之间将 IPv6 /64 的上半部分作为 /65 进行隧道传输
由于有隧道,我的服务器现在可以通过 IPv6 成功连接到互联网,但我无法让 dnsmasq 为我的其他设备提供 IPv6。
这是我的相关部分/etc/dnsmasq.conf
:
except-interface=tun0
# pick up prefix from tun0
dhcp-range=::2,::500,constructor:tun0,slaac, 12h
enable-ra
# try to force advertisement on br0
ra-param=br0,30
启动 dnsmasq 时我得到以下输出(我将它们翻译成英文并省略了与 ipv6/路由器广告无关的部分):
Compile options: IPv6 GNU-getopt DBus i18n IDN2 DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify dumpfile
DHCP, IP-range 192.168.0.2 -- 192.168.0.100, Lease time 12h
DHCPv6, IP-range ::2 -- ::500, Lease Time 12h, template for tun0
Router-Advertisment on tun0
IPv6-Router-Advertisement enabled
默认情况下,br0 接口只有一个链接本地地址,没有来自 dnsmasq 使用的范围的地址。但是,即使为其提供了来自此范围的地址,仍只会为 tun0 报告广告。
如何让 dnsmasq 通过 br0 进行广告?
删除后的 IP 地址为
远程服务器:
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet xx.xx.xx.xx brd xx.xx.xx.xx scope global eth0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx::1/64 scope global deprecated
valid_lft forever preferred_lft 0sec
inet6 fe80::xxxx:xx:xxxx:xxxx/64 scope link
valid_lft forever preferred_lft forever
tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx:8000::1/65 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xx:xxxx:xxxx/64 scope link stable-privacy
valid_lft forever preferred_lft forever
在我的本地服务器上
br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global br0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx:8000::500/65 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xx:xxxx:xxxx:xxxx/64 scope link
valid_lft forever preferred_lft forever
tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx:8000::1000/65 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xxxx:xxxx/64 scope link stable-privacy
valid_lft forever preferred_lft forever
所有 2a01 地址的 64 位前缀都是相同的。
编辑
我尝试了以下设置gravity 的回答:
在远程服务器上 /etc/openvpn/server.conf
server-ipv6 fc00::/96
# use low metric to override existing route
route-ipv6 2a01:xxx:xxxx:xxxx::/64 ::1 1
# enable routing to remote on local server
push "route-ipv6 2a01:xxxx:xxxx:xxxx::1/128 ::1 1"
$ ip addr
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 96:00:00:27:b7:14 brd ff:ff:ff:ff:ff:ff
inet xx.xx.xx.xx brd 116.202.98.219 scope global eth0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx::1/64 scope global deprecated
valid_lft forever preferred_lft 0sec
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link
valid_lft forever preferred_lft forever
tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fc00::1/96 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link stable-privacy
valid_lft forever preferred_lft forever
$ ip -6 route
2a01:xxxx:xxxx:xxxx::/64 dev tun0 metric 1 pref medium
2a01:xxxx:xxxx:xxxx::/64 dev eth0 proto kernel metric 256 pref medium
fc00::/96 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
default via fe80::1 dev eth0 metric 1024 pref medium
在我的本地服务器上:/etc/dnsmasq.conf
# start with 3 to avoid assigning the remote eth0 and local br0 addresses
dhcp-range=::3,constructor:br0,slaac, 12h
enable-ra
$ ip addr
br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0c:c4:7a:02:09:cc brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global br0
valid_lft forever preferred_lft forever
inet6 2a01:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:9cc/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 6930sec preferred_lft 6930sec
inet6 2a01:xxxx:xxxx:xxxx::2/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link
valid_lft forever preferred_lft forever
tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fc00::1000/96 scope global
valid_lft forever preferred_lft forever
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link stable-privacy
valid_lft forever preferred_lft forever
$ ip -6 route
::1 dev lo proto kernel metric 256 pref medium
2a01:xxxx:xxxx:xxxx::1 dev tun0 metric 1024 pref medium
2a01:xxxx:xxxx:xxxx::/64 dev br0 proto kernel metric 256 pref medium
2a01:xxxx:xxxx:xxxx::/64 dev br0 proto ra metric 1024 expires 6243sec pref medium
fc00::/96 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev br0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
default dev tun0 metric 1024 pref medium
使用此配置,我的 LAN 设备从 2a01:xxxx:xxxx:xxxx/64 获取 IPv6。我可以在我的 LAN 内成功 ping 这些地址,但隧道交叉似乎已损坏:
拥有以下 IP:
- 远程服务器 eth0 2a01:xxxx:xxxx:xxxx::1
- 远程服务器 tun0 fc00::1
- 本地服务器 br0 2a01:xxxx:xxxx:xxxx::2
- 本地服务器 tun0 fc00::1000
从远程服务器,我可以 ping 除第 3 个(本地服务器 br0)之外的所有服务器。从本地服务器,我可以 ping 所有服务器。从我的 LAN,我可以 ping 所有本地服务器,但无法 ping 远程服务器。
因此,一半似乎有效。此外,我可以通过远程 tcpdump 和从另一台 IPv6 主机 ping 来验证 2a01:xxx:xxxx:xxxx/64 的所有流量是否都路由到远程的 eth0。
答案1
服务器是否有路由到它的 /64,或者它是否有可用的 /64 在线?(如果是在线,您是否已经在服务器上使用了类似 proxy_ndp 的东西?)
我之所以问这个问题,是因为许多 VPS 提供商会分配链接范围(而不是推荐的路由前缀),这意味着提供商的本地网关认为 /64 中的所有地址都是当地的:它希望向它们发送 NDP(ARP)查询,并希望您的服务器对其中任何一个做出响应。
通常,系统仅响应分配给其接口的单个地址的邻居请求,例如,在您的情况下,服务器将仅响应 2a01:xxxx:xxxx:xxxx::1,但不会对您用于 VPN 的所有地址执行任何操作。结果是服务器提供商的网关认为所有这些地址都不存在于 LAN 中,并将它们报告为无法访问。
可以通过在服务器上启用“NDP 代理”来解决这个问题,使其为您在 VPN 上使用的 /65 发送“欺骗”响应。从理论上讲,从提供商的角度来看,这应该与仅在本地拥有地址没有区别。
IPv4 OpenVPN 连接在两台服务器之间将 IPv6 /64 的上半部分作为 /65 进行隧道传输
一般情况下,您不能将 SLAAC 用于 /64 以外的任何地址。(最初是因为自动配置使用了基于 EUI64 的地址。)因此,您的第一步应该是获取较短的前缀,例如 /56 或至少 /60,您可以将其划分为多个网络。
如果您必须为 LAN 使用非 /64 前缀,那么您只能使用静态 IP 配置或 DHCPv6(对于支持它的设备;并非所有设备都支持)。
如果您没有其他选择,只能共享 /64,并且您要求要使 SLAAC 正常工作... 嗯,它必须在您的 br0 接口上配置并作为 /64 进行宣传,并且您可能必须使用代理 NDP 将两侧连接在一起。(它类似于代理 ARP,但适用于 IPv6。)也就是说,您必须使用 ndppd 来响应较低 /65 的 ND 查询。
默认情况下,br0 接口仅具有链接本地地址,而没有 dnsmasq 使用的范围的地址。
您的系统充当两个网络之间的路由器,并且每个接口应该通常具有其所属网络的地址。(就像处理 192.168.1.0/24 的路由器本身将具有该范围内的地址一样。)
但更重要的是,每个链接都需要有一个独特的分配给它的前缀。在您的“本地”系统中,您有两个使用相同 2a01:xxxx:xxxx:xxxx:8000::/65 前缀的接口 - 因此即使您的 LAN 主机配置了地址,路由器也无法正确转发数据包。即它不知道任何给定地址是否可通过 tun0 或 br0 访问 - 它只有两个 /65 路由,并且它始终会为所有流量选择相同的路由。
如果您幸运的话,它会选择 br0 路由,您的 LAN 主机将无法到达位于 2a01:xxxx:xxxx:xxxx:8000::1 的服务器本身,但其他一切可能仍然有效。如果您不幸的话,它会选择 tun0 路由,服务器将无法向 LAN 主机发送任何内容,因为数据包会被反射回来。
在这种情况下,OpenVPN 隧道实际上根本不需要使用 /65 的寻址;例如,它可以使用私有地址。无论如何,/65 应该是投入的到您的本地 br0 接口,您只需constructor:br0
在 dnsmasq 中使用。
服务器 OpenVPN 配置示例:
server-ipv6 fd6a:d884:2a8b:11b::/96
route-ipv6 2a01:xxxx:xxxx:xxxx:8000::/65
在客户端的 ccd 中:
iroute-ipv6 2a01:xxxx:xxxx:xxxx:8000::/65
服务器接口示例:
eth0: 2a01:xxxx:xxxx:xxxx:0000::1/65 (note prefix length)
tun0: fd6a:d884:2a8b:11b::1/96
客户端接口示例:
tun0: fd6a:d884:2a8b:11b::1000/96
br0: 2a01:xxxx:xxxx:xxxx:8000::1/65
dnsmasq 配置示例:
enable-ra
dhcp-range = ::2, ::500, constructor:br0, 12h
# you can't get SLAAC with a non-/64 prefix, so it's DHCPv6 only