IPv6
在 Arch Linux 中,IPv6 是默認開啟的。
tldp Linux+IPv6-HOWTO 這篇文章比較舊, 且缺乏維護。不過其涵蓋了本文所提及的許多主題,從基礎的東西講起並且循序漸進到高級配置。而且還有很多命令的例子。初學者可以先讀一讀這篇文章再接着閱讀本文。
鄰居發現(Neighbor discovery,ND)[編輯 | 編輯原始碼]
使用 Ping 命令來 ping ff02::1
這個多播地址,會得到本地鏈路層的所有主機的響應。需要手動指定接口(%eth0
)
$ ping ff02::1%eth0
Ping 完之後,您可以用如下命令來獲取本地子網中的所有主機。
$ 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。只要您的網絡配置好了「無狀態地址自動配置」(Stateless address autoconfiguration,簡稱SLAAC),您的設備就會自動根據路由器廣播(Router Advertisement,RA)的前綴為自己配置一個地址。既不需要進一步配置,也不需要專門的軟件(如DHCP客戶端)
客戶端配置[編輯 | 編輯原始碼]
如果您正在使用 netctl,您要做的只是往接口配置文件裡加上這麼一行:
IP6=stateless
如果您使用的是 NetworkManager,那麼只要網絡內有路由器廣播,它就會自動配置上 IPv6 地址。
不過需要注意的是,SLAAC只有在網絡允許 IPv6 ICMP 包通過的時候才能工作。所以你需要在客戶端防火牆上允許 ipv6-icmp
類型的數據包傳入。如果您用的是 Simple stateful firewall/iptables,加上下面這行就可以了:
-A INPUT -p ipv6-icmp -j ACCEPT
如果您用的是其他防火牆,請參考對應的文檔來放行 ipv6-icmp
數據包。
如果你選擇的網絡管理方案不支持通過SLAAC配置DNS(比如netctl),那麼你可以考慮用ndisc6包包裡的rdnssd(8)命令來配置DNS。
路由器(網關)配置[編輯 | 編輯原始碼]
要正確給網絡內的客戶端分配 IPv6,我們要用到一個廣播守護進程,一般是radvd包。其配置過程其實相當簡單。參考下面的配置來編輯 /etc/radvd.conf
文件。
# 把LAN替换为你实际的局域网接口 interface LAN { AdvSendAdvert on; MinRtrAdvInterval 3; MaxRtrAdvInterval 10; prefix ::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; }; };
以上配置會讓客戶端自己從 /64 地址段中選擇地址來使用。請注意如果配置了 prefix ::/64
,RADVD會向局域網廣播那個接口上的所有可用的前綴。如果您想要廣播指定的前綴,請手動指定,比如 prefix 2001:DB8::/64
。prefix
節可以根據需要多次重複來廣播多個不同前綴。
您可以通過 RDNSS 功能向客戶端廣播 DNS,以 Google DNS 為例,配置如下:
RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 { };
網關必須在所有鏈上允許 ipv6-icmp
類型數據包通過。以 Simple stateful firewall/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 SLAAC 地址反推客戶端 MAC。為了解決這個問題,RFC 4941 中提出了 IPv6 私隱拓展 標準。啟用私隱擴展後,內核會生成一個 臨時 地址,這個地址是原來的 SLAAC 地址經過二次計算得出的隨機地址。當主動連接到遠程伺服器時,會優先選擇使用私有地址,從而幫助隱藏原始的 SLAAC地址。啟用私隱擴展的步驟如下:
向 /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.nic0.use_tempaddr = 2 ... net.ipv6.conf.nicN.use_tempaddr = 2
上面的 nic0
到 nicN
是你的網絡接口。你可以參考 網絡配置#Listing network interfaces 來列出你的設備上的接口。 all.use_tempaddr
或者 default.use_tempaddr
參數對於執行 sysctl 設置時已經存在的接口無效,也就是說不會即時生效。
不過當您重啟設備之後,私隱拓展應該就會生效了。
dhcpcd[編輯 | 編輯原始碼]
dhcpcd 的默認配置已經包括了 slaac private
,這會啟用 RFC 7217 中定義的「穩定的私有IPv6地址而不是基於硬件的地址」功能。因此,您無需修改任何設置,除非您希望更頻繁地獲得新的隨機地址,而不僅在連接到新網絡的時候改變IPv6地址。您還可以設置 slaac hwaddr
來使用普通的基於 MAC 生成的固定 IPv6 後綴。
NetworkManager[編輯 | 編輯原始碼]
您可以修改 NetworkManager 的全局配置文件 NetworkManager.conf(5) 或連接配置中的 ipv6.ip6-privacy
選項,來決定是否啟用 IPv6 私隱拓展。如果全局配置和連接配置都沒有設置該選項,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/
目錄下的 keyfile,並把 ip6-privacy=2
添加到 [ipv6]
一節下方,示例如下:
/etc/NetworkManager/system-connections/example_connection.nmconnection
... [ipv6] method=auto ip6-privacy=2 ...
最後,重新加載連接配置並再次連接。
scope global temporary
IPv6 地址看上去永遠不會被更新(在其 valid_lft
所顯示的生命周期內,該地址永遠不會變為 deprecated
狀態),但經過較長時間的驗證,這個地址 確實 會發生變化。systemd-networkd[編輯 | 編輯原始碼]
systemd-networkd 同樣不遵守 /etc/sysctl.d/40-ipv6.conf
中配置的 net.ipv6.conf.xxx.use_tempaddr
內核參數,除非您在 .network 文件中指定 IPv6PrivacyExtensions
選項的值為 kernel
。
不過 systemd-networkd 遵守其他 IPv6 私隱拓展的內核參數,比如:
net.ipv6.conf.xxx.temp_prefered_lft net.ipv6.conf.xxx.temp_valid_lft
temp_prefered_lft
才是正確的變量名,「preferred」應該是拼錯了請參考 systemd-networkd 和 systemd.network(5) 以了解更多信息。
ConnMan[編輯 | 編輯原始碼]
在服務文件(比如 /var/lib/connman/service/settings
)中設置:
IPv6.privacy=preferred
請參考 ConnMan 以了解更多信息。
穩定的私隱地址[編輯 | 編輯原始碼]
另外一個選擇,是使用 RFC 7217 中定義的穩定私隱地址。它可以在不暴露 MAC 地址的情況下固定住網絡中的 IPv6 地址。
Another option is a stable private IP address (RFC 7217). This allows for IPs that are stable within a network without exposing the MAC address of the interface.
以 wlan0
接口為例,使用以下命令來讓內核為其生成一個密鑰:
# sysctl net.ipv6.conf.wlan0.addr_gen_mode=3
把接口關閉再啟用,然後運行 ip addr show dev wlan0
,您應該會看到每個 IPv6 地址旁邊會有 stable-privacy
標誌。內核已經為該接口生成了一個 128 位的密鑰用於產生穩定 IPv6 地址,您可以運行 sysctl net.ipv6.conf.wlan0.stable_secret
來查看這一密鑰。我們需要固定這個密鑰以讓他每次重啟後都獲得同樣的地址,所以請在 /etc/sysctl.d/40-ipv6.conf
中進行如下配置:
# Enable IPv6 stable privacy mode net.ipv6.conf.wlan0.stable_secret = 刚才查看的密钥 net.ipv6.conf.wlan0.addr_gen_mode = 2
stable-privacy
標誌 不會 被應用到由 dhcpcd 獲得的 IPv6 地址上NetworkManager[編輯 | 編輯原始碼]
NetworkManager 不遵守以上設置,但是它默認已經啟用了穩定私隱地址。[1][2]
靜態地址[編輯 | 編輯原始碼]
有些情況下使用靜態地址可以增強安全性。使用SLAAC分配動態地址時,你的計算機的地址會由其網卡MAC推算出,這不利於安全,因為即使地址的網絡號改變,你的電腦依然可以被追蹤到。
要想用netctl分配一個靜態地址,可以參照/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')如果你的ISP沒有告訴你IPv6的DNS伺服器地址,並且你也沒有自己的伺服器,你可以從resolv.conf這篇文章中選一個。
IPv6與PPPoE[編輯 | 編輯原始碼]
PPPoE的軟件包pppd
提供了對PPPoE之上的IPv6的支持(前提是你的ISP和調製解調器支持)。只需要將如下內容加入/etc/ppp/pppoe.conf
:
+ipv6
如果你使用netctl,那麼就向你的netctl配置文件加入如下內容:
PPPoEIP6=yes
地址委派 (DHCPv6-PD)[編輯 | 編輯原始碼]
地址委派是一種常見的 IPv6 部署方式,被許多 ISP 所採用。具體的做法是將一個地址前綴分配給用戶(局域網),即路由器配置為將不同的前綴分配給不同的子網;ISP 通過 DHCPv6 將地址前綴(通常是/56
或/64
)分發出去,DHCP 客戶端再將前綴分配給局域網。對於一個擁有兩個網卡的簡單網關來說,它的工作就是將從 WAN 口(或虛擬接口,比如ppp)獲取的前綴分配給局域網。
DHCPv6 客戶端需要在 UDP 546 接口上接受傳入的連接。對於基於 nftables 的防火牆,可以編輯 /etc/nftables.conf
:
table inet filter { chain input { udp dport dhcpv6-client accept ... } ... }
使用dhcpcd[編輯 | 編輯原始碼]
Dhcpcd在 IPv4 之外也提供了一個完整的支持 DHCPv6-PD 的客戶端。如果你使用 dhcpcd
,需要修改 /etc/dhcpcd.conf
。你可能已經在用dhcpcd來配置 IPv4,,所以只需要對現有的配置進行小幅修改:
duid noipv6rs waitip 6 # Uncomment this line if you are running dhcpcd for IPv6 only. #ipv6only # use the interface connected to WAN interface WAN ipv6rs iaid 1 # use the interface connected to your LAN ia_pd 1 LAN #ia_pd 1/::/64 LAN/0/64
這種配置下,客戶端會從WAN
接口獲取一個前綴,分配給LAN
接口。
如果ISP分配的是/64
的地址,你需要用第二個ia_pd
選項。
這也會禁用除WAN
接口之外的所有路由器請求。
dhcpcd(8)
與dhcpcd.conf(5)
獲得更多信息。使用WIDE-DHCPv6[編輯 | 編輯原始碼]
WIDE-DHCPv6是原本由KAME計劃開發的DHCPv6開源實現。它在AUR中: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
。要啟用或運行wide-dhcpv6,使用如下命令。把WAN
改為連接到ISP的網卡:
# systemctl enable/start dhcp6c@WAN.service
dhcp6c(8)
與dhcp6c.conf(5)
獲取更多信息。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 地址的主機通過使用 NAT 來和 IPv4 主機通信的過渡機制。
Linux 內核並不原生支持 NAT64,但您可以使用以下這些軟件包來添加 NAT64 支持:
- Jool — SIIT and NAT64 for Linux
- https://nicmx.github.io/Jool/ || jool-dkmsAUR, jool-toolsAUR
- TAYGA — NAT64 daemon (unmaintained)
禁用 IPv6[編輯 | 編輯原始碼]
關閉 IPv6 功能[編輯 | 編輯原始碼]
如果您遇到一些問題,可以試着向內核參數加入 ipv6.disable=1
,來完全關閉 IPv6 功能, 參考 內核參數 來了解更多信息.
此外,只加入ipv6.disable_ipv6=1
內核參數可以保留IPv6功能,但不會向網卡分配IPv6地址。
也可以通過向/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
單元來應用上述設置。
注意你必須在這裏清楚地列出所有不需要分配IPv6地址的網卡,僅僅設置all.disable_ipv6
並不會立刻對已經連接的網卡起作用。
/etc/hosts
中刪除所有的IPv6主機,否則當你使用主機名連接它們的時候會解析到不通的IPv6地址其他應用程式[編輯 | 編輯原始碼]
在內核中關閉 IPv6 功能不會阻止應用程式嘗試使用 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
看看還有沒有顯示 IPv6 地址(inet6)。或者檢查 /proc/sys/net/ipv6/conf/interface/disable_ipv6
這個內核參數,其值應該為 1。
ntpd[編輯 | 編輯原始碼]
依照Systemd#Drop-in files,修改ntpd.service
的啟動方式。
# systemctl edit ntpd.service
這樣會產生一個drop-in snippet,替代原有的ntpd.service
來加載ntpd。參數-4
關閉了ntpd的IPv6支持。向drop-in snippet中加入如下內容:
[Service] ExecStart= ExecStart=/usr/bin/ntpd -4 -g -u ntp:ntp
第一行清除了之前的ExecStart
配置,接下來的一行將該配置設置為帶有-4
參數的ntpd。
GnuPG[編輯 | 編輯原始碼]
在 dirmngr 配置文件中設置如下參數:
~/.gnupg/dirmngr.conf
disable-ipv6
然後重啟 dirmngr.service
服務.
sshd[編輯 | 編輯原始碼]
修改 sshd_config
來讓 sshd 只使用 IPv4:
/etc/ssh/sshd_config
AddressFamily inet
然後重啟 sshd.service
服務
systemd-timesyncd[編輯 | 編輯原始碼]
有時 Systemd-timesyncd 會嘗試查詢IPv6時間伺服器,即使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。所以將 2.arch.pool.ntp.org
和 2.pool.ntp.org
從配置文件 /etc/systemd/timesyncd.conf
的 NTP 和 FallbackNTP 部分中刪去即可避免這一現象。
systemd-networkd[編輯 | 編輯原始碼]
networkd 支持按接口禁用IPv6。當網絡單元的 [Network]
部分的 LinkLocalAddressing=ipv4
或 LinkLocalAddressing=no
時,networkd不會嘗試在匹配的接口上配置IPv6。
然而,請注意,即使在使用上述選項時,如果 IPv6 未被全局禁用,networkd 仍會收到路由器通告。如果接口未接收到IPv6流量(例如,由於 sysctl 或 ip6tables 設置),它將保持在配置狀態,並可能導致等待網絡完全配置的服務超時。為了避免這種情況,還應在 [Network]
部分設置 IPv6AcceptRA=no
選項。
參見[編輯 | 編輯原始碼]
- IPv6 — kernel.org documentation
- IPv6 temporary addresses — a summary about temporary addresses and privacy extensions
- IPv6 prefixes — a summary of prefix types
- net.ipv6 options — documentation of kernel parameters