Zhi Wei 的个人博客
记录一次折腾WIFI漫游的过程
记录一次折腾WIFI漫游的过程

记录一次折腾WIFI漫游的过程

自己撸的小工具升级以后,我的X86 OpenWRT终于做下线的准备了,替换它的是小米AC2100。这款路由器是我2019年购买的,一直给X86当作AP使用,机缘巧合之下我又获得一款号称WIFI6的路由器,又将AC2100替换下来,之后便一直放在储物间中。

时过境迁,路由器已经变得花里胡哨起来,什么MESH自组网,全屋覆盖之类的技术宣传的铺天盖地,价格也是蹭蹭的往上涨。技术都是一样的名字,可是却互相不兼容。终于我在咸鱼上闲逛的时候,大数据给我推送了小米AC2100,50包邮到家,于是便有了替换X86,实现WIFI自动漫游这篇文章。

前置知识

技术摘要

在开始折腾之前,需要了解相关技术文档中提到的技术名称和其实现的功能,否则在调试的过程中往往会手足无措,或者弄巧成拙。

802.11系列协议
802.11k向客户端提供接口报告网络中AP的信息,帮助客户端选择最佳AP
802.11vAP主动通知客户端设备有关网络的信息,包括漫游建议等信息
802.11r减少客户端在无线网络不同接入点之间切换漫游时的延迟
802.11sMESH网络,定义了MESH网络的框架和操作,包括节点间的通信和路由
802.11ac/ax使用ac协议一般称为WIFI5,ax则为WIFI6

ax/ac都支持160Mhz的带宽,但是ac是使用两个80MHz组成的一个160Mhz(ac wave2),这种方式只能最多只能链接一个客户端,且需要客户端网卡支持该协议。

WIFI信道

途中蓝色部分为中国地区可用的WIFI信道,WIFI信道实际就是无线电波的频段,灰色部分因为有其他比如飞机,特种设备之类的使用,所以不开放公众使用。有的时候即使你指定了某个WIFI信道,但实际上无线工作的信道和你指定信道也有可能并不一样,这是因为DFS(Dynamic Frequency Selection),DFS会自动探测这些非民用的无线电信号,并且自动避开。在选择可用的WIFI信道的时候,需要避开或者选择同频段信号较少的信道,这样有助于增强WIFI信号的质量。

信号值dBm

客户端接收到的信号(RSSI)强度,用单位dBm表示,这个数值通常是一个负值。比如-40dBm和-45dBm,因为-40 > -45,所以前者的信号更好。在OpenWRT中,AP属性中有一个字段叫做噪音(noise level)表示当前AP收到干扰程度,这个数值越小说明当前信道的干扰越小,信号质量越好。

单位强度描述(WIFI5场景)
-30dBm强到可怕把设备直接放在天线旁边
-50dBm很强信号非常不错,玩游戏看4K电影是足够的。
-65dBm优秀此信号强度对于网络电话和流媒体视频的使用是足够的。
-70dBm一般对于网页冲浪和收发邮件的使用是足够的。
-80dBm较差实现基本连接,但数据包传输不稳定。
-90dBm非常差你将会经常看到类似转圈圈的标志。

最为对比,我将我的IPAD AIR放在AC2100边上,测得的数据为:信号 -32dBm,噪声 -89dBm,信噪比 -57dBm。

AC2100的参数

刷入OpenWRT固件

首先将原厂固件降级至漏洞版本,然后通过URL注入开启SSH,将OpenWRT固件传入/tmp目录下,使用mtd命令写入。网络上有大量教程可以参考,这里给出OpenWRT官方发布的方法。https://openwrt.org/toh/xiaomi/mi_router_ac2100

漏洞固件刷写成功以后,登录并修改管理员密码,注销后重新登录获取当前的stok值,注意不要关闭当前网页。在新窗口中请求下面的URL。

#开启SSH
http://192.168.31.1/cgi-bin/luci/;stok=【替换】/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20nvram%20set%20ssh_en%3D1%3B%20nvram%20commit%3B%20sed%20-i%20's%2Fchannel%3D.*%2Fchannel%3D%5C%22debug%5C%22%2Fg'%20%2Fetc%2Finit.d%2Fdropbear%3B%20%2Fetc%2Finit.d%2Fdropbear%20start%3B

#修改admin密码
http://192.168.31.1/cgi-bin/luci/;stok=【替换】/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20echo%20-e%20'admin%5Cnadmin'%20%7C%20passwd%20root%3B

开启SSH以后,使用root账户进行登录,密码为admin。这里会有一个问题,就是高版本的SSH连接低版本的SSH客户端会提示鉴权失败,需要修改使用下面的命令进行SSH链接。我使用SCP命令将固件发送到路由器上,所以也要修改sshd_config配置。

