ConnMan (简体中文) - ArchWiki

Jump to content

相关文章

- Network configuration
- Wireless network configuration

翻译状态：本文是 ConnMan 的翻译。上次翻译日期：2021-03-12。如果英文版本有所更改，则您可以帮助同步翻译。

ConnMan 是一个命令行网络管理器，为嵌入式设备和快速响应设计。ConnMan 通过 插件 扩展，但内置了 DHCP 与 NTP 支持。[1]

## 安装

安装 connman 软件包。 wpa_supplicant、bluez 与 openvpn 是对应 Wi-Fi、蓝牙与 VPN 功能的可选依赖。

在启用 `connman.service` 之前，确保禁用所有已安装的网络配置。

ConnMan 自带 connmanctl(1) 命令行界面。各种 #前端 也可以使用。

### 前端

- cmst — ConnMan 的 QT GUI。

  https://github.com/andrew-bibb/cmst || cmstAUR

- connman-ncurses — ConnMan 的简单 ncurses UI；没有实现 ConnMan 的全部功能，但是可以用（有没有 X 都可以运行），参考 wiki。

  https://github.com/eurogiciel-oss/connman-json-client || connman-ncurses-gitAUR

- ConnMan-UI — GTK3 客户端托盘程序。

  https://github.com/tbursztyka/connman-ui || connman-ui-gitAUR

- connman_dmenu — dmenu 客户端/前端。

  https://github.com/taylorchu/connman_dmenu || connman_dmenu-gitAUR

- Econnman — Enlightenment 桌面托盘程序。

  https://www.enlightenment.org || econnmanAUR

- LXQt-Connman-Applet — LXQt 桌面托盘程序。

  https://github.com/lxqt/lxqt-connman-applet || lxqt-connman-appletAUR

- connman-gtk — GTK 客户端。

  https://github.com/jgke/connman-gtk || connman-gtkAUR

- gnome-extension-connman — ConnMan 的 Gnome3 扩展；如果不安装 connman-gtk，提供的功能很少。

  https://github.com/jgke/gnome-extension-connman || https://extensions.gnome.org/extension/981/connman-extension/

## 用法

ConnMan 自带 `connmanctl` 命令行界面，参考 connmanctl(1)。 如果你不提供任何命令，直接运行 `connmanctl`，将会启动一个交互式终端。

ConnMan 会自动处理有线连接。

### Wi-Fi

#### 启用与禁用 wifi

执行 `connmanctl technologies` 来检查 wifi 是否开启，查看类似 `Powered: True/False` 的输出。 执行 `connmanctl enable wifi` 来开启 wifi，或者执行 `connmanctl disable wifi` 来禁用 wifi。 其他启用 wifi 的方法包括使用笔记本电脑上的 `Fn` 键，或者执行 `ip link set <interface> up`。

#### 连接到公开的接入点

`connmanctl` 接受简单的 technologies 名称来扫描网络，要扫描附近的 Wi-Fi 网络：

    $ connmanctl scan wifi

在扫描之后，列出可用的网络（示例输出）：

    $ connmanctl services

    *AO MyNetwork               wifi_dc85de828967_68756773616d_managed_psk
        OtherNET                wifi_dc85de828967_38303944616e69656c73_managed_psk
        AnotherOne              wifi_dc85de828967_3257495245363836_managed_wep
        FourthNetwork           wifi_dc85de828967_4d7572706879_managed_wep
        AnOpenNetwork           wifi_dc85de828967_4d6568657272696e_managed_none

要连接到公开的网络，使用以 `wifi_` 开头的第二个参数:

    $ connmanctl connect wifi_dc85de828967_4d6568657272696e_managed_none

提示： 网络名称可以用 tab 补全。

你现在应该已经连上网络了，使用 `connmanctl state` 或 `ip addr` 来检查。

#### 连接到受保护的接入点

你需要提供更多的信息，起码是密码或者密码短语，给 ConnMan 守护程序来连接受保护的接入点。

这一节的命令展示了如何在交互模式执行 `connmanctl`，只有交互模式下才能使用 `agent` 命令。要开启交互模式，只需要输入：

    $ connmanctl

接下来的操作和之前的类似，首先扫描所有的 Wi-Fi technologies：

    connmanctl> scan wifi

列出服务：

    connmanctl> services

