網絡配置

出自 Arch Linux 中文维基

這篇文章或章節的翻譯不反映原文。

原因:本文久未同步,內容與英語原文相比,已有較大差異。(在 Talk:網絡配置# 中討論)

本頁解釋了如何在 OSI 第三層及之上配置網絡連接。有部分內容在網絡配置/以太網網絡配置/無線網絡配置兩個頁面中。

提示:建議參閱systemd-networkd

檢查連接[編輯 | 編輯原始碼]

若要排查網絡連接問題,請先確保你滿足了以下要求。

  1. 你的網絡接口可見並已啟用。否則請檢查設備驅動-請查閱 Network configuration/Ethernet#Device driverWireless network configuration#設備驅動[損壞的鏈接:無效的章節] 頁面。
  2. 你已連接到網絡。網線已接好或者已經連接到無線局域網
  3. 你的網絡接口擁有一個IP 地址
  4. 你的路由表設置正確。
  5. 你可以 ping 通一個本地 IP 地址(例如你的默認網關)。
  6. 你可以 ping 通一個公網 IP 地址(例如 9.9.9.9 ,即 Quad9 的 DNS 服務器)。
  7. 檢查是否能解析域名(例如 archlinux.org)。

Ping[編輯 | 編輯原始碼]

ping 用於測試你是否可連接到某個主機, 用 Ctrl+c 停止測試。

$ ping www.example.com
PING www.example.com (93.184.216.34): 56(84) data bytes
64 bytes from 93.184.216.34: icmp_seq=0 ttl=56 time=11.632 ms
64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=11.726 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=10.683 ms
...

如上所示,Ping 命令對每個收到的回應都會顯示一行信息。詳細的解釋請閱讀 ping(8) 手冊。注意,計算機可以配置為不響應 ICMP 回應請求。[1]

如果沒有收到回應,原因可能與默認網關配置或者網絡接入服務商(ISP)有關。可以運行 traceroute 以進一步診斷到對端主機的路由。

網絡管理[編輯 | 編輯原始碼]

通過以下步驟來設置網絡鏈接:

  1. 確保網絡接口已連接並已開啟。
  2. 連接到網絡。網線已接好或者已經連接到無線局域網
  3. 配置網絡連接:
注意: 安裝鏡像使用 systemd-resolvedsystemd-networkd[2], WLANWWAN網絡配置 DHCP 客戶端。

網絡工具[編輯 | 編輯原始碼]

Arch Linux 已經棄用了 net-tools 轉而使用 iproute2[3]

已棄用的命令 替換命令
arp ip neighbor
ifconfig ip address, ip link
netstat ss
route ip route

想要更多更完整的總結,請參閱這篇文章

iproute2[編輯 | 編輯原始碼]

iproute2base 元包的依賴,提供 ip(8) 命令行接口,用於管理網絡接口IP 地址路由表。注意使用 ip 進行的配置會在重啟後丟失。要進行永久配置,可以使用網絡管理器或通過腳本和 systemd 單元使 ip 命令自動化。同時需要注意的是 ip 命令通常能夠縮寫,為了清楚起見,本文對其進行了詳細說明。

網絡接口[編輯 | 編輯原始碼]

默認情況下, udev 使用可預測的網絡接口名稱分配給你的網絡接口,該名稱以 en (有線/以太網) ,wl (無線/WLAN) 或 ww (WWAN)開頭 。參見 systemd.net-naming-scheme(7)

提示:要改變接口名稱,請參閱 #更改接口名稱#改回傳統接口名稱

列出網絡接口[編輯 | 編輯原始碼]

有線和無線接口名稱都可以通過 ls /sys/class/netip link 找到。要注意的是 loLoop 設備,不被用於建立網絡連接。

同樣,也可以用 iw dev 來檢索無線設備的名稱。可以參閱無線網#獲取有用信息[損壞的鏈接:無效的章節]

如果未列出您的網絡接口,請確保已成功加載設備驅動。參閱以太網#設備驅動無線網#設備驅動[損壞的鏈接:無效的章節]

啟用和禁用網絡接口[編輯 | 編輯原始碼]

可以使用 ip link set interface up|down 來啟用/禁用網絡接口,參閱 ip-link(8)

要想檢查接口 enp2s0 的狀態:

$ ip link show dev enp2s0
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT qlen 1000
...

<BROADCAST,MULTICAST,UP,LOWER_UP> 中的 UP 表示接口已經啟動,而非表示稍後的 state DOWN

注意: 如果您的默認路由是通過接口 enp2s0 進行的,則將其刪除也會刪除該路由,而恢復備份將不會自動重新建立默認路由。參閱 #路由表 以重新建立它。

靜態還是動態 IP 地址?[編輯 | 編輯原始碼]

如果你在使用 WiFi 或路由器,你很可能會使用動態 IP 地址。你的計算機應該被配置為使用由 WiFi 或路由器分配的 IP 地址。如果你處於家庭環境且電腦連接到網絡接入服務商提供的調製解調器,比如一個線纜調製解調器,那也會使用一個動態 IP 地址。動態 IP 地址會在每次開機時改變。在工作環境中,你可能具有靜態 IP 地址或動態 IP 地址。在家裡,你可以將路由器配置為始終為計算機分配相同的 IP 地址,在這種情況下,你將使用靜態 IP 地址。使用動態 IP 地址時,需要使用 DHCP 以便用正確的 IP 地址設置網絡接口。除了配置 IP 地址外,DHCP 還可以配置路由(如何從你的位置到達任意網絡中你要訪問的的位置)以及域名服務器,域名服務器會轉換主機名(例如 google.com)到 IP 地址(帶點號的數字)。

靜態 IP 地址[編輯 | 編輯原始碼]

可以通過絕大多數的網絡管理器dhcpcd 來配置靜態 IP 地址。

要手動配置靜態 IP 地址,請按照 #IP 地址中的說明添加 IP 地址,設置路由表配置 DNS 服務器

IP 地址[編輯 | 編輯原始碼]

通過 ip-address(8) 來管理 IP 地址

列出 IP 地址:

$ ip address show

將 IP 地址添加到接口:

# ip address add address/prefix_len broadcast + dev interface
注意:
注意: 要確保手動分配的 IP 地址與 DHCP 分配的 IP 地址不衝突。

將 IP 地址從接口中刪除:

# ip address del address/prefix_len dev interface

刪除所有符合條件的地址,例如某個特定接口的地址:

# ip address flush dev interface
提示:可通過 ipcalc (ipcalc) 計算 IP 地址。

路由表[編輯 | 編輯原始碼]

路由表被用於確定是否可以直接訪問某個 IP 地址或該使用哪個網關(路由器)。如果別的路由與這個 IP 地址匹配,將使用默認網關

通過 ip-route(8) 來管理路由表。

應在 PREFIX 處使用 CIDR 表示法,或填入 default 表示默認網關。

列出 IPv4 路由:

$ ip route show

列出 IPv6 路由:

$ ip -6 route

添加路由:

# ip route add PREFIX via address dev interface

刪除路由:

# ip route del PREFIX via address dev interface

DHCP[編輯 | 編輯原始碼]

動態主機配置協議(DHCP) 服務器為客戶端提供動態 IP 地址,子網掩碼,默認網關 IP 地址,有時還可以提供域名服務器。

要使用 DHCP ,需要網絡中有 DHCP 服務器和 DHCP 客戶端:

客戶端 軟件包 Archiso 備註 Systemd 單元
dhcpcd dhcpcd DHCP, DHCPv6, ZeroConf, static IP dhcpcd.service, dhcpcd@interface.service
ISC dhclient dhclient DHCP, DHCPv6, BOOTP, static IP dhclient@interface.service
注意:
  • ISC 從 2022 年初開始已經停止 ISC DHCP 客戶端開發,程序已經不再維護,請不要在生產系統中使用。
  • 不能同時運行兩個 DHCP 客戶端。
  • 除了直接使用獨立的 DHCP 客戶端,還可以使用具有內置 DHCP 客戶端的網絡管理器
  • 另外,iwd 提供了內置的 DHCP 客戶端,可以通過某些配置來使用它:iwd#啟用內置網絡配置
提示:
  • 可以通過 dhcping 檢查一個 DHCP 服務器是否在運行。
  • 在等待分配 IP 時,可以運行 watch -n 1 ping -c 1 archlinux.org 之類的命令來自動確認網絡是否配置好。

服務器[編輯 | 編輯原始碼]

服務器 軟件包 IPv4 IPv6 GUI 接口 後端存儲 備註
dhcpd dhcp Glass-ISC-DHCP ? 文件
dnsmasq dnsmasq ? 文件 還可運行 DNS,PXE 和 TFTP 服務
Kea kea Stork REST,RADIUS 和 NETCONF 文件,MySQL,PostgreSQL 和 Cassandra 還可運行 DNS 服務

網絡管理器[編輯 | 編輯原始碼]

網絡管理器可以在網絡配置文件中管理網絡連接設置,以便切換網絡。

注意: 有許多可選的方案,但他們都相互排斥,因此不要同時運行兩個守護程序
網絡管理器 GUI Archiso [4] CLI 工具 點對點協議 支持
(例如 3G 調製解調器)
DHCP 客戶端 Systemd 單元
ConnMan 8 種,非官方 connmanctl(1) 是(通過 ofonoAUR 內置 connman.service
netctl 2 種,非官方 netctl(1), wifi-menu dhcpcddhclient netctl-ifplugd@interface.service, netctl-auto@interface.service
NetworkManager nmcli(1), nmtui(1) 內置或 dhclient NetworkManager.service
systemd-networkd 是 (base) networkctl(1) 內置 systemd-networkd.service, systemd-resolved.service

設置計算機名[編輯 | 編輯原始碼]

主機名是一個網絡中唯一標識一台機器的名稱。主機名通過文件 /etc/hostname 進行配置,參閱 hostname(5)hostname(7) 獲取詳細介紹。/etc/hostname 可以包含系統使用的域名(如果有)。要設置主機名,請編輯 /etc/hostname 使之包含單獨一行 myhostname

/etc/hostname
myhostname
提示:有關選取一個主機名的建議,參閱 RFC 1178

也可以使用 hostnamectl(1)

# hostnamectl set-hostname myhostname

要臨時設置主機名(直到下次重啟為止),使用 inetutils 中的 hostname(1) 命令:

# hostname myhostname

要設置「美觀」的主機名和其它機器元數據,請參考 machine-info(5)

局域網主機名解析[編輯 | 編輯原始碼]

要想使用主機名在你的局域網上訪問你的機器,你可以使用下列方法:

  • 編輯你局域網上所有設備的 /etc/hosts,參見 hosts(5)
  • 設立一個 DNS 服務器來解析你的主機名,並讓局域網中的設備都使用這個 DNS 服務器(比如,通過 #DHCP
  • 或者最簡單的方式:使用 Zero-configuration networking 服務:
    • 通過微軟的 NetBIOS 進行主機名解析。在 Linux 上由 Samba 提供。它只需要啟用 nmb.service 模塊。運行 Windows,macOS 或運行 nmb 的 Linux 的計算機都能夠發現你的設備。
    • 通過 mDNS 進行主機名解析。 由帶有 Avahinss_mdns(閱讀 Avahi#Hostname resolution 獲取詳細配置)或 systemd-resolved 提供。 運行 macOS,或者帶有 Avahi 的 Linux 或者運行 systemd-resolved 的 Linux 的計算機能夠發現你的設備。老版本的 Win32 API 不支持 mDNS,一些老的 Windows 應用可能無法訪問你的設備。

更多設置[編輯 | 編輯原始碼]

更改接口名稱[編輯 | 編輯原始碼]

注意: 當你改變接口命名規則時,不要忘記更新所有與網絡相關的配置文件和自定義的 systemd 單元文件以反映更改。

你可以通過編輯 udev 規則來手動更改設備名稱。例如:

/etc/udev/rules.d/10-network.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="aa:bb:cc:dd:ee:ff", NAME="net1"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="ff:ee:dd:cc:bb:aa", NAME="net0"

這些規則將在啟動時自動應用。

值得注意的兩點:

  • 使用這條命令來獲得每張網卡的 MAC 地址:

cat /sys/class/net/設備名/address

  • 確保你的 udev 規則中使用小寫的十六進制值,而不是大寫。

如果網卡的 MAC 地址是會動態變化的,你可以使用 DEVPATH,例如:

/etc/udev/rules.d/10-network.rules
SUBSYSTEM=="net", DEVPATH=="/devices/platform/wemac.*", NAME="int"
SUBSYSTEM=="net", DEVPATH=="/devices/pci*/*1c.0/*/net/*", NAME="en"

要得到所有當前已連接設備的 DEVPATH,請查看 /sys/class/net/ 中符號鏈接指向的位置。例如:

file /sys/class/net/*
/sys/class/net/enp0s20f0u4u1: symbolic link to ../../devices/pci0000:00/0000:00:14.0/usb2/2-4/2-4.1/2-4.1:1.0/net/enp0s20f0u4u1
/sys/class/net/enp0s31f6:     symbolic link to ../../devices/pci0000:00/0000:00:1f.6/net/enp0s31f6
/sys/class/net/lo:            symbolic link to ../../devices/virtual/net/lo
/sys/class/net/wlp4s0:        symbolic link to ../../devices/pci0000:00/0000:00:1c.6/0000:04:00.0/net/wlp4s0

設備路徑應與新設備名稱和舊設備名稱均匹配,因為該規則可能在啟動時執行多次。例如,在第二條規則中若寫 "/devices/pci*/*1c.0/*/net/enp*" 是錯誤的,因為一旦設備名稱更改為 en,它將停止匹配。 只有系統默認規則會第二次觸發,從而使設備名稱改回例如 enp1s0

如果你正在使用具有動態 MAC 地址的 USB 網絡設備(如 Android 手機網絡共享),並且你希望能夠使用不同的 USB 端口,你可以使用匹配供應商和產品 ID 的規則:

/etc/udev/rules.d/10-network.rules
SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="12ab", ATTRS{idProduct}=="3cd4", NAME="net2"

測試[損壞的鏈接:無效的章節]自定義規則,可以直接從用戶空間觸發這些規則,例如使用 udevadm --debug test /sys/class/net/*。切記先關閉您要重命名的接口(例如,ip link set enp1s0 down)。

注意: 選擇靜態名稱時,應該避免使用形如「ethX」或「wlanX」的名稱,因為這可能在引導時導致內核與 udev 之間的競爭狀態。相反,最好用內核默認不會使用的接口名稱,例如:net0net1wifi0wifi1。更多細節請查看 systemd 文檔。

改回傳統接口名稱[編輯 | 編輯原始碼]

如果希望使用像 eth0 這樣的傳統接口命名,可以通過下面方法禁用可預測網絡接口名:

# ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules

設定設備的 MTU 和隊列長度[編輯 | 編輯原始碼]

你可以手動定義一條 udev 規則來改變設備的 MTU 和隊列長度。舉例來說:

/etc/udev/rules.d/10-network.rules
ACTION=="add", SUBSYSTEM=="net", KERNEL=="wl*", ATTR{mtu}="1500", ATTR{tx_queue_len}="2000"

mtu:使用大於 1500 的值(所謂的巨型幀)可以大大加快網絡傳輸速度。請注意,所有網絡接口(包括本地網絡中的交換機)都必須支持相同的 MTU 才能使用巨型幀。對於 PPPoE,MTU 不應大於 1492。您還可以通過 systemd.netdev(5) 設置MTU。

tx_queue_len:對於具有高延遲的速度較慢的設備(如調製解調器鏈路和 ISDN),使用較小的值。對於通過高速 Internet 連接進行大型數據傳輸的服務器,建議使用較大的值。

綁定和鏈路聚合[編輯 | 編輯原始碼]

參閱 netctl[損壞的鏈接:無效的章節]systemd-networkd無線網絡綁定

IP 別名[編輯 | 編輯原始碼]

IP 別名是指給同一個網絡接口分配多個 IP 地址。這樣一個網絡節點可以有多個網絡連接,每個實現不同的作用。典型的用處是 Web 服務器和 FTP 服務器的虛擬主機,或者是重組服務器時不需要更新其他任何機器上的 IP (對於名稱服務器來說很有用)。

例子[編輯 | 編輯原始碼]

要手動設置別名,可以使用 iproute2 執行:

# ip addr add 192.168.2.101/24 dev enp2s0 label eth0:1

刪除別名:

# ip addr del 192.168.2.101/24 dev enp2s0:1

默認情況下,發往子網的數據包將使用主 IP。如果目標 IP 子別名,原始 IP 也會被相應設置。如果有多個網卡,可以通過 ip route 查看默認路由。

混雜模式[編輯 | 編輯原始碼]

切換網卡到混雜模式可以讓(無線)網卡接收所有數據然後轉交給操作系統處理。而正常模式下,網卡會丟掉不是發給自己的數據。這通常用來檢查網絡問題或進行數據包嗅探

/etc/systemd/system/promiscuous@.service
[Unit]
Description=Set %i interface in promiscuous mode
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/ip link set dev %i promisc on
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

如果要在 enp2s0 上啟用全接收模式,只需要啟用promiscuous@enp2s0.service.

檢測套接字[編輯 | 編輯原始碼]

ss 是用來檢測網絡端口的工具,是 iproute2 軟件包的一部分。它與已棄用的 netstat 工具具有相似的功能。

一般的用途包括:

顯示所有 TCP 連接及相應的服務名:

$ ss -at

顯示所有 TCP 連接及其端口號:

$ ss -atn

顯示所有 UDP 連接:

$ ss -au

更多信息請參閱 ss(8)

疑難解答[編輯 | 編輯原始碼]

TCP窗口擴縮(window scaling)故障[編輯 | 編輯原始碼]

TCP 包頭有個「窗口」(window)值表明其它主機可以發送多少數據回來。這個值只有16個bit,也就是說窗口大小最多只有 64KiB。TCP包會被緩存一段時間( 它們要重新排序),如果內存有限(過去經常是)的話,主機會很容易用完內存。

回到 1992 年,內存逐漸增加,RFC 1323 被發布以改善情況:窗口擴縮(Window Scaling)。所有包裡的窗口值,可以被初始連接時定義的一個縮放因子(Scale Factor)所改變。8bit 的縮放因子使得窗口可以是初始 64KiB 的 32 倍。

但是 Internet 上有些有故障的路由器和防火牆會將縮放因子重寫為 0,這導致主機之間產生誤解。Linux內核 2.6.17 引入了新的計算方式生成更高的縮放因子,間接的使得這些有故障的路由器和防火牆引發的後果更明顯。

這導致連接緩慢甚至中斷。

如何診斷故障[編輯 | 編輯原始碼]

首先,我們要明白:這個問題很怪異。在某些案例中,你根本無法使用(HTTP, FTP, ...),而有時候,你可以連接某些主機(很罕見)。

當你碰到這個故障時,dmesg 的輸出正確,日誌也沒問題,ip addr 報告狀態正常……實際上一切看起來都很正常。

如果你無法瀏覽任何網站,不過你能 ping 通某些主機,很可能你是遇到了這個問題:ping 使用 ICMP 協議所以不受 TCP 問題的影響。

你可以嘗試使用 Wireshark。你也許會看到 UDP 和 ICMP 通訊成功,但是 TCP 通訊不成功(僅對外部主機)。

如何修復[編輯 | 編輯原始碼]

糟糕的方法[編輯 | 編輯原始碼]

用比較糟糕的方法修復的話,你可以修改縮放因子計算所基於的 tcp_rmem 值。雖然它對大部分主機有效,但並不擔保一定都有效,特別是某些很遠的主機。

# echo "4096 87380 174760" > /proc/sys/net/ipv4/tcp_rmem
好點的方法[編輯 | 編輯原始碼]

只需要禁止窗口縮放。雖然窗口縮放是個不錯的TCP特性,但它也可能令人不安,特別是當你沒法修改出了問題的路由器的時候。有幾種方法可以禁止窗口縮放,而看來最可靠的(適用於大部分內核)是將下面一行加入到你的 /etc/sysctl.d/99-disable_window_scaling.conf 中 (參見 sysctl):

net.ipv4.tcp_window_scaling = 0
最佳的方法[編輯 | 編輯原始碼]

這個故障是由有毛病的路由器/防火牆引起的,所以最好換了它。有些用戶報告說那些有故障的路由是他們自己的 DSL 路由。

更多[編輯 | 編輯原始碼]

本段內容是基於 LWN文章 TCP window scaling and broken routers 和一篇 Kernel Trap 文章:Window Scaling on the Internet

在 LKML 上也有幾篇相關的帖子。

連接第二台電腦後無法進行橋接[編輯 | 編輯原始碼]

第一台電腦有兩個 LAN 口。第二台電腦有一個 LAN 口並連接到第一台電腦。讓第二台電腦橋接網絡接口並可以訪問 LAN 口:

# sysctl net.bridge.bridge-nf-filter-pppoe-tagged=0
# sysctl net.bridge.bridge-nf-filter-vlan-tagged=0
# sysctl net.bridge.bridge-nf-call-ip6tables=0
# sysctl net.bridge.bridge-nf-call-iptables=0
# sysctl net.bridge.bridge-nf-call-arptables=0

本地主機名解析[編輯 | 編輯原始碼]

systemdmyhostname Name Service Switch (NSS) 模塊提供localhost 和本地域名到 IP 地址的解析,默認是啟用的。

然而一些客戶端應用仍然會依賴於 /etc/hosts,相關例子參見 [5] [6]

要阻止程序通過網絡非安全的解析 localhost,請將 localhost 加入 hosts(5) 文件:

/etc/hosts
127.0.0.1        localhost
::1              localhost
注意: Report any software affected by this issue in FS#56684. This may help in getting localhost entries added to the default /etc/hosts.

要配置 /etc/hosts,將以下內容加入其中:

127.0.0.1        localhost
::1              localhost
127.0.0.1        myhostname.localdomain        myhostname
注意: /etc/hosts 中在 IP 地址後的主機名或別名的順序是重要的。第一個字符串會被認為是標準主機名,其後可以加上以點逐級分隔的上級域名(也就是上面的 .localdomain)。所有同一行中其後的字符串都被認為是別名。更多信息請參閱 hosts(5)

這樣系統就會解析每條配置:

$ getent hosts
127.0.0.1       localhost
127.0.0.1       localhost
127.0.0.1       myhostname.localdomain myhostname

對於有固定 IP 地址的系統,應該用固定 IP 地址替換 127.0.0.1。For a system with a fully qualified domain name, insert the fully qualified domain name before the hostname (see the following link for the reasoning). For example:

/etc/hosts
127.0.0.1        localhost
::1              localhost
203.0.113.45     host1.fqdomain.example host1
注意: The order of hostnames/aliases that follow the IP address in /etc/hosts is significant. The first string is considered the canonical hostname and may be appended with parent domains, where domain components are separated by a dot. All following strings on the same line are considered aliases. See hosts(5) for more info.

As a result the system resolves to both entries:

$ getent hosts
127.0.0.1       localhost
127.0.0.1       localhost
127.0.0.1       myhostname

擴展閱讀[編輯 | 編輯原始碼]