内容纲要

🗂 | 查看更多 关于 Linux 的内容


Linux 之前与传统 UNIX 一样使用相同的命令进行网络管理和状态检查,如 ifconfigroutenetstat。这些命令在目前大多数发行版中仍旧可用,但是目前活跃的开发活动已经转向 iproute2,其中用于包括路由选择在内的大部分日常网络配置的 ip 命令可替代 ifconfigroute 命令,而用于检查网络套接字状态的 ss 命令大体上也可用于替代 netstat

本文主要介绍 iproute2 为主的命令,但鉴于可能会使用一些老旧的发行版,所以会将已经停止维护的 net-tools 相关命令以「💡 提示」的形式注明。

基本的网络配置

给本地网络添加新机器的步骤差不多是这样:

  1. 分配唯一的 IP 地址和主机名;
  2. 配置网络接口和 IP 地址;
  3. 设置默认路由(及可能更为复杂的路由选择配置);
  4. 设置 DNS 服务器;

一般来说可以依赖 DHCP 服务器完成大部分配置工作,现在新安装的系统一般默认都会选择通过 DHCP 配置,所以可能完全不需要手动配置网络。

在完成任何可能影响系统启动的改动后,一定要重新启动以查看机器是否正常,否则在一段时间后当电源出现故障机器无法引导时,很难再想起当初做了什么改动才引起这些问题。

在完成基本的网络配置后,可以使用 ping 或 traceroute 这类基本的工具测试网络的连通性。

查看网络接口及 IP 配置

💡 提示:类似于 net-tools 的 ifconfig -a

可以使用 ip link show 查看所有的网络接口

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:21:a7:43 brd ff:ff:ff:ff:ff:ff

接口的命名约定各不相同,如:

  • eno1(板载网卡)
  • ens33(PCI-E 网卡)
  • enp0s3(无法获取物理信息的 PCI-E 网卡)

Linux 当前版本试图确保接口名称不会随时间发生变化,所以名称显得有些随意,而 FreeBSD 和较久的 Linux 内核采用的是更为传统的「驱动程序」+「实例编号」的形式,如 eth0

显示网络接口及 IP 配置信息可使用ip addr

$ ip address # 可简写为 ip addr
...
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
    link/ether aa:aa:00:12:07:7f brd ff:ff:ff:ff:ff:ff
    inet 98.142.140.209/21 brd 98.142.143.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a8aa:ff:fe12:77f/64 scope link 
       valid_lft forever preferred_lft forever
...

可以看到相比前者返回的信息要更详尽,其中inet 表示 IPv4 相关信息;inet6 表示 IPv6 相关信息。

配置网络

IP 配置

添加 IP 地址

# 在网卡 ens33 上添加 IP 地址 192.168.1.3/24
$ sudo ip addr add 192.168.1.100/24 dev ens33

# 在网卡 ens33 上添加 IP 地址 192.168.1.3/24,并将广播地址指定为 192.168.1.63
$ sudo ip addr add 192.168.1.13/26 broadcast 192.168.1.63 dev ens33

在这里第二条示例中的 broadcast 192.168.1.63 其实是多余的,因为按照给定的掩码为 26 默认地址就是 192.168.1.63,如果需要明确设置广播地址就需要这么做。

删除 IP 地址

$ sudo ip addr del 192.168.1.100/24 dev ens33

静态路由配置

💡 提示:类似于 net-tools 的 routenetstat

查看路由表

$ ip route show # 可简写成 ip route
default via 192.168.1.2 dev ens33 proto dhcp src 192.168.1.65 metric 100 
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.65 
192.168.1.2 dev ens33 proto dhcp scope link src 192.168.1.65 metric 100 

类似于 netstat -rnetstat -rn,虽然输出信息不如后者清晰。

路由是在 IP 层执行的。当要发送到其他某个主机的包到达的时候,就把这个包的目标 IP 和内核中路由表里的路由进行比较,如果它匹配表中的某条路由,那么这个包就被转发到与这条路由相关联的「下一跳网关」(next-hop gateway)的 IP 地址。

这里有两种特殊的情况:首先,包可能位于直连相关网络的中的主机,这种情况下「下一跳网关」的地址是本地主机自己的某个网络接口,所以包会直接发送到它的目的地。此类路由在配置网络接口时通过 ip address 命令添加到路由表中。其次,可能没有与目的地匹配的路由。这种情况下则使用默认路由(如存在),否则 ICMP 会将消息 network unreachablehost unreachable 返回给发送方。

许多局域网只有一个出口且它们的默认路由就指向这个出口。在 Internet 骨干网中的路由器没有默认路由(包就停在那里),如果没有对应目的地的路由项,就不能到达这个目的地址。