现在你需要注册一个 agent 来处理用户请求，命令是：

    connmanctl> agent on

现在连接到受收保护的服务，使用 tab 补全来输入 wifi_ 服务，比如要连接到上面例子中的 OtherNET， 输入：

    connmanctl> connect wifi_dc85de828967_38303944616e69656c73_managed_psk

Agent 会向你询问守护进程连接到网路需要的一切信息，这些信息会依据与你要连接的网络类型的不同而变化。 Agent 也会像下面一样显示有关信息的额外数据：

    Agent RequestInput wifi_dc85de828967_38303944616e69656c73_managed_psk
      Passphrase = [ Type=psk, Requirement=mandatory ]
      Passphrase?

提供要求的信息，在这个例子里是密码短语，然后输入：

    connmanctl> quit

如果你提供的信息正确，那么你应该已经连接到受保护的接入点了。

#### 使用 iwd 代替 wpa_supplicant

ConnMan 可以使用 iwd 连接无线网络。Community 中提供的的软件包已经支持使用 iwd 来连接无线网络。因为只要 connman 找到 wpa_supplicant 就会启动它，这里建议卸载 wpa_supplicant。

目前 iwd 的 `-i` 选项似乎会导致 connman 无法找到 Wi-Fi 接口。

创建下面两个服务文件，可以让 connman 无论是否安装了wpa_supplicant，都一律使用 iwd 来连接无线网络。

    /etc/systemd/system/iwd.service

    [Unit]
    Description=Internet Wireless Daemon (IWD)
    Before=network.target
    Wants=network.target

    [Service]
    ExecStart=/usr/lib/iwd/iwd

    [Install]
    Alias=multi-user.target.wants/iwd.service

    /etc/systemd/system/connman_iwd.service

    [Unit]
    Description=Connection service
    DefaultDependencies=false
    Conflicts=shutdown.target
    RequiresMountsFor=/var/lib/connman
    After=dbus.service network-pre.target systemd-sysusers.service iwd.service
    Before=network.target multi-user.target shutdown.target
    Wants=network.target
    Requires=iwd.service

    [Service]
    Type=dbus
    BusName=net.connman
    Restart=on-failure
    ExecStart=/usr/bin/connmand --wifi=iwd_agent -n
    StandardOutput=null
    CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_TIME CAP_SYS_MODULE
    ProtectHome=true
    ProtectSystem=true

    [Install]
    WantedBy=multi-user.target

然后启用/开始 `connman_iwd` 服务。

使用 iwd 代替 wpa_supplicant 的好处是：ping 时间似乎会更加一致，并且连接会更加可靠。

### 设置

对于用户经常连接的网络，ConnMan 会自动创建设置与配置文件。这些文件包括了密码短语、essid 和其他信息。配置文件存放在 `/var/lib/connman/` 内，以服务为名的文件夹下。要查看所有的网络配置文件，在 root shell 内执行：

    # cat /var/lib/connman/*/settings

注意： VPN 设置存放在 `/var/lib/connman-vpn/`。

### Technologies

ConnMan 将各种硬件接口称为 Technologies。

要列出所有可用的 Technologies，执行：

    $ connmanctl technologies

只列出 Technologies 类型的名字，可以使用这一行命令：

    $ connmanctl technologies | awk '/Type/ { print $NF }'

注意： 字段 `Type = tech_name` 里的“tech_name”，就是 `connmanctl` 命令所使用的 technology 类型

要与这些接口交互，必须使用 technology 的类型。要开启或关闭 Technologies 可以用：

    $ connmanctl enable technology_type

与：

    $ connmanctl disable technology_type

比如要关闭 wifi：

    $ connmanctl disable wifi

警告： connman 会监听 rfkill 事件。使用 connman 时，尽管硬件锁可能可以正常工作，但基本无法使用 `rfkill` 或 `bluetoothctl` 来开关设备。 [2] 请使用 `connmanctl enable|disable`

## 提示与技巧

### 避免改变 hostname

ConnMan 默认会更改临时 hostname。与 X authority 一起使用时会有问题：如果用旧的 hostname 生成了 xauth magic coookie 之后，ConnMan 改变了你的 hostname，那么将无法创建新的窗口，会显示诸如 `No protocol specified` 和 `Can't open display: :0.0` 的错误。手动重置 hostname 可以解决这个问题，但根本的解决办法是从一开始就防止 ConnMan 改变你的 hostname。把下面的配置加入 `/etc/connman/main.conf` 即可：

    [General]
    AllowHostnameUpdates=false

