IPv6

出自 ArchWiki
(重定向自 禁用 IPv6

在 Arch Linux 中,IPv6 默认启用。

tldp Linux+IPv6-HOWTO 文章比较旧,维护也较少。但它试图涵盖本文中提到的许多主题,从基础知识开始,并以较慢的节奏推进。它还有许多命令行示例。初学者可能希望在阅读这篇 wiki 文章之前阅读或浏览一下。

邻居发现

Ping 组播地址 ff02::1 会导致链路本地范围内的所有主机响应。必须指定接口

$ ping ff02::1%eth0

之后,您可以使用以下命令获取本地网络中所有邻居的列表

$ ip -6 neigh

Ping 组播地址 ff02::2 只会使路由器响应。

如果添加选项 -I 您的全局-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 分发给网络客户端,我们将需要使用通告守护程序。此任务的标准工具是 radvdradvd 的配置相当简单。编辑 /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 地址派生的。这可能会引起隐私问题,因为 IPv6 地址可以很容易地推导出计算机的 MAC 地址。为了解决这个问题,开发了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_tempaddrdefault.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] 部分或全局配置文件的 /etc/systemd/networkd.conf.d/ 中设置 IPv6PrivacyExtensions=yes。例如:

/etc/systemd/networkd.conf.d/ipv6-privacy-extensions.conf
[Network]
IPv6PrivacyExtensions=yes

systemd-networkd 不遵守 sysctl 设置 net.ipv6.conf.nicN.use_tempaddr,除非 IPv6PrivacyExtensions 选项设置为 kernel

IPv6 隐私扩展的其他选项,如

变量名 描述
net.ipv6.conf.nicN.temp_prefered_lft 首选临时地址生存期(秒)。请注意必须使用错误的拼写。
net.ipv6.conf.nicN.temp_valid_lft 最大临时地址生存期(秒)。

但是,这些选项会被遵守。[1]

有关详细信息,请参阅 systemd-networkdsystemd.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
注意: 如果您正在使用 dhcpcd 获取 IPv6 地址,则 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'
注意: 如果您仅连接 IPv6,则需要确定您的 IPv6 DNS 服务器。例如
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

除了 IPv4 dhcp 支持外,dhcpcd 还提供了 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) 之外的所有接口上的路由器请求。

提示: 另请阅读 dhcpcd(8)dhcpcd.conf(5)

使用 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-prefix) + (sla-len) = 64。在本例中,它设置为 /56 前缀 56+8=64。对于 /64 前缀,sla-len 应为 0

可以使用 dhcp6c@interface.service systemd 单元文件启动/启用 wide-dhcpv6 客户端,其中 interface 是配置文件中的接口名称,例如,对于接口名称“WAN”,请使用 dhcp6c@WAN.service

提示: 阅读 dhcp6c(8)dhcp6c.conf(5) 以获取更多信息。

systemd-networkd

配置您的上游 (wan) 和下游 (lan) 接口。这将启用 DHCPv6-PD 在运行 DHCPv6 客户端的接口上。委派的前缀通过下游网络上的 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
提示: 另请阅读 systemd.network(5) § 示例

其他客户端

dhclient 也可以请求前缀,但必须使用 dhclient 退出脚本将该前缀或该前缀的一部分分配给接口。例如:https://github.com/jaymzh/v6-gw-scripts/blob/master/dhclient-ipv6

NAT64

维基百科:NAT64 是一种 IPv6 过渡机制,其中仅 IPv6 主机能够使用 NAT 与 IPv4 主机通信。

Linux 内核本身不支持 NAT64,但有几个软件包可以添加对 NAT64 的支持。

  • Jool — Linux 的 SIIT 和 NAT64
https://nicmx.github.io/Jool/ || jool-dkmsAUR, jool-toolsAUR
  • TAYGA — NAT64 守护程序(未维护)
http://www.litech.org/tayga/ || taygaAUR

禁用 IPv4

本文或章节需要扩充。

原因: 添加禁用旧版 IP 的说明,尤其是在网络具有 NAT64 和 DNS64 的情况下,我们不需要维护双栈,CGN 的实施也降低了 ipv4 的性能和可用性(例如,如今,在家托管 nextcloud 通常只能使用 ipv6 和 dynv6.com 或 namecheap dyndns 记录等服务来实现。这是因为没有可用的公共 ipv4,甚至 CPE 路由器也没有)(在 Talk:IPv6 中讨论)

在 systemd-networkd 中禁用 IPv4

本文或章节的事实准确性存在争议。

原因: 这不是“在 systemd-networkd 中禁用 IPv4”,它只是启用了仅 IPv6 的 DHCP 客户端。(在 Talk:IPv6 中讨论)

这是 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

注意: Arch 内核直接内置了 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 在网络接口完全配置之前启动。在启动时,只能设置 lodefaultall 的配置,因为它们是 IPv6 堆栈的内部组成部分。

提示: 如果 IPv6 堆栈未完全禁用,也可以在运行时禁用接口的 IPv6 以测试配置更改。执行 # sysctl -w net.ipv6.conf.all.disable_ipv6=1 会删除所有网络接口上分配的 IPv6 地址及其路由,并且可以撤消。
注意
  • 大多数网络管理器(netplansystemd-networkdNetworkManager 等)根据自己的配置设置已配置网络接口的 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.org2.pool.ntp.org

systemd-networkd

networkd 支持在每个接口上禁用 IPv6。当网络单元的 [Network] 部分具有 LinkLocalAddressing=ipv4LinkLocalAddressing=no 时,networkd 将不会尝试在匹配的接口上配置 IPv6。

但请注意,即使使用上述选项,如果未全局禁用 IPv6,networkd 仍会期望接收路由器通告。如果接口未接收到 IPv6 流量(例如,由于 sysctlip6tables 设置),它将保持在配置状态,并可能导致等待网络完全配置的服务超时。为避免这种情况,还应在 [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

参见