IPv6
在 Arch Linux 中,默认启用 IPv6。
tldp Linux+IPv6-HOWTO 文章较旧,维护较少。然而,它尝试涵盖本文中提到的许多主题,从基础知识开始,并以较慢的速度推进。它还包含许多命令行示例。初学者可能希望在阅读这篇 wiki 文章之前阅读或浏览它。
邻居发现
Ping 组播地址 ff02::1
会导致链路本地范围内的所有主机响应。必须指定接口
$ ping ff02::1%eth0
之后,您可以使用以下命令获取本地网络中所有邻居的列表
$ ip -6 neigh
使用 ping 组播地址 ff02::2
只有路由器会响应。
如果您添加选项 -I your-global-ipv6
,链路本地主机将使用它们的链路全局范围地址进行响应。在这种情况下,可以省略接口
$ ping -I 2001:4f8:fff6::21 ff02::1
要 ping 所有接口上的所有人,并将您的地址通告给所有人,请使用脚本。
#!/usr/bin/bash declare -a l_ifs readarray l_ifs < <(/sbin/ip -6 -j address | jq -r '.[] | .ifname ') for l_if in ${l_ifs[@]} ; do echo $l_if declare -a l_addrs readarray l_addrs < <(/sbin/ip -6 -j address show dev "$l_if" | \ jq -r '.[0].addr_info[].local') for l_addr in ${l_addrs[@]} ; do echo $l_addr ping -c 4 -6 -I "$l_addr" ff02::1%"$l_if" done done
无状态自动配置 (SLAAC)
只要您的网络已配置,获取 IPv6 地址的最简单方法是通过无状态地址自动配置(简称 SLAAC)。地址从您的路由器通告的前缀自动推断,既不需要进一步配置,也不需要专门的软件,例如 DHCP 客户端。
客户端
如果您使用 netctl,您只需要将以下行添加到您的以太网或无线配置中。
IP6=stateless
如果您使用 NetworkManager,如果网络中有针对 IPv6 地址的通告,它将自动启用 IPv6 地址。
请注意,无状态自动配置工作的条件是 IPv6 icmp 数据包在整个网络中被允许。因此,对于客户端,必须接受 ipv6-icmp
数据包。如果您使用 简单有状态防火墙/iptables,您只需要添加
-A INPUT -p ipv6-icmp -j ACCEPT
如果您使用其他防火墙前端(ufw、shorewall 等),请查阅其文档,了解如何启用 ipv6-icmp
数据包。
如果您选择的网络管理解决方案不支持使用无状态 IPv6 配置 DNS 解析器(例如 netctl),则可以使用 rdnssd(8),它来自 ndisc6 软件包。
网关
为了正确地将 IPv6 分发给网络客户端,我们需要使用通告守护进程。此任务的标准工具是 radvd。radvd 的配置相当简单。编辑 /etc/radvd.conf
以包含
# replace LAN with your LAN facing interface interface LAN { AdvSendAdvert on; MinRtrAdvInterval 3; MaxRtrAdvInterval 10; prefix ::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; }; };
上述配置将告诉客户端使用通告的 /64 区块中的地址自动配置自己。请注意,上述配置通告分配给面向 LAN 接口的所有可用前缀。如果您想限制通告的前缀,而不是 ::/64
,请使用所需的前缀,例如 2001:DB8::/64
。prefix
区块可以重复多次以用于更多前缀。
要将 DNS 服务器通告给您的 LAN 客户端,您可以使用 RDNSS 功能。例如,将以下行添加到 /etc/radvd.conf
以通告 Google 的 DNS v6 服务器
RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 { };
网关还必须允许 ipv6-icmp
数据包在所有基本链上的流量。对于 简单有状态防火墙/iptables,添加
-A INPUT -p ipv6-icmp -j ACCEPT -A OUTPUT -p ipv6-icmp -j ACCEPT -A FORWARD -p ipv6-icmp -j ACCEPT
为其他防火墙前端进行相应调整,并且不要忘记启用 radvd.service
。
隐私扩展
当客户端通过 SLAAC 获取地址时,其 IPv6 地址是从通告的前缀和客户端网络接口的 MAC 地址派生的。这可能会引起隐私问题,因为计算机的 MAC 地址可以很容易地从 IPv6 地址推导出来。为了解决这个问题,开发了IPv6 隐私扩展标准 (RFC 4941)。使用隐私扩展,内核会生成一个临时地址,该地址是从原始自动配置的地址修改而来的。当连接到远程服务器时,首选私有地址,因此原始地址会被隐藏。要启用隐私扩展,请重现以下步骤
添加以下 sysctl 参数
/etc/sysctl.d/40-ipv6.conf
# Enable IPv6 Privacy Extensions net.ipv6.conf.all.use_tempaddr = 2 net.ipv6.conf.default.use_tempaddr = 2 net.ipv6.conf.nic.use_tempaddr = 2
其中 nic
是您的网络接口卡。您可以使用网络配置#列出网络接口中的说明找到它们的名称。all.use_tempaddr
或 default.use_tempaddr
参数不适用于在执行 sysctl 设置时已存在的网卡。
最迟在重启后,应启用隐私扩展。
dhcpcd
dhcpcd 的默认配置包括选项 slaac private
,它启用“稳定的私有 IPv6 地址而不是基于硬件的地址”,实现 RFC 7217。因此,无需更改任何内容,除非希望比每次系统连接到新网络时更频繁地更改 IPv6 地址。将其设置为 slaac hwaddr
以获得稳定的地址。
NetworkManager
可以在 NetworkManager 中使用 ipv6.ip6-privacy
设置控制 IPv6 隐私扩展的使用,该设置位于 NetworkManager.conf(5) 或连接的配置文件中。如果未全局设置或未按连接设置,NetworkManager 将回退到读取 /proc/sys/net/ipv6/conf/default/use_tempaddr
。
要默认显式启用 IPv6 隐私扩展,请将以下行添加到 NetworkManager.conf(5)
/etc/NetworkManager/conf.d/ip6-privacy.conf
[connection] ipv6.ip6-privacy=2
应用配置并重新连接到所有活动连接。
要控制针对单个 NetworkManager 管理的连接使用 IPv6 隐私扩展,请编辑 /etc/NetworkManager/system-connections/
中所需的连接密钥文件,并在其 [ipv6]
部分附加键值对 ip6-privacy=2
/etc/NetworkManager/system-connections/example_connection.nmconnection
... [ipv6] method=auto ip6-privacy=2 ...
重新加载连接,然后重新连接。
scope global temporary
IPv6 地址似乎永远不会续订(在其 valid_lft
生存期结束时永远不会转移到 deprecated
状态),但需要在较长一段时间内验证此地址确实会更改。systemd-networkd
systemd-networkd 默认不启用 IPv6 隐私扩展。要启用它们,请在每个连接的 .network 文件中的 [Network]
部分中设置 IPv6PrivacyExtensions=yes
,或使用 /etc/systemd/networkd.conf.d/
中的配置文件全局设置。例如
/etc/systemd/networkd.conf.d/ipv6-privacy-extensions.conf
[Network] IPv6PrivacyExtensions=yes
除非 IPv6PrivacyExtensions
选项设置为 kernel
,否则 systemd-networkd 不会遵守 sysctl 设置 net.ipv6.conf.nicN.use_tempaddr
。
IPv6 隐私扩展的其他选项,例如
变量名 | 描述 |
---|---|
net.ipv6.conf.nicN.temp_prefered_lft
|
首选临时地址生存期,以秒为单位。请注意必须使用错误的拼写。 |
net.ipv6.conf.nicN.temp_valid_lft
|
最大临时地址生存期,以秒为单位。 |
但是,这些选项会被遵守。[1]
有关详细信息,请参阅 systemd-networkd 和 systemd.network(5)。
ConnMan
在您的服务文件中使用以下设置
/var/lib/connman/service/settings
IPv6.privacy=preferred
有关详细信息,请参阅 ConnMan。
稳定的私有地址
另一种选择是稳定的私有 IP 地址 (RFC 7217)。这允许 IP 在网络内稳定,而不会暴露接口的 MAC 地址。
为了让内核生成密钥(例如,对于 wlan0
),我们可以设置
# sysctl net.ipv6.conf.wlan0.addr_gen_mode=3
将接口关闭并重新启动,运行 ip addr show dev wlan0
后,您应该会在每个 IPv6 地址旁边看到 stable-privacy
。内核已为此接口生成 128 位密钥以生成 ip 地址,要查看它,请运行 sysctl net.ipv6.conf.wlan0.stable_secret
。我们将持久化此值,因此将以下行添加到 /etc/sysctl.d/40-ipv6.conf
# Enable IPv6 stable privacy mode net.ipv6.conf.wlan0.stable_secret = output_from_previous_command net.ipv6.conf.wlan0.addr_gen_mode = 2
stable-privacy
标志将不会归属于此 IP 地址。NetworkManager
NetworkManager 不遵守上述设置,但 NetworkManager 默认使用稳定的私有地址。[2][3]
systemd-networkd
systemd-networkd 不遵守上述设置。为确保始终使用稳定的私有地址,您可以设置
[IPv6AcceptRA] Token=prefixstable
以上告诉 systemd-networkd 使用从机器 ID 派生的密钥。您还可以自己指定密钥,甚至仅将设置应用于路由器通告消息中出现的特定前缀。有关详细信息,请参阅 systemd.network(5)。
如果需要,您还可以生成稳定的私有链路本地地址
[Network] IPv6LinkLocalAddressGenerationMode=stable-privacy
静态地址
有时,使用静态地址可以提高安全性。例如,如果您的本地路由器使用邻居发现或 radvd (RFC 2461),您的接口将根据其 MAC 地址自动分配地址(使用 IPv6 的无状态自动配置)。这对于安全性来说可能不太理想,因为它允许即使 IP 地址的网络部分发生更改也能够跟踪系统。
要使用 netctl 分配静态 IP 地址,请查看 /etc/netctl/examples/ethernet-static
中的示例配置文件。以下行很重要
... # For IPv6 static address configuration IP6=static Address6=('1234:5678:9abc:def::1/64' '1234:3456::123/96') Routes6=('abcd::1234') Gateway6='1234:0:123::abcd'
DNS=('6666:6666::1' '6666:6666::2')如果您的提供商没有给您 IPv6 DNS,并且您没有运行自己的 DNS 服务器,您可以从 resolv.conf 文章中选择。
IPv6 和 PPPoE
PPPoE 的标准工具 pppd(8) 提供对 PPPoE 上 IPv6 的支持,只要您的 ISP 和您的调制解调器支持它。只需将以下内容添加到 /etc/ppp/options
+ipv6
如果您使用 netctl 进行 PPPoE,那么只需将以下内容添加到您的 netctl 配置中即可
PPPoEIP6=yes
前缀委派 (DHCPv6-PD)
前缀委派是许多 ISP 使用的常见 IPv6 部署技术。这是一种将网络前缀分配给用户站点(即本地网络)的方法。可以将路由器配置为将不同的网络前缀分配给各种子网。ISP 使用 DHCPv6(通常是 /56
或 /64
)分配网络前缀,dhcp 客户端将前缀分配给本地网络。对于简单的双接口网关,它实际上是将 IPv6 前缀从通过连接到 WAN 的接口(或伪接口,例如 ppp)获取的地址分配给连接到本地网络的接口。
DHCPv6 要求客户端接收端口 546 UDP 上的传入连接。对于基于 nftables 的防火墙,可以使用 /etc/nftables.conf
中输入链中的一行进行配置
table inet filter { chain input { udp dport dhcpv6-client accept ... } ... }
使用 dhcpcd
dhcpcd 除了 IPv4 dhcp 支持外,还提供了 DHCPv6 客户端标准的相当完整的实现,其中包括 DHCPv6-PD。如果您使用 dhcpcd
,请编辑 /etc/dhcpcd.conf
。您可能已经在使用 dhcpcd 进行 IPv4,因此只需更新您现有的配置。
duid noipv6rs waitip 6 # Uncomment this line if you are running dhcpcd for IPv6 only. #ipv6only # The following applies to the interface WAN. interface WAN ipv6rs # Assign WAN the iaid 1. iaid 1 # Assign a Normal Address to the interface with iaid 1 (i.e. WAN). ia_na 1 # Delegate a prefix with wan interface iaid 1 (i.e. WAN) and lan interface LAN. ia_pd 1 LAN #ia_pd 1/::/64 LAN/0/64
此配置将从 WAN 接口 (WAN
) 请求前缀,并将其委派给内部接口 (LAN
)。如果发出 /64
范围,您将需要使用注释掉的第二个 ia_pd 指令
。它还将禁用除 WAN 接口 (WAN
) 之外的所有接口上的路由器请求。
使用 WIDE-DHCPv6
WIDE-DHCPv6 是 IPv6 (DHCPv6) 的动态主机配置协议的开源实现,最初由 KAME 项目开发。可以使用 wide-dhcpv6AUR 安装。
如果您使用 wide-dhcpv6,请编辑 /etc/wide-dhcpv6/dhcp6c.conf
# use the interface connected to your WAN interface WAN { send ia-pd 0; }; id-assoc pd 0 { # use the interface connected to your LAN prefix-interface LAN { sla-id 1; sla-len 8; }; };
sla-len
,以便 (WAN 前缀) + (sla-len) = 64
。在本例中,它设置为 /56
前缀 56+8=64。对于 /64
前缀,sla-len
应为 0
。可以使用 dhcp6c@interface.service
systemd 单元文件启动/启用 wide-dhcpv6 客户端,其中 interface
是配置文件中的接口名称,例如,对于接口名称“WAN”,使用 dhcp6c@WAN.service
。
systemd-networkd
配置您的上游 (wan) 和下游 (lan) 接口。这将启用运行 DHCPv6 客户端的接口上的 DHCPv6-PD。委派的前缀通过下游网络上的 IPv6 路由器通告分发。
/etc/systemd/network/wan.network
[Network] # Use 'yes' instead of 'ipv6' for both ipv4 and ipv6. DHCP=ipv6
/etc/systemd/network/lan.network
[Network] IPv6SendRA=yes DHCPv6PrefixDelegation=yes
其他客户端
dhclient 也可以请求前缀,但将该前缀或该前缀的一部分分配给接口必须使用 dhclient 退出脚本来完成。例如:https://github.com/jaymzh/v6-gw-scripts/blob/master/dhclient-ipv6。
NAT64
Wikipedia:NAT64 是 IPv6 过渡机制,其中仅 IPv6 主机能够使用 NAT 与 IPv4 主机通信。
Linux 内核本身不支持 NAT64,但有几个软件包可以添加对 NAT64 的支持。
- Jool — Linux 的 SIIT 和 NAT64
- https://nicmx.github.io/Jool/ || jool-dkmsAUR, jool-toolsAUR
- TAYGA — NAT64 守护进程(未维护)
禁用 IPv4
在 systemd-networkd 中禁用 IPv4
这是 systemd-networkd 中仅 IPv6 接口的示例配置。
/etc/systemd/network/lan.network
[Match] Name=eno0 [Link] RequiredForOnline=routable [Network] # Enable IPv6 only DHCP=ipv6 # Enable SLAAC IPv6AcceptRA=true
禁用 IPv6
对于某些 ISP[4][5],IPv6 流量比 IPv4 流量慢:如果您可以确定您受到此类问题的影响,禁用 IPv6 可能会提高您的网络速度。
不应盲目执行此操作:对于大多数用户来说,仅 IPv4 网络会在 运营商级 NAT 之后降低性能,并妨碍他们使用 P2P 或 WebRTC 应用程序(例如某些游戏)。相反,配置优先使用 IPv4 而不是 IPv6 是两全其美的方法。
禁用功能
将 ipv6.disable=1
添加到内核行会禁用整个 IPv6 协议栈,如果您遇到问题,这很可能是您想要的。有关更多信息,请参阅 内核参数。
或者,添加 ipv6.disable_ipv6=1
将保持 IPv6 协议栈的功能,但不会为您的任何网络设备分配 IPv6 地址。
sysctl
可以通过将以下 sysctl 配置添加到 /etc/sysctl.d/40-ipv6.conf
来禁用所有或特定网络接口的 IPv6 协议栈
# Disable IPv6 net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.nic0.disable_ipv6 = 1 ... net.ipv6.conf.nicN.disable_ipv6 = 1
但是,只有在启动后重启 systemd-sysctl.service
后,此操作才有效,因为 systemd-sysctl.service
在网络接口完全配置之前启动。在启动时,只能设置 lo
、default
和 all
的配置,因为它们是 IPv6 协议栈的内部组成部分。
# sysctl -w net.ipv6.conf.all.disable_ipv6=1
会删除所有网络接口上分配的 IPv6 地址及其路由,并且可以撤消。- 大多数网络管理器(netplan、systemd-networkd、NetworkManager 等)根据自己的配置设置已配置网络接口的 IPv6 协议栈状态,而忽略
net.ipv6.conf.default.disable_ipv6
中设置的配置。 - 如果通过 sysctl 禁用 IPv6,您应该注释掉
/etc/hosts
中的 IPv6 主机。否则,可能会出现一些连接错误,因为主机被解析为其无法访问的 IPv6 地址。
systemd 单元
如果希望在启动时禁用所有网络接口的 IPv6 协议栈,并且能够稍后轻松启用 IPv6,则需要一个在网络管理器之后运行的 systemd 单元。
用于 systemd-networkd 的单元如下所示
/etc/systemd/system/enforce_disable_ipv6.service
[Unit] Description=enforce default disable_ipv6 AssertPathExists=/proc/sys/net/ipv6/conf/all/disable_ipv6 AssertPathExists=/proc/sys/net/ipv6/conf/default/disable_ipv6 After=systemd-networkd.service PartOf=systemd-networkd.service [Service] Type=oneshot ExecStart=-/usr/bin/cp --no-preserve=all -T /proc/sys/net/ipv6/conf/default/disable_ipv6 /proc/sys/net/ipv6/conf/all/disable_ipv6 [Install] WantedBy=systemd-networkd.service
启用此单元后,任何 systemd-networkd 的启动或重启都将强制所有网络接口上的 IPv6 协议栈状态的 default
值。
default
值可以在启动时使用 #sysctl 设置。
要为其他网络管理器调整此单元,需要将所有出现的 systemd-networkd.service
替换为您的网络管理器的配置单元。
其他程序
禁用内核中的 IPv6 功能并不能阻止其他程序尝试使用 IPv6。在大多数情况下,这是完全无害的,但如果您发现自己遇到该程序的问题,您应该查阅该程序的手册页,以了解禁用该功能的方法。
dhcpcd
dhcpcd 将继续无害地尝试执行 IPv6 路由器请求。要禁用此功能,如 dhcpcd.conf(5) 手册页 中所述,将以下内容添加到 /etc/dhcpcd.conf
noipv6rs noipv6
NetworkManager
要在 NetworkManager 中禁用 IPv6,请右键单击网络状态图标,然后选择编辑连接 > 有线 > 网络名称 > 编辑 > IPv6 设置 > 方法 > 忽略/禁用。然后单击保存。
这也可以通过以下方式完成
# nmcli connection modify ConnectionName ipv6.method "disabled"
然后重启网络连接
# nmcli connection up ConnectionName
要确认设置已应用,请使用 ip address show
并检查是否未显示 inet6 条目。或者,/proc/sys/net/ipv6/conf/interface/disable_ipv6
应具有值 1。
ntpd
按照 systemd#Drop-in 文件 中的建议,编辑 ntpd.service
以定义 systemd 如何启动它。
这将创建一个 drop-in 代码段,该代码段将代替默认的 ntpd.service
运行。-4
标志阻止 ntp 守护程序使用 IPv6。将以下内容放入 drop-in 代码段
[Service] ExecStart= ExecStart=/usr/bin/ntpd -4 -g -u ntp:ntp
它首先清除之前的 ExecStart
,然后将其替换为包含 -4
标志的代码段。
GnuPG
在 dirmngr 的配置文件中禁用 IPv6
~/.gnupg/dirmngr.conf
disable-ipv6
重启 dirmngr.service
用户单元。
sshd
通过将以下内容添加到 sshd_config
来确保 sshd 正在使用 IPv4
/etc/ssh/sshd_config
AddressFamily inet
并重启 sshd.service
。
systemd-timesyncd
有时,即使已禁用 IPv6,systemd-timesyncd 也会尝试查询 IPv6 时间服务器。这可能会导致系统时钟未更新,并且日志显示类似于以下的错误
systemd-timesyncd[336]: Failed to set up connection socket: Address family not supported by protocol
systemd-timesyncd
的单元状态将在其状态条目中显示尝试使用 IPv6 地址连接,类似于
Status: "Connecting to time server [2001:19f0:8001:afd:5400:1ff:fe9d:cba]:123 (2.pool.ntp.org)"
根据 FS#59806,只有 “2.” ntp.org 池提供 IPv6 服务。因此,为防止这种情况,请从 /etc/systemd/timesyncd.conf
文件中的 NTP 和 FallbackNTP 条目中删除 2.arch.pool.ntp.org
和 2.pool.ntp.org
。
systemd-networkd
networkd 支持在每个接口的基础上禁用 IPv6。当网络单元的 [Network]
部分具有 LinkLocalAddressing=ipv4
或 LinkLocalAddressing=no
时,networkd 将不会尝试在匹配的接口上配置 IPv6。
但请注意,即使使用上述选项,如果未全局禁用 IPv6,networkd 仍然会期望接收路由器通告。如果接口未接收到 IPv6 流量(例如,由于 sysctl 或 ip6tables 设置),它将保持在配置状态,并可能导致等待网络完全配置的服务超时。为避免这种情况,还应在 [Network]
部分中设置 IPv6AcceptRA=no
选项。
优先使用 IPv4 而不是 IPv6
取消注释 /etc/gai.conf
中的以下行
# # For sites which prefer IPv4 connections change the last line to # precedence ::ffff:0:0/96 100
参见
- IPv6 — kernel.org 文档
- IPv6 临时地址 — 关于临时地址和隐私扩展的摘要
- IPv6 前缀 — 前缀类型摘要
- net.ipv6 选项 — 内核参数文档