改变这个文件后记得重启 `connman.service`。

要测试的话，建议一边观察 systemd 日志，一边插拔几次网线接口。

### 有线网络与无线网络共存时，优先使用有线网络

ConnMan 默认不会优先使用有线网络，这会导致 ConnMan 即使在可以使用有线网络时，也只使用慢速的无线网络。你可以将下面的配置加入 `/etc/connman/main.conf`，让 ConnMan 优先使用有线网络。

    [General]
    PreferredTechnologies=ethernet,wifi

### 互斥连接

ConnMan 允许你同时连接有线与无线网络。这样允许程序在通过 wifi 建立了连接后，再连接到有线网络，通过 wifi 建立的连接也不会中断。但有些人更喜欢同一时间只使用一种网络，将下面的配置加入 `/etc/connman/main.conf` 可以实现这一点：

    [General]
    SingleConnectedTechnology=true

### 连接到 eduroam (802.1X)

在连接到诸如 eduroam 的 WPA2 企业模式网络之前，需要建立单独的配置文件。 比如，创建 `/var/lib/connman/eduroam.config`：

    eduroam.config

    [service_eduroam]
    Type=wifi
    Name=eduroam
    EAP=peap
    CACertFile=/etc/ssl/certs/certificate.cer
    Phase2=MSCHAPV2
    Identity=user@foo.edu
    AnonymousIdentity=anonymous@foo.edu
    Passphrase=password

重启 `wpa_supplicant.service` 和 `connman.service` 来连接到新网络上。

注意：

- 选项是大小写敏感的，比如应该用 `EAP = ttls` 而不是 `EAP = TTLS`。[3]
- 请向提供 eduroam 网络的机构咨询各种设置，比如用户名、密码、`EAP`、`Phase2output`和需要的凭证。

更多信息请参考 connman-service.config(5) 和 Wireless network configuration (简体中文)#eduroam.

### 避免与本地 DNS 服务冲突

如果你在运行本地的 DNS 服务，在安装了 ConnMan 之后，你很可能会遇到 53 端口（TCP 和/或 UDP）被占用的问题。这是因为 ConnMan 内置的 DNS 代理也会尝试绑定 53 端口。如果你看到了来自 BIND 或 dnsmasq 的日志诸如：

    named[529]: could not listen on UDP socket: address in use

就是这个问题引起的。要确认是哪个应用占用了 53 端口，可以以 root 身份执行 `ss -tulpn`。

要修复这个问题，可以修改 systemd 服务文件，以 `-r` 或 `--nodnsproxy` 选项启动 connmand。 创建文件夹 `/etc/systemd/system/connman.service.d/` 并新增文件 `disable_dns_proxy.conf`：

    /etc/systemd/system/connman.service.d/disable_dns_proxy.conf

    [Service]
    ExecStart=
    ExecStart=/usr/bin/connmand -n --nodnsproxy

确保在新增此文件后 reload systemd 守护程序，并 restart `connman.service` 和你的 DNS 代理。

### /etc/resolv.conf

如果你既想知道从 DHCP 获得的 DNS 服务器地址，同时又想保留自定义的 `/etc/resolv.conf`，那么就在上面的文件里追加 `RuntimeDirectory=connman`（如果不需要 `ExecStart` ，就去掉 ExecStart 行）。这样 connman 就会把从 DHCP 获得的 DNS 服务器地址写入 `/var/run/connman/resolv.conf`。

记得在增加这个文件之后重载 systemd 守护程序，并重启 `connman.service`和你的 DNS 代理。

### 屏蔽接口

如果有 Docker (简体中文) 之类的的程序创建了虚拟接口，当网络连接中断时，ConnMan 可能会尝试连接这些虚拟接口，而不是真实的硬件接口。简单的解决办法是将你不想要 ConnMan 连接的接口加入黑名单。 ConnMan 默认会屏蔽以 `vmnet`、`vboxnet`、`virbr` 与 `ifb` 开头的接口，所以配置新的黑名单时也要加入这些接口。

屏蔽接口还可以避免竞态条件：在 systemd/udev 改变接口名称到形如 `enp4s0` 的可预测的网络接口名称之前，connman 可能就会去连接接口。屏蔽惯用（且不可预测）的接口前缀可以让 connman 在接口重命名之后再连接。

把下面的配置加入 `/etc/connman/main.conf`（如果不存在就创建这个文件）：

    [General]
    NetworkInterfaceBlacklist=vmnet,vboxnet,virbr,ifb,docker,veth,eth,wlan

重启 `connman.service` 之后，在 Econnman 这样的 GUI 工具中，所有形如 `veth#######` 的接口也都会被隐藏。

## 疑难杂症

### Error /net/connman/technology/wifi: Not supported

目前，connman 不支持用 iwd 扫描 Wi-Fi 网络，这个功能暂时只能由 `wpa_supplicant` 提供（参考 [4]）。要用 iwd连接 wifi，enable 并 start `iwd.service`，然后参考 Iwd 中的指示，或者使用#前端的其中之一。为了让 connman 能扫描 Wi-Fi，安装 wpa_supplicant 软件包，并在停用 `iwd.service` 之后重启`connman.service`。

### Error /net/connman/technology/wifi: No carrier

在你使用这条命令启用 wifi 后：

    $ connmanctl enable wifi

如果扫描无线网络时产生了这条错误，这可能是因为一个未解决的 Bug。[5][失效链接 2022-09-17 ⓘ] 如果在满足了这些条件后还未解决，请在禁用其他网络管理器，并重启系统之后再尝试。

也可能仅仅是因为无线接口被 rfkill 关闭了，重启 wpa_supplicant 时有可能会这样。使用 `rfkill list` 来检查。

### "Not registered", or "Method "Connect" with signature ... doesn't exist"

在执行命令时你可能会看到这样的错误：

来自 `connmanctl` 提示符：

    connmanctl> connect service_id

    Error /net/connman/service/SSID: Method "Connect" with signature "" on interface "net.connman.Service" doesn't exist

来自终端：

    # connmanctl connect service_id

    Error /net/connman/service/service_id: Not registered

这些错误是由于没有运行 agent。在 `connmanctl` 提示符里执行 `agent on` 来启动 agent，然后再试一试。

### Error Failed to set hostname/domainname

Connman 可能会因没有 `CAP_SYS_ADMIN` 而无法设置 hostanme 或 domainname。

你需要编辑 `connman.service`（以及其他类似的文件，如 `connman-vpn.service`）来修改 `CapabilityBoundingSet` 行，增加 `CAP_SYS_ADMIN`。

更多细节请参考 `EPERM` 下的 sethostname(2) § ERRORS 或 setdomainname(2) § ERRORS。

### 连接时出现未知路由

每次连接完成后，日志中可能出现未知的路由，比如：

    ...
    connmand[473]: wlp2s0 {add} route 82.165.8.211 gw 10.20.30.4 scope 0 <UNIVERSE>
    connmand[473]: wlp2s0 {del} route 82.165.8.211 gw 10.20.30.4 scope 0 <UNIVERSE>
    ...

这可能是由于 ConnMan 在通过检查与 ipv4.connman.net 的连接，来测试网络（在本例里，`82.165.8.211` 就是 ipv4.connman.net 被解析后的 IP地址）。[6][失效链接 2022-09-17 ⓘ] 详细信息，包括 ConnMan 为什么要这么做，以及 ConnMan 除了连接 IP 还传递了什么信息，请参考 ConnMan README。

该行为可以通过在 `/etc/connman/main.conf` 中增加下面的配置来阻止：

    [General]
    EnableOnlineCheck=false

这项配置也会导致默认设备状态不会从 READY 切换到 ONLINE。connman.conf(5) 但网络连接是正常的。

也可以用防火墙规则阻止连接检查，这不会影响正常的网络连接（除非有 captive portal）：

    # ip6tables -A OUTPUT -d ipv6.connman.net -j REJECT
    # iptables -A OUTPUT -d ipv4.connman.net,ipv6.connman.net -j REJECT

### File /proc/net/pnp doesn't exist

如果你在错误日志中看到了这个，这是由 connman 的 bug 引起的 [7]，可以无视。Bug Report[失效链接 2022-09-17 ⓘ]

## 另请参见

- Git 仓库文档 —— 更多细节文档

Category:

- Network managers (简体中文)

Hidden category:

- Pages with dead links