如何优雅地在 Linux 上开启 WiFi 热点
在 Linux 下创建 WiFi 热点 (Access Point),自古以来都不是一件容易的事情。
常见的解决方案有三种,hostapd、NetworkManager 和 systemd-networkd。
前两种方案用的比较多,而 systemd 近些年才在服务器中流行起来,文档和教程相对而言比较少。
一般而言,使用 NetworkManager 可以获得“开箱即用”的体验——但只能说勉强能用,存在的问题也很多。比如,5GHz 往往不能工作、不能指定频宽等等……
hostapd 则提供了许多配置项,但代价是配置非常复杂。好在有一些现成的配置文件和脚本可以参考,比如USB-WiFi、create_ap、linux-wifi-hotspot 和 linux-router。
使用 5GHz 频段
网上的教程一般只涉及 2.4GHz 的配置。一开始,我以为只需要把 802.11n 改成 802.11ac,再调整一下频段就可以了。然而,现实却狠狠地打了我的脸:
1 | 2月 26 14:45:16 armbian wpa_supplicant[1107]: nl80211: Added 802.11b mode based on 802.11g information |
看起来是指定了网卡不支持的频段!使用 iw list 查看一下支持的频段:
1 | ❯ sudo iw list |
好家伙,几乎所有的 5GHz 信道都被标记了 no IR (no-initiating-radiation),也就是无法使用!
根据 Arch Linux wiki 的说法,每个国家都有着不同的限制,因此我们可以通过设置国家代码来规避这种限制:
1 | ❯ sudo iw reg get |
怎么回事?为什么国家代码的设置没有生效?就在我一筹莫展时,我无意间发现了这个issue。
按照 issue 中的 workaround,将 regulatory.db
链接到 /lib/firmware/regulatory.db-upstream
后,出乎意料的可以工作了:
1 | ❯ dmesg | grep -i cfg80211 |
开启 80MHz 频宽
一通操作猛如虎,一测速度二百五。
按照linux-router中的教程,只需要指定 ssid 和 password 就可以开启热点:
1 | sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 --wifi5 |
这样虽然能开启热点,但尴尬的是它的频宽只有 20MHz,并且握手速度只有 54Mbps(还不如直接去用 802.11n 呢)
在中国,52-68 信道被划为 DFS 信道,而 96-144 信道则不允许使用。参考:List_of_WLAN_channels
使用 DFS 信道时,按照法规要求,启动时应先检测附近是否有雷达信号,在使用过程中如果检测到了雷达信号也必须进行规避。这会导致热点启动延迟,并带来诸多难以排查的奇怪问题。反正尽量别用就对了!
更重要的是,我的网卡在 DFS 信道上的发射功率远低于其他信道。因此,我们将使用其他信道。尝试指定 149 信道并启用 80MHz 频宽:
1 | sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 -c 149 --country CN --wifi5 --req-vht --vht-ch-width 1 |
不出意外的话,这时 hostapd 会输出一长串日志,告诉你启动失败了:
1 | ctrl_interface_group=0 |
它告诉我们没有指定中心频率(vht_oper_centr_freq_seg0_idx
):
1 | DFS chan_idx seems wrong; num-ch: 25 ch-no: -6 conf-ch-no: 149 11n: 0 sec-ch: 0 vht-oper-width: 1 |
查看配置文件,可以看到我们确实没有指定 vht_oper_centr_freq_seg0_idx
:
1 | ❯ sudo cat /dev/shm/lnxrouter_tmp/lnxrouter.wlan0.conf*/hostapd.conf |
对于 80MHz 频宽,vht_oper_centr_freq_seg0_idx
的值一般是 channel
+6。然而,lnxrouter 并没有提供指定 眼瞎了,可以通过 vht_oper_centr_freq_seg0_idx
的选项,我采用了一个比较 dirty 的方法——直接修改 lnxrouter 的脚本文件:--vht-seg0-ch
参数指定
再次执行脚本,hostapd 会出现新的报错:
1 | DFS 0 channels required radar detection |
这是由于我们没有设置合适的 ht_capab
或 vht_capab
导致的。
参考hostapd-WiFi5.conf,添加合适的 capability 到 lnxrouter 中:
1 | sudo lnxrouter --ap wlan0 <ssid> -p <password> --freq-band 5 -c 149 --country CN --ieee80211n --ieee80211ac --ht-capab "[HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]" --vht-capab "[MAX-MPDU-11454][SHORT-GI-80][TX-STBC-2BY1][SU-BEAMFORMEE][HTC-VHT]" --vht-ch-width 1 |
Tips:
ht_capab
和vht_capab
的值取决于驱动程序,不同的驱动程序支持的参数可能不同。对于 rtw88 驱动,上述的 capability 应该可以正常工作。
Tips:
我并不清楚这些 capability 的作用,于是我让 GPT 解释了一下:802.11n 功能:
HT40+
和HT40-
:支持 40 MHz 信道宽度。+
或-
表示 AP 使用 40 MHz 信道的上/下 20 MHz 部分。40 MHz 信道比 20 MHz 吞吐量更高。SHORT-GI-20
:启用 20 MHz 信道的短保护间隔(SGI)。保护间隔是符号间的静默时间,用于避免信号重叠。短保护间隔减少静默时间,提升信道效率。SHORT-GI-40
:同上,但适用于 40 MHz 信道,可减少开销并提升吞吐量。GF
(Greenfield 模式):启用 纯 802.11n 模式(不兼容传统非 HT 设备)。此模式通过放弃向后兼容性来提高效率(现代网络较少使用)。MAX-AMSDU-7935
:
设置 最大聚合 MAC 服务数据单元(AMSDU)大小,允许 AP 发送更大的数据包以减少开销。802.11ac 功能:
SHORT-GI-80
:启用 80 MHz 信道的短保护间隔,减少静默时间以提升吞吐量。MAX-MPDU-11454
:设置 最大 MPDU(MAC 协议数据单元)大小,更大的 MPDU 可提升效率。TX-STBC-2BY1
:启用 发射端空时块编码(STBC),通过多天线提升多径环境下的信号稳定性。RX-STBC-1
:启用 接收端 STBC(支持单空间流)。SU-BEAMFORMEE
:支持 单用户波束成形,AP 将信号定向传输至特定设备,提升信号质量与覆盖范围。MU-BEAMFORMEE
:支持 多用户波束成形,AP 可同时定向传输至多个设备。HTC-VHT
:
支持 802.11ac 的 高吞吐量控制信道模式。
不出意外的话,此时热点已经工作在 80MHz 的频宽下,并且握手速度也应该达到 433/866Mbps。
后记
在 Linux 下创建 AP 确实不是一件容易的事。如果不是特殊需求,使用 OpenWrt 这种为无线专门优化过的发行版,可能会是更好的选择。