#高版本连接低版本ssh 使用ssh-ras加密方式
ssh -oHostKeyAlgorithms=+ssh-rsa root@192.168.31.1
#高版本sshd_conf 添加加密方式
HostKeyAlgorithms +ssh-rsa,ssh-dss
#写入固件
mtd write /tmp/openwrt-23.05.3-ramips-mt7621-xiaomi_mi-router-ac2100-squashfs-kernel1.bin kernel1
mtd -r write /tmp/openwrt-23.05.3-ramips-mt7621-xiaomi_mi-router-ac2100-squashfs-rootfs0.bin rootfs0

下面是固件资源,点击可下载

配置OpenWRT

在咸鱼上淘了2个AC2100回来以后,我一共拥有三个,分别命名为R1、R2、R3。其中R1是我原有的,R2、R3是咸鱼回来的。R1作为出口路由,配置有一个LAN子网192.168.0.0,提供DHCP服务。设置R2、R3仅提供无线接入点,不提供路由和NAT服务,在我的网络中,我将其看成一个linux终端,而并非路由器,有点类似带网口的AP面板。

容错配置

将网线插入R2的1号网口(OpenWRT中命名为LAN3),登录OpenWRT在【网络】-【接口】-【设备】中修改br-lan桥接的端口,只保留1号网口(LAN3)。这样做可以避免配置错误无法访问路由。然后修改R2的【接口】中修改默认子网LAN地址,避免冲突(因为我的R1子网段和OpenWRT默认的1段并不冲突,所以可以跳过)。

桥接端口

在【设备】中创建一个网桥命名为SWITCH,将WAN、LAN1、LAN2桥接在一起,其他设置保持默认即可。回到【接口】中将WAN6关闭,修改WAN桥接至SWITCH。这里可以创建一个新的防火墙区域(有颜色好看),也可以跳过。添加防火墙策略,允许22和80的分组通过。

这里只是R2本身关闭了IPV6,不影响R1子网中的IPV6DHCP,任何连接到R2的无线客户端,相当于直接连接到了R1的子网,由R1提供DNS和DHCP4/6以及网关服务。

更新wpad包

现在可以将R1的子网接入R2的WAN接口,使R2可以访问互联网。从R2的WAN区域登录R2(即R1的子网中),更新wpad包以支持802.11k/v/r,固件中已经存在的wpad包为精简版本,只支持802.11r,需要删除并且重新安装完整版本,我这里选择了wpad-wolfssl包。参考:https://openwrt.org/docs/guide-user/network/wifi/mesh/80211s

  • wpad-mesh-openssl(精简版以节省空间)
  • wpad-openssl (完整大版本)
  • wpad-mesh-wolfssl(精简版以节省空间)
  • wpad-wolfssl (完整大版本)
  • wpad-mesh-mbedtls(精简版以节省空间)
  • wpad-mbedtls(完整大版本)
  • wpad-basic-*版本仅支持802.11r802.11w
  • wpad-mesh-*版本仅支持802.11r/w802.11s
  • wpad-*完整版本wpad支持802.11k/v/r/w802.11s
  • 完整意味着wpad没有修剪任何内容来减小其尺寸。
opkg update
opkg remove wpad-mini
opkg remove wpad-basic
opkg remove wpad-basic-wolfssl
opkg remove wpad-basic-openssl
opkg remove wpad-basic-mbedtls
opkg install wpad-wolfssl

安装dawn服务

dawn服务是一个“Decentralized Wifi Controller”,可以理解为AC控制器,管理网络中的无线AP,提高漫游以及WIFI性能,特别是当你有很多个AP接入点的时候。其中有很多高级功能,如果需要对其进行更加精细的配置可以参考:https://github.com/berlin-open-wireless-lab/DAWN/blob/master/CONFIGURE.md。这里是dawn的安装方法:https://openwrt.org/docs/guide-user/network/wifi/dawn

opkg update
opkg install dawn luci-app-dawn
#修改配置 
nano /etc/config/dawn
#config network
#	option broadcast_ip '192.168.0.255' #广播地址用来发现ap
#	option broadcast_port '1025'  #端口
#	option network_option '0' #配置0使用udp广播 默认2使用tcp
/etc/init.d/dawn restart #重启服务
reboot

广播地址类似于群发消息,目标是子网中的所有地址,因为R2的WAN口已经桥接在SWITCH上了,所以R2本身也是R1子网中的成员。所以当R1/R3发送广播的时候,R2就会收到dawn数据包。

dawn重启成功后,将R2重启。重启完成重新登录web在顶部就会出现dawn菜单,注意:不要忘记打在防火墙上打开UDP1025端口!参考上文桥接端口小节。

到这里相对于对R2完成了初始化,然后按照上面的方法重复一遍配置R3,然后就可以开始配置无线接入点了。

配置接入点AP