# 添加路由
# 添加默认路由,网关为 192.168.1.1
$ sudo ip route add default via 192.168.1.1
# 添加网卡为 eth0 的默认路由,网关为 192.168.1.1
$ sudo ip route add default via 192.168.1.1  dev eth0
# 添加通过网关 192.168.1.1 到达 192.168.1.0/24 的路由
$ sudo ip route add 192.168.1.0/24 via 192.168.1.1
# 添加网卡 eth0 上网关为 192.168.1.254 到达 192.168.1.0/24 的路由
$ sudo ip route add 192.168.1.0/24 via 192.168.1.254 dev eth0

# 替换路由(没有则使用 add)
$ sudo ip route replace 192.168.1.0/24 dev eth0

# 删除一条路由
$ sudo ip route delete 192.168.1.0/24 via 192.168.1.1

# 初始化路由表并重新开始
$ sudo ip route flush

# 显示到达指定 IP 的路由
$ ip route get 192.168.1.2

设置默认路由时使用关键字 default 而非地址或名称,关键字 default 等同于 0.0.0.0/0(它可以匹配任意地址,且没有真实的具体目的地)。

配置文件

通过 ip 命令进行的配置虽然会立即启用但只是临时生效(在系统重启后就会失效),所以如果需要配置持久性更改就需要修改网络配置文件。

NetworkManager & Debian

Debian 使用 NetworkManager 进行管理网络,修改 IP 地址、网络掩码和默认路由的主要配置为 /etc/network/interfaces

# 先将配置文件备份以防万一
$ sudo cp /etc/network/interfaces  /etc/network/interfaces.bak

# 编辑配置
$ sudo vim /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug ens33
iface ens33 inet dhcp

上述示例中 iface ens33 inet dhcp 表示接口 ens33 的 IPv4 正在使用 DHCP 获取配置,如果想要手动配置:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug ens33
iface ens33 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1

dhcp 修改为 static 然后填写 IP 地址、网络掩码和默认路由的配置。

保存配置后重启服务:

$ sudo systemctl restart networking

Netplan & Ubuntu

Ubuntu 原先也使用 NetworkManager,但从 17.10 开始转为使用 Netplan

它的配置文件位置也不一样,位于 /etc/netplan/

ls /etc/netplan/

要使用 ls 命令查看下默认的配置文件名,因为它不是固定的,它可能是 00-installer-config.yaml50-cloud-init.yaml 或是其他。

# 先将配置文件备份一下以防万一
$ sudo cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak

# 编辑配置文件
$ sudo vim /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    ens33:
      dhcp4: true
  version: 2

配置内容其实大同小异,比如此处网卡 ens33 使用 DHCP 获取 IPv4 配置信息,进行手动配置:

network:
  ethernets:
    ens33:
      addresses: [192.168.1.100/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1, 8.8.8.8]
  version: 2
  • addresses:即 IP 地址,此处为一个数组,如果你有多个地址需要配置可以就写成:[192.168.1.121/24,192.168.1.122/24],如果你有 IPv6 地址可以写成 [192.168.1.121/24, 2002:7111:236b:1::1/64],而网络掩码不像之前使用类似 255.255.255.0 而是以 /24 形式配置。
  • gateway4:即网关,此处的 4 表示 IPv4,举一反三如果要配置 IPv6 的网关便是 gateway6
  • nameservers: 也就是 DNS 服务器地址,同样以数组的方式进行多个配置。

除了上述还有一些其他配置可以查看 Netplan官网的 示例配置

需要注意的是文件格式为 YAML,如果你从未了解过该格式很可能在格式缩进等问题上出岔子,所以在编辑完成后可以先使用测试命令:

$ sudo netplan try

如果配置的格式上没有问题会提示配置成功,按「回车键」即可应用。

如果你很自信认为绝对没问题配置一次过也可以使用命令直接应用配置:

$ sudo netplan apply

配置网络接口

一些 ip link 命令的网络接口操作:

# 开启 eth0 网卡
$ sudo ip link set eth0 up

# 关闭 eth0 网卡
$ sudo ip link set eth0 down

# 修改 eth0 的 MAC 地址
$ sudo ip link set dev eth0 address aa:bb:cc:dd:ee:ff

# 开启网卡的混合模式
$ sudo ip link set eth0 promisc on

# 关闭网卡的混合模式
$ sudo ip link set eth0 promisc offi

# 设置网卡队列长度
$ sudo ip link set eth0 txqueuelen 1200

