網絡配置

出自 Arch Linux 中文维基

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

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

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

注意: 配置網絡連接時請不要同時安裝啟用多個網絡管理器,例如:不要同時啟用 iwctl 與 NetworkManager,這可能會導致網絡連接故障
提示:建議參閱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

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