网络配置 - Arch Linux 中文维基

跳转到内容

# 网络配置

来自 Arch Linux 中文维基

相关文章

- Firewalls
- Router
- Internet sharing
- Network Debugging

翻译状态：

- 本文（或部分内容）译自 Network configuration，最近一次同步于 2022-12-04，若英文版本有所更改，则您可以帮助同步与翻译更改的内容。
- 您可以在 ArchWiki 的对应页面找到本文翻译的原始修订历史。
- 本文可能与英文原文存在出入。

这篇文章或章节的翻译质量不佳。

原因：本文久未同步，内容与英语原文相比，已有较大差异。（在 Talk:网络配置# 中讨论）

本页解释了如何在 OSI 第三层及之上配置网络连接。有部分内容在网络配置/以太网和网络配置/无线网络配置两个页面中。

注意：配置网络连接时请不要同时安装启用多个网络管理器，例如：不要同时启用 iwctl 与 NetworkManager，这可能会导致网络连接故障
提示：建议参阅systemd-networkd

## 检查连接

要排查网络连接问题，请依次检查以下条件，确保满足每一项:

1. 你的网络接口已列出并处于启用状态。否则请检查设备驱动－请查阅 Network configuration/Ethernet#Device driver 或 Wireless 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 命令对每个收到的回应都会显示一行信息，直到你手动中断（按ctrl+c）。详细的解释请阅读 ping(8) 手册。注意，计算机可以配置为不响应 ICMP 回应请求。[1]

如果你收到错误信息（参见ping错误提示）或未收到任何回复，原因可能与默认网关配置或者网络接入服务商（ISP）有关。可以运行 traceroute 命令以进一步诊断到对端主机的路由路径。

## 网络管理

通过以下步骤来设置网络链接：

1. 确保网络接口已连接并已开启。
2. 连接到网络。网线已接好或者已经连接到无线局域网。
3. 配置网络连接：
   - 静态 IP 地址
   - 动态 IP 地址：使用 DHCP

注意：安装镜像使用 systemd-resolved 和 systemd-networkd 为[2], WLAN 和 WWAN网络配置 DHCP 客户端。

### 网络工具

Arch Linux 已经弃用了 net-tools包 转而使用 iproute2包。 [3]

已弃用的命令 | 替换命令
--- | ---
arp | ip neighbor
ifconfig | ip address, ip link
netstat | ss
route | ip route

想要更多更完整的总结，请参阅这篇文章。

### iproute2

iproute2 是 base包 元包的依赖，提供 ip(8) 命令行接口，用于管理网络接口，IP 地址和路由表。注意使用 `ip` 进行的配置会在重启后丢失。要进行永久配置，可以使用网络管理器或通过脚本和 systemd 单元使 ip 命令自动化。同时需要注意的是 `ip` 命令通常能够缩写，为了清楚起见，本文对其进行了详细说明。

### 网络接口

默认情况下， udev 使用可预测的网络接口名称分配给你的网络接口，该名称以 `en` (有线/以太网) ，`wl` (无线/WLAN) 或 `ww` (WWAN)开头 。参见 systemd.net-naming-scheme(7)。

提示：要改变接口名称，请参阅 #更改接口名称 和 #改回传统接口名称。

#### 列出网络接口

有线和无线接口名称都可以通过 `ls /sys/class/net` 或 `ip link` 找到。要注意的是 `lo` 是 Loop 设备，不被用于建立网络连接。

同样，也可以用 `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

  注意：

  - 地址格式是 CIDR 表示法，这种格式也可以用来提供子网掩码。
  - `+` 是使 `ip` 从 IP 地址和子网掩码派生多播地址的特殊符号。

  注意：要确保手动分配的 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 | 是 | dhcpcd 或 dhclient包 | `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 进行主机名解析。 由带有 Avahi 的 `nss_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 之间的竞争状态。相反，最好用内核默认不会使用的接口名称，例如：`net0`、`net1`、`wifi0`、`wifi1`。更多细节请查看 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

### 本地主机名解析

systemd包 的 `myhostname` 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

## 扩展阅读

- Linux 网络管理员指南
- Debian 参考手册：网络安装
- RHEL7：网络指南
- 监视和调优 Linux 网络栈：接收数据
- 监视和调优 Linux 网络栈：发送数据
- 使用 Linux tracepoints、perf 和 eBPF 跟踪数据包

分类：​

- 网络

隐藏分类：​

- 使用“模板:糟糕的翻译”标记的页面或章节
- 包含损坏章节链接的页面

网络配置
添加话题