进入【网络】-【无线】中配置radio1(5G),默认已经有一个SSID叫做OpenWRT的配置,修改国家代码(可以筛掉无法使用的信道),选择一个占用比较少的信道,可以使用OpenWRT的信道分析功能查看。设置带宽为80Mhz,发送功率为20dBm(略微降低该值,可以鼓励客户端更主动切换AP)。将网络绑定为SWITCH,在无线安全中选择加密方式为WPA2-PSK,算法自动。MAC过滤和高级设置默认不做修改。

重点在于WLAN漫游菜单,根据dawn的使用说明,需要在无线配置文件中写入bss_transition ‘1’、ieee80211k ‘1’字段。其中ieee80211k就是802.11k协议,bss_transition就是802.11v协议。因为ieee80211v字段已经被移除了,详细配置说明可以参考https://openwrt.org/docs/guide-user/network/wifi/basic,其中就包括了kvr协议的详细配置。

回到luci配置中来,打开802.11r快速切换,NAS ID不填写,移动域不填写,默认为SSID的首字母的HEX表示方法,而不是f457,(启动后可以在/var/run/hostapd-phy*.conf文件中查看https://forum.openwrt.org/t/any-way-to-monitor-if-802-11r-is-working/73504/38)。如果你的SSID全部一致则没有必要修改此参数。重关联截止时间修改为思科推荐的20000,FT协议选择FT over the air,勾选本地生成PMK、802.11k RRM(ieee80211k)、BSS 过渡(bss_transition)选项,其他保持默认。

按照以上步骤配置R3,设置R3的防火墙、dawn服务、以及无线接入点配置,与R2保持一致。开启R2、R3的无线接入点,在LUCI的dawn菜单中查看AP接入点详情。这里dawn已经发现了R1子网中存在的两个无线热点。

测试验证

漫游802.11r

在R1上开启iperf3服务端,ipad使用iperf3客户端进行网速测试,同时在R1上对ipad进行ping大包测试,size设置为20000。我在书房和卧室之间来回走动进行测试,中间需要穿过客厅。为了能准确定位问题,暂时没有对R1配置无线接入点。

测试结果还是令人满意的,我一共来回走动了3次,其中最后一次,在R2和R3信号都相对比较弱的客厅做了停留,所以导致了丢包,但是iperf很快便又有了速度,应该是dawn配置还需要调优,加上我的R1还没有开启WIFI。

通过编辑无线配置文件来开启syslog,也可以观察FT的工作情况。在LUCI的【状态】-【系统日志】中查看,也可以使用logread命令在shell中查看。

nano /etc/config/wireless
#config wifi-device 'radio1'
#       option type 'mac80211'
#      option path '1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0'
#      option channel '157'
#      option band '5g'
#      option htmode 'VHT80'
#      option country 'CN'
#      option cell_density '0'
#      option txpower '19'
      option log_level '1'  #启用日志
#日志中出现下列字段 表示FT工作正常
#IEEE 802.11: authentication OK (FT)
#WPA: FT authentication already completed - do not start 4-way handshake
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed IEEE 802.11: binding station to interface 'phy1-ap0'
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed IEEE 802.11: authentication OK (FT)
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed MLME: MLME-AUTHENTICATE.indication(aa:54:fc:4b:fc:ed, FT)
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed IEEE 802.11: association OK (aid 1)
Sun Jun  2 15:46:37 2024 daemon.info hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed IEEE 802.11: associated (aid 1)
Sun Jun  2 15:46:37 2024 daemon.notice hostapd: phy1-ap0: AP-STA-CONNECTED aa:54:fc:4b:fc:ed auth_alg=ft
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed MLME: MLME-REASSOCIATE.indication(aa:54:fc:4b:fc:ed)
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed IEEE 802.11: binding station to interface 'phy1-ap0'
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed WPA: event 6 notification
Sun Jun  2 15:46:37 2024 daemon.debug hostapd: phy1-ap0: STA aa:54:fc:4b:fc:ed WPA: FT authentication already completed - do not start 4-way handshake

DAWN配置

在测试中,就目前的效果就已经可以满足我的日常使用了,所以不再对dawn进行精细调整,如果需要调整可以在https://github.com/berlin-open-wireless-lab/DAWN/blob/master/CONFIGURE.md找到详细的配置方法,简单询问了GPT他给了我这些建议:

channel_utilization:启用信道利用率检测,以帮助选择最佳的接入点。

rssi_val:设置RSSI阈值,低于此值的客户端将被重新分配到更好的接入点。

chan_util_checkclient_check:启用信道利用率和客户端检查。

确保所有AP的SSID和安全设置(例如加密类型和密码)一致,这样可以保证客户端可以在不同的AP之间无缝漫游。根据实际环境调整rssi_val(RSSI阈值),确保客户端可以及时切换到信号更强的AP。设置DAWN的日志级别和监控机制,以便及时发现和解决问题。可以将log_level设置为更高的值(如 23)以获得更多调试信息。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注