晚上的时候临时起意决定把网络管理器从 netctl 切换到 systemd-networkd,切换的过程意外的顺畅。本文记录了一下切换的过程并简单介绍一下 systemd-networkd + iwd 的组合如何使用。


出场人物介绍

netctl

netctl 是 archlinux 的亲儿子,上游就在 https://git.archlinux.org/netctl.git/,也是除了 systemd-networkd 之外(这是 systemd 钦定的),唯一一个进入 base 组的网络管理工具,说是官方钦定也不为过。netcl 依赖 dhcpcd 或者 dhclient 来获取动态 IP 地址,通过 wpa_supplicant 来访问加密的 WiFi,提供了 wifi-menu 供用户在命令行下交互式地选择热点并输入密码。同时还提供了一系列的 systemd service 文件(netctl@.servicenetctl-ifplugd@.servicenetctl-auto@.service)来帮助用户进行配置,比如在开启了 netctl-auto@<interface>.service 之后,你的网卡就能在可选的 profile 中自动切换。

systemd-networkd

正如它的名字所暗示的,这是 systemd 全家桶的一员。它主要负责的是检测并配置网络设备,特别的是它还能够用来配置 systemd-nspawn 启动的容器的网络。

iwd

iwd (iNet wireless daemon) 是 Intel 开发,用于取代 wpa_supplicant 的 WiFi 后端。它的主要目标是通过不依赖任何外部库而是最大限度的利用 Linux 内核提供的功能来优化资源利用率。iwd 可以很好的跟 systemd-network 配合使用。

使用场景介绍

平时只需要连接 3 个 Wi-Fi:家里的,公司的,手机的,没有频繁切换/增加/修改/删除 Wi-Fi 配置的需求,所以我不需要一个常驻通知区域的服务来进行切换。此外,我的 VPN 已经全部通过 systemd 来进行管理了,所以也不需要网络管理工具替我做这些操作。我需要的是这样的一个工具组合:一个负责管理网络设备,一个负责连接 WiFi 并进行认证。之前的组合是 netctl + wpa_supplicant,现在我有了新欢:systemd-networkd + iwd

如何使用

停用 netctl

首先需要停用 netctl 的相关服务,避免多个网络管理工具在一起打架。

:) systemctl stop netctl-auto@<interface>.service
:) systemctl disable netctl-auto@<interface>.service

配置网卡

然后按照 Wiki 的指示写无线网卡的配置,放在 /etc/systemd/network 下。

对无线网卡来说,最小化的配置是这样的:

[Match]
Name=wlp2s0

[Network]
DHCP=ipv4
  • Match 主要是用于匹配管理的设备,可以通过设备名,MAC 地址等来选择
  • Network 用来做网络相关的具体配置,比如 DHCP,DNS 等

我的本地开启了 coredns 作为 DNS 服务,所以我需要额外加一些配置来通过 DHCP 来获取 IPv4 地址,但是不使用 DHCP 下发的 DNS。

[Match]
Name=wlan0

[Network]
DHCP=ipv4
DNS=127.0.0.1

[DHCP]
UseDNS=false

iwd 启动的时候似乎会修改网络设备的名字,我的网卡被修改成了 wlan0

在配置写好之后就可以启动 systemd-networkd 的服务啦:

:) systemctl start systemd-netword

如果修改了网络配置,只需要 restrart 即可。

更具体的配置可以参阅 ArchWiki 或者 man systemd-networkd

配置 iwd

iwd 不是自带的软件包,所以首先需要自行安装:

:) pacman -S iwd

在开始使用之前,我们需要 start 并且 enable iwd 服务:

:) systemctl start iwd
:) systemctl enable iwd

然后就可以用 iwctl 进行管理啦,iwctl 默认会进入一个交互式的命令行界面,使用体验还是很赞的:

:) iwctl
[iwd]#

此时输入 help 会返回支持的所有命令,各个命令都比较直观,只要对 WiFi 的相关技术名词稍有了解就能很快上手,此外这个界面所有命令都支持自动补全,好评。

首先先看看我们有哪些设备:

[iwd]# device list
Devices                                   *
--------------------------------------------------------------------------------
Name                Address             Powered   Adapter   Mode
--------------------------------------------------------------------------------
wlan0               xx:xx:xx:xx:xx:xx   on        phy0      station

这个界面是动态的,右上角的 * 会不断闪烁表明这个界面是实时的。

然后我们可以手动触发一次 STA 扫描:

[iwd]# station wlan0 scan

之后就可以查看有哪些能连接 WiFi 热点了:

[iwd]# station wlan0 get-networks
                               Available networks                             *
--------------------------------------------------------------------------------
    Network name                    Security  Signal
--------------------------------------------------------------------------------
    CU_SNZQ                         psk       ****
    xjzy                            psk       ****
    Tenda_30BDD0                    psk       ****
    TP-LINK_D82B80                  psk       ****
    TP-LINK_lee                     psk       ****
    ziroom201                       psk       ****
    mhshome                         psk       ****
    TP-LINK_he                      psk       ****
    TP-LINK_450C                    psk       ****
    yuzhe                           psk       ****
    z212-202                        psk       ****
    Bill's Router                   psk       ****
    tcs                             psk       ****
  > XXXXXXXXXXX                     psk       ****

这个界面同样是动态的,可以查看当前能连接网络机器信号强度。

最后就能够选择想要连接 SSID 连接网络了,如果需要输入密码的话,iwd 还会出现一个提示要求输入密码。

[iwd]# station wlan0 connect XXXXXXXXXXX

这里有个需要提出来的点:iwd 通过交互式界面成功连接上网络之后,就会自动的在 /var/lib/iwd 下生成对应的配置文件,之后 iwd 自动的进行连接。所以一方面是不需要自己手动的去写配置文件,另一方面是切换过程也是自动的,不需要人工干预。

iwd 生成的配置文件名是有一定规则的,用 SSID 作为文件名,然后以加密方式作为后缀,比如 *.open 表示这是一个开放网络,*.psk 表示这是一个使用 PSK 加密的网络。

检查状态

全部配置好之后可以分别查看一下 WiFi 和网卡的状态:

:) iwctl device wlan0 show
                                 Device: wlan0
--------------------------------------------------------------------------------
  Settable  Property            Value
--------------------------------------------------------------------------------
            Name                wlan0
         *  Mode                station
         *  Powered             on
            Address             xx:xx:xx:xx:xx:xx
         *  WDS                 off
            Adapter             phy0
:) networkctl status
●        State: routable
       Address: 192.168.0.103 on wlan0
                xxxx::xxxx:xxxx:xxxx:xxxx on wlan0
       Gateway: 192.168.0.1 (TP-LINK TECHNOLOGIES CO.,LTD.) on wlan0
           DNS: 127.0.0.1

总结

systemd 真香,上交底裤我光荣!天灭 networkmanager !

参考资料