ConnMan
ConnMan 是一個命令行網絡管理器,為嵌入式設備和快速響應設計。ConnMan 通過插件擴展,但內置了 DHCP 與 NTP 支持。[1]
安裝[編輯 | 編輯原始碼]
安裝 connman包 軟體包。 wpa_supplicant包、bluez包 與 openvpn包 是對應 Wi-Fi、藍牙與 VPN 功能的可選依賴。
在啟用 connman.service
之前,確保禁用所有已安裝的網絡配置。
ConnMan 自帶 connmanctl(1) 命令行界面。各種 #前端也可以使用。
前端[編輯 | 編輯原始碼]
- cmst — ConnMan 的 QT GUI。
- connman-ncurses — ConnMan 的簡單 ncurses UI;沒有實現 ConnMan 的全部功能,但是可以用(有沒有 X 都可以運行),參考 wiki。
- ConnMan-UI — GTK3 客戶端托盤程序。
- connman_dmenu — dmenu 客戶端/前端。
- Econnman — Enlightenment 桌面托盤程序。
- LXQt-Connman-Applet — LXQt 桌面托盤程序。
- connman-gtk — GTK 客戶端。
- 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
你現在應該已經連上網絡了,使用 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
使用 iwd包 代替 wpa_supplicant包 的好處是:ping 時間似乎會更加一致,並且連接會更加可靠。
設置[編輯 | 編輯原始碼]
對於用戶經常連接的網絡,ConnMan 會自動創建設置與配置文件。這些文件包括了密碼短語、essid 和其他信息。配置文件存放在 /var/lib/connman/
內,以服務為名的文件夾下。要查看所有的網絡配置文件,在 root shell 內執行:
# cat /var/lib/connman/*/settings
/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
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 倉庫文檔——更多細節文檔