我的提供商 Internet 路由器使用 IPv6 地址时遇到问题,我意识到我并不真正了解如何使用 IPv6 地址。为了得到一个想法,我想问一下如何使用不同的 IPv6 地址类型,例如将流量从一台主机路由到另一台主机,它们之间只有一个路由器。
Using three nodes:
┏━━━━━━━━━┓ addr: 2001:db8:0:10::1/64 addr: 2001.db8:0:20::1/64 ┏━━━━━━━━━┓
┃ host-a ┃ ╲ ┏━━━━━━━━━━┓ ╱ ┃ host-b ┃
┃ eth0┣════════════════════════┫eth0 eth1┣════════════════════════┫eth0 ┃
┗━━━━━━━━━┛ ╲ ┃ router ┃ ╱ ┗━━━━━━━━━┛
addr: 2001:db8:0:10::2/64 ┗━━━━━━━━━━┛ addr: 2001:db8:0:20::2/64
subnet: 2001:db8:0:10::/64 subnet: 2001:db8:0:20::/64
我该如何设置?
到目前为止,我还没有找到像这样的简单示例来参考源代码来理解基础知识。这更像是一个概念的证明,但它花了我一些努力,所以我将逐步与社区分享。
准备工作
我在 KVM(基于内核的虚拟机)上使用三个虚拟机,全部使用 Debian 11(bullseye,此时为测试版本)并使用RFC 2460中的术语:
Node是启用 IPv6 的接口。
路由器是转发未明确寻址的 IPv6 数据包的任何节点。
主机是不是路由器的任何节点。
我们需要一些帮助程序,只要我们在节点上可以访问互联网,就应该在重新配置其网络接口以进行测试之前安装这些帮助程序。在所有节点上安装
radvdump
并在路由器上安装radvd
。一定要radvd
禁用,否则会混淆测试。我将使用tcpdump
查看网络上发生的情况,因此将其安装在路由器上。在 Debian 上,我通过以下方式完成所有这些操作:我使用 IPv6 地址前缀2001:DB8::/32 Reserved for Documentation ( RFC 3849 ),它可用于有效的全球单播地址,但不路由到 Internet。
要手动处理,这里有一些规范:
使用了一些地址类型(RFC 4291)
多播地址范围 ( RFC 4291 ):
众所周知的 IPv6 多播地址(摘录 - IANA的完整列表):
通过以下方式启用systemd-networkd
使用 systemd-networkd 进行一般网络的快速步骤一节,然后回到这里。
我将禁用所有内容,以便我们可以看到需要什么并逐步启用它。打开
host-a
并host-b
使用此网络文件:在路由器上使用这些:
简单的本地链接连接
首先,我将看一下
host-a
和之间的直接联系router
。路由器已启动,我开始host-a
。tcpdump
在子网 2001:db8:0:10/64 上显示我:host-a
作为多播组的侦听器加入ff02::16
- 所有支持 MLDv2 的路由器。路由器现在知道它想要接收路由消息。host-a
可以使用地址。ping 到
router
作品:链路本地单播地址
在下一步中,我想连接到eth1上的第二个接口
router
。为此,我们需要一个静态路由:但
ping6 -n 2001:db8:0:20::1
工作不稳定:如果你按照这个
seq
数字,你会看到 ping 延迟为 1 秒,它在大约 10 秒后被中断,并在大约 45 秒后重复,丢包率约为 80%。这不能称为稳定。我不太了解它,但在寻找故障排除时了解这种行为是件好事。无论如何,它不符合规范,因为对于链接(2001:db8:0:10:2 到 2001:db8:0:10:1)上的连接,必须使用RFC 4291 - Link-Local中指定的链接本地地址IPv6 单播地址:检查接口上的链路本地地址。那里没人:
我通过在所有节点上
LinkLocalAddressing=ipv6
的所有文件中进行设置、重新启动、检查和 ping 来启用它:/etc/systemd/network/*.network
作品。
静态路由
如果我尝试从连接
host-a
到host-b
然后ping6 -n 2001:db8:0:20::2
失败。那是因为router
它不会在其接口之间转发包。我们必须启用它。只需附加IPForward=ipv6
到*.network
文件。我们还需要一个静态路由,host-b
以便它知道将回复发送到哪里host-a
。我们现在会坚持下去。所以你会得到以下.network
文件:主机-a
路由器
主机-b
路由器广告
静态路由不是很舒服。这通常是自动完成的。主机可以向路由器询问其配置。要支持它,您必须
IPv6AcceptRA=yes
在其/etc/systemd/*.network
文件中启用。如果你这样做,你会tcpdump
在启动主机时发现:除了已知的包
multicast listener report v2
,neighbor solicitation
我们还发现了router solicitation
包。通过此消息,主机向路由器请求接口配置。但是router
没有回应,所以主持人继续询问。在 Linux 上,IPv6 路由器不会立即回复路由器请求。它需要额外的服务radvd
来管理它。我们已经安装了它但禁用了它。使用来自 Debian 的简单示例,/usr/share/doc/radvd/examples/simple-radvd.conf
我们现在配置并启用它:因为我们希望主机现在从路由器获取配置,所以我们必须从其
.network
文件中删除手动设置。它们应该如下所示:主机-a和主机-b:
路由器:
Reboot all nodes and you should have an autoconfigured running simple network.
Simplifications
To show what's needed I explicitly wrote the options into the network configuration files. But most of them are default settings, so we can just omit them.
host-a and host-b:
router:
Debug
You may need to check if the host gets the correct settings from the router, or there is a router, for example from you internet provider, from that you must know what exactly settings it sends. Then you can start
radvdump
to view the received Router Advertisement. If you start it, just wait a little bit until a Router Advertisement is received. This is it with the default settings fromrouter
:Name Resolution
Name resolution over the complete network is only possible with a DNS server. Its setup is a new question and out of scope here. Not having a DNS server available on this simple network is also the reason why we always use ping6 with option
-n
which suppresses querying a DNS server to translate the ip address. Without-n
, ping6 tries to connect to a DNS server for each request with a timeout. This slows down pinging drastically and isn't usable.For the local link it is no problem to enable multicast DNS (mDNS) so you have name resolution for the direct connected nodes. Just add option
to the
[Network]
section on every nodes/etc/systemd/network/*.network
file. Then you should be able toBut
ping6 -n host-b.local
will not work fromhost-a
because mDNS is not routable.References: