由于之前买的中兴路由器没有办法完全关掉 DHCP 服务器,所以如果 x86 重启,它就会启动自己的 DHCP 服务器,自作主张为客户端分配另一个网段(192.168.5.x)的 IP ;即使 x86 重启之后 DHCP 服务器重新上线,由于 DHCP lease 的刷新时间还没到,客户端们不会询问新的 IP ;而中兴自己则在上游 DHCP 恢复之后抛下客户端们不管了、自己以 10.x.x.x 的 IP 重新回到下级路由的位置,直接导致网烂掉。
为了改善体验,在网上冲浪一番之后决定让中兴退休,x86 把这活也揽过来(真正的 All-in-One )。于是需要挑选能够做 AP 的无线网卡,并且对 x86 上的 Archlinux 进行配置来完成这个任务。
硬件
兼职路由器,很多极客前辈们都是用的 openwrt 。恩山论坛的这个帖子是我的起点: [openwrt(x86)] 2024-4-18—官方源码—史上最全驱动—支持无线AP模式—openwrt x86-64 23.05.3版 。
根据帖主的建议,第一张卡我没有买高通的,只是买了一个便宜大份的 MT7921E。需要注意的是, QCA9882 、 MT7921 等都是芯片,整个网卡还需要其他电路才能成型;MT7921E 我的是 AzureWave 的 AW-XB468NF ; QCA9882 则是拆机件 COMPEX 的 WLE600VX 7AA。由于 AW-XB468NF 设计之初是为了做客户端的,所以做 AP 有各种各样的问题,特别是PS5会断连,所以在使用了一段时间之后我买了2张 WLE600VX 7AA 分别发射 2.4GHz 和 5GHz 。两个卡的区别简单总结如下1:
支持的特性 | AW-XB468NF(MT7921) | WLE600VX 7AA(QCA9882) |
---|---|---|
WiFi协议 | 最高 802.11ax | 最高 802.11ac wave 1 |
频宽 | 80mhz(理论上支持160,没试过) | 80mhz |
DFS/ACS | 不支持 | 支持 |
最高握手速率(5) | 1201 Mbps | 867 Mbps |
最高握手速率(2.4) | 574 Mbps | 600 Mbps |
通道 | 2T2R | 2T2R |
双频双待(DBDC) | 不支持 | 不支持 |
接口 | NGFF M.2 | Mini PCIe |
对于小白来说这些参数都很陌生,毕竟无线电也是一个很大的学科。根据这段时间的摸索,有以下的一些经验之谈:
- 两个卡都不支持DBDC,意味着一张卡只能发射 2.4 GHz 或者 5 GHz 其中之一,不能同时发射两个频段。像普通的路由器能够同时发射两个频段的,都是有两个甚至更多的芯片才能做到的;如果真能买到这样的网卡的话,通常会表现为内置两个 radio ,在系统里也会显示成两个 dev
- 2T2R 代表着网卡上有两个天线接口,所以转接板需要买至少有两根天线的;比如 WLE900VX 是3T3R 的,就是有三个接口,就需要买三天线的转接板了
- DFS 是很重要的,因为没有 DFS 的 MT7921 会无法扫描附近的军事、气象雷达占用了哪些频段,直接导致 5GHz 的低位频段被禁用;没有 DFS 也就同时不会有 ACS,虽然手动指定频道也不麻烦,但是毕竟能自动就自动
- WLE600VX 的 Mini PCIe 转接主板的全尺寸 PCIe 接口那是真的难买;相比之下 NGFF M.2 就随便一搜一堆
软件
(前置准备 - 配置网桥、网卡设备名)
无论是 MT7621 还是 QCA9882,现在的 Linux 内核都有内置驱动,即插即用。
为了不重复劳动,所以需要把所有的 Lan 网卡都接入一个虚拟网桥(bridge),然后在这个 bridge 上运行 DHCP 服务器、提供其他服务。这部分我们用 systemd-networkd 搞定,在/etc/systemd/network/
里面搞几个文件:
1
2
3
4
5
# 25-br0.netdev
# 这个文件是创建 br0 网桥的
[NetDev]
Name=br0
Kind=bridge
1
2
3
4
5
6
7
8
9
# 25-br0.network
# 这个文件是用来配置 br0 的 IP 段的
# 并且让 systemd 生成对应的 ip 包 routing、nat 规则
[Match]
Name=br0
[Network]
Address=10.0.0.1/16
IPMasquerade=ipv4
配置好这些文件之后,再去/etc/udev/rules.d/
写个文件固定一下无线网卡们的名字,按照 MAC 地址命名为 netwlan0、netwlan1等名字方便记忆(address后面那一串就是mac地址,用ip a
来确认自己的网卡的mac替换进去):
1
2
3
# 10-network.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="04:f0:21:aa:bb:cc", NAME="netwlan1"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="04:f0:21:xx:yy:zz", NAME="netwlan2"
搞定之后重启,这样才能让udev规则生效。
(前置准备 - 安装、配置dnsmasq)
DHCP服务器部分,我们用 dnsmasq 来负责。关键的配置文件如下:
1
2
3
4
5
6
7
# 注意监听的是 br0 网桥,不是监听无线网卡
interface=br0
bind-interfaces
# 配置 DHCP 地址池、子网掩码、租期
dhcp-range=10.0.0.2,10.0.0.200,255.255.0.0,12h
# 配置下发的 DNS 服务器
dhcp-option=6,10.0.0.1
此外还需要改一下 dnsmasq 的 systemd 服务文件,使用systemctl edit dnsmasq
,填入如下内容:
1
2
3
[Service]
# 确保 br0 已经 UP 了,也就是至少有一个 Lan 网卡接入了使得 br0 有IP 地址 10.0.0.1 了,才开启 DHCP;否则会fail
ExecStartPre=timeout 60s bash -c 'until ip a s dev br0; do sleep 1; done'
(安装、配置 hostapd)
安装了之后,首先也是对 hostapd 的 systemd 服务文件进行更改;由于我们有好几个网卡,所以用的是 hostapd@.service 而不是 hostapd.service。使用 systemctl edit 'hostapd@.service'
,注意命令中的单引号,是为了防止shell理解错误:
1
2
3
4
[Unit]
# 等待 br0 设备存在了,才启动 hostapd
# 因为我们要用 hostapd 把所管理的无线网卡绑定到 br0 去
After=sys-subsystem-net-devices-br0.device
然后用 ip a
确定一下无线网卡的名字们,前面的 udev 规则正确的话现在就应该是 netwlan+数字 这样的名字了。接下来需要解决的问题是:谁是谁?特别是两张卡的 feature 很相似时,就会导致很难用iw list
来区分。其实很简单:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ ip a
3: netwlan2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP group default qlen 1000
link/ether 04:f0:21:xx:yy:zz brd ff:ff:ff:ff:ff:ff
altname wlp4s0
4: netwlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP group default qlen 1000
link/ether 04:f0:21:aa:bb:cc brd ff:ff:ff:ff:ff:ff
altname wlp5s0
$ iw netwlan1 info
Interface netwlan1
ifindex 4
wdev 0x100000001
addr 04:f0:21:aa:bb:cc
wiphy 1
$ iw netwlan2 info
Interface netwlan2
ifindex 3
wdev 0x1
addr 04:f0:21:xx:yy:zz
wiphy 0
iw命令的输出里面 addr 跟 ip命令的 link/ether
后面的是对应的,但是我们更关注的是 iw命令输出的 wiphy
,根据这个数字就能够确认 netwlan1和2 分别对应 iw list
的输出里面的哪个设备了;而 hostapd 配置文件里面的 ht_capab
和 vht_capab
正是根据 iw list
输出的 feature 列表进行配置的。
hostapd 的配置文件包含了非常详尽的解释,接下来的这个示例配置基于 WLE600VX 7AA 这个硬件进行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
interface=netwlan1
# 绑定到 br0 网桥
bridge=br0
# 多数网卡都是用nl80211接口进行管理的,虽然真正的驱动是ath10k或者MT76,所以这里填nl80211
driver=nl80211
# 日志相关配置,可以省略
logger_syslog=0
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
ctrl_interface=/run/hostapd
ctrl_interface_group=0
# 配置显示的WiFi名字
ssid=<WiFi名字>
# 这里设置成1意味着ssid里面如果是"test"那么WiFi名字连双引号都会显示出来
utf8_ssid=1
# 地区码,设置成中国的CN
country_code=CN
# 这个代表的是indoor场景,可以省略
country3=0x49
# 这些标准因为网卡都支持,所以都打开
ieee80211d=1
ieee80211h=1
ieee80211w=1
# 这个卡我们让它负责 5GHz,所以是 802.11ac,模式就是a
hw_mode=a
# 指定频道;如果填0就会让它用ACS自己决定一个
channel=149
# op_class和channel组合在一起就能够确定物理上的频率是多少
# 注意op_class会直接影响频宽,这里设置128对应的是80mhz宽度的那个class;设置成124就会导致工作在40mhz宽度
op_class=128
# 如果channel设置成了0,这里就可以限制ACS自动选择的频道、频率范围
# chanlist=36 40 44 48 149 153 157 161 165
# freqlist=5180,5200,5220,5240,5745,5765,5785,5805,5825
max_num_sta=128
preamble=1
macaddr_acl=0
deny_mac_file=/etc/hostapd/hostapd.deny
wmm_enabled=1
uapsd_advertisement_enabled=1
# 802.11n标准,WiFi 4,又称 HT
ieee80211n=1
ht_capab=[LDPC][HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935][DSSS_CCK-40]
# 802.11ac标准,WiFi 5,又称 VHT
ieee80211ac=1
vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][RX-STBC-1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP3]
# 设置工作频宽,1是80mhz,0是20或40mhz
vht_oper_chwidth=1
# 根据前面的选项组合,80mhz的中心工作频道是155(虽然155本身不是一个channel)
vht_oper_centr_freq_seg0_idx=155
# WiFi密码相关配置,设置成WPA2;注意WPA3也是用wpa=2
wpa=2
wpa_passphrase=<WPA2的密码>
# WPA3的是SAE,WPA2的是PSK,都填上就都支持
wpa_key_mgmt=WPA-PSK SAE
wpa_pairwise=CCMP
sae_password=<WPA3的密码>
channel、op_class、vht_oper_centr_freq_seg0_idx这几个都需要参照IEEE的手册的E-4表格,这里节选一部分:
op_class | 频道起点频率(GHz) | 频道宽度(MHz) | 频道组 | 频道中心频率index |
---|---|---|---|---|
81 | 2.407 | 25 | 1,2,3,4,5,6,7,8,9,10,11,12,13 | - |
83 | 2.407 | 40 | 1,2,3,4,5,6,7,8,9 | - |
84 | 2.407 | 40 | 5,6,7,8,9,10,11,12,13 | - |
115 | 5 | 20 | 36,40,44,48 | - |
116 | 5 | 40 | 36,44 | - |
117 | 5 | 40 | 40,48 | - |
124 | 5 | 20 | 149,153,157,161 | - |
126 | 5 | 40 | 149,157,165 | - |
127 | 5 | 40 | 153,161,169 | - |
128 | 5 | 80 | - | 42,58,106,122,138,155 |
所以对于国内的 5GHz 频段来说,channel设置成149,op_class设置成128,vht_oper_centr_freq_seg0_idx设置成155,就是唯一可用的80mhz频宽频道了。而 2.4GHz 的配置文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
interface=netwlan2
bridge=br0
driver=nl80211
logger_syslog=0
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
ctrl_interface=/run/hostapd
ctrl_interface_group=0
# 配置显示的WiFi名字
ssid=<WiFi名字>
utf8_ssid=1
country_code=CN
country3=0x49
ieee80211d=1
ieee80211h=1
ieee80211w=1
# 注意 g 不代表是 802.11g
# a 指的是 802.11ac或ax,而且是 5G
# 想要发射 2.4G 就要设置成 g
hw_mode=g
# 这里开启ACS,自动选择频道
channel=0
# 这里设置成40mhz的class,至于能不能真开40取决于附近,通常是不能的
op_class=84
# 限制ACS的频道为5-11,因为class 84 包括 12和13 这两个在中国不能用的
chanlist=5-11
max_num_sta=128
preamble=1
macaddr_acl=0
deny_mac_file=/etc/hostapd/hostapd.deny
wmm_enabled=1
uapsd_advertisement_enabled=1
ieee80211n=1
ht_capab=[LDPC][HT40+][HT40-][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935][DSSS_CCK-40]
# 注意,如果是 g 模式,那么 80211ac 相关的选项全部注释掉,否则即使这里的capab配置都是正确的,驱动会报错
# ieee80211ac=1
# vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][RX-STBC-1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP3]
# vht_oper_chwidth=1
# vht_oper_centr_freq_seg0_idx=155
# WiFi密码相关配置,设置成WPA2;注意WPA3也是用wpa=2
wpa=2
wpa_passphrase=<WPA2的密码>
# WPA3的是SAE,WPA2的是PSK,都填上就都支持
wpa_key_mgmt=WPA-PSK SAE
wpa_pairwise=CCMP
sae_password=<WPA3的密码>
假设配置文件控制 netwlan1 的保存成 /etc/hostapd/netwlan1.conf
,netwlan2 的则是 /etc/hostapd/netwlan2.conf
,那么执行以下命令启动 hostapd 以及 dnsmasq :
1
2
3
systemctl enable --now hostapd@wlan1 hostapd@wlan2
# 等能够搜索到所配置的WiFi信号之后
systemctl enable --now dnsmasq
附上iw list
输出的该网卡信息:
iw
-
资料来源:Shoutwiki、COMPEX官网以及手册 ↩