# 设置网卡最大传输单元
$ sudo ip link set eth0 mtu 1400

一些 ethtool 命令的网络接口操作:

# 查看网卡 eth0 的 NIC 信息
$ ethtool eth0

# 使用 -i 查看网卡 eth0 的驱动程序和固件版本
$ ethtool -i eth0

# 使用 -S 查看网卡 eth0 的网络使用情况统计
$ ethtool -S eth0

# 查找指定网卡的物理接口(使其 LED 灯闪烁)
$ ethtool -p eth0

# 修改网卡 eth0 的以太网速度,修改后需要手动重启网卡
$ sudo ethtool -s eth0 speed 100
$ sudo ip link set eth0 up

# 显示与协议相关的任务被分配给了网络接口而不是内核
$ ethtool -k eth0
# 使用 -K 设置强制或禁止某些类型的任务分担

# 查看网卡 eth0 的自动协商、RX 和 TX
$ sudo ethtool -a eth0

# 启用或禁用自动协商
$ sudo ethtool -s eth0 autoneg off
$ sudo ethtool -s eth0 autoneg on

# 设置网卡 eth0 全/半双工
$ sudo ethtool -s eth0 duplex full
$ sudo ethtool -s eth0 duplex half

# 设置网卡 eth0 速度为 100 Mbit/s
$ sudo ethtool -s eth0 speed 100

显示 ARP 配置

💡 提示:类似于 net-tools 的 arp -na

ip neighbor 命令能够检查并处理 ARP 或 NDP 创建的缓存、添加或删除条目、清除或打印缓存。

$ ip neigh
173.82.157.121 dev eth0 lladdr 00:17:df:b3:a8:00 STALE
98.142.136.35 dev eth0 lladdr 24:6e:96:42:3b:1c STALE
98.142.136.1 dev eth0 lladdr 10:0e:7e:a5:5a:a1 PERMANENT

显示 Socket 配置

💡 提示:类似于 net-tools 的 netstat

ss 用来显示处于活动状态的套接字信息。ss 命令可以用来获取 socket 统计信息,它可以显示和 netstat 类似的内容。但 ss 的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比 netstat 更快速更高效。


# 显示 TCP socket
$ ss -at

# 显示 UDP socket
$ ss -au

# 显示 socket 使用摘要
$ ss -s

# 显示进程 socket 使用摘要
$ ss -pl

# 显示连接到 192.168.2.1 的 80 端口的所有 socket 情况
$ ss -t dst 192.168.2.1:80

# 显示所有 SSH 相关的连接
$ ss -t state established '( dport = :ssh or sport = :ssh )'

配置 DNS 及本地映射

DNS 配置

传统的修改 DNS 方法为修改配置文件:/etc/resolv.conf

$ sudo vim /etc/resolv.conf
nameserver 1.0.0.1
nameserver 1.1.1.1
nameserver 8.8.4.4

如上 nameserver 字段不变后面写上 DNS 服务器的 IP 即可,最多可以有 3 个条目且可能的话应该不止有 1 个。

应当将「距离最近的」、稳定的 DNS 服务器放到最前面,服务器会按照出现的顺序依次访问,但尝试访问下一个服务器之前的超市等待时间较长。

但目前不少发行版已经不在此进行配置 DNS,你可能会看到这样的配置:

# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "resolvectl status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53
options edns0 trust-ad

开头提示此文件已经被 systemd-resolved 托管了不要进行编辑。有些文档指出可以通过系统管理守护进程查看是 init 还是 systemd 以进行区分,但这并不准确。

如果使用的是 systemd-resolved,可以在 /etc/systemd/resolved.conf 中进行持久性更改

$ sudo vim /etc/systemd/resolved.conf
DNS=1.0.0.1 8.8.4.4
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#DNSOverTLS=no
#Cache=no-negative
#DNSStubListener=yes
#ReadEtcHosts=yes

DNS 前的井号移除(使其不是注释)并配置 DNS 服务器 IP,保存配置后应用生效:

# 重启 systemd-resolved 服务
$ sudo systemctl restart systemd-resolved

# 查看是否生效
$ resolvectl status | grep 'DNS Servers'

本地映射

配置 /etc/hosts 文件是一种名称映射到 IP 地址最古老也是最简单的方法:

$ sudo vim /etc/hosts
127.0.0.1 localhost

文件中每一行以一个 IP 地址开头,后面跟着 地址即可。

主机名

可以使用 hostname 命令查看现在的主机名。

传统的修改主机名方式为修改 /etc/hostname 文件,在使用 systemd 的系统上可以使用命令:

$ sudo hostnamectl set-hostname <主机名>