WIFI无线网络之无线监管域(国家码)

什么是 Wi-Fi 无线监管域(国家码)?

Wi-Fi 国家码,也称为无线监管域,是一个由两个字母组成的代码,用于标识设备所在的国家或地区。这个代码至关重要,因为它决定了 Wi-Fi 设备在哪个频段信道发射功率限制下运行。

为什么需要国家码?
世界各地的无线电频谱管理法规不同。例如:

  • 2.4 GHz 频段:在大多数国家,信道 1-11 是通用的,但在日本,还可以使用信道 12, 13, 14。
  • 5 GHz 频段:不同国家开放的信道差别更大。例如,美国允许使用信道 36-165,而中国在早期只允许使用 149-165 等信道。此外,一些信道需要支持 DFS(动态频率选择)和 TPC(发射功率控制)以避免干扰雷达等系统。
  • 6 GHz 频段:这是最新的 Wi-Fi 频段,各国的开放进度和规则也各不相同。

因此,设置正确的国家码是为了确保您的 Wi-Fi 设备合法、安全地运行,并且能够解锁该地区允许的所有信道和功能,从而获得最佳性能并避免干扰。

Linux下的无线监管域管理

我们通过将合规性纳入cfg80211中,使其成为新无线驱动程序所使用的部分,从而确保Linux内核的合规管理得到妥善落实。我们在用户空间维护着一套全面且灵活的监管数据库,并提供中央监管域代理(CRDA)这一用户空间代理工具。当检测到需要更新时,该代理可被触发,以刷新内核无线核心模块中针对特定国家/地区的法规权限定义。将数据库置于用户空间,使发行版无需升级内核即可轻松推送更新。此外,数据库以二进制形式分发,采用专为节省空间而设计的二进制文件格式;同时,它还内置了一组RSA数字签名,或支持从预配置目录中读取这些签名。一旦系统检测到监管区域变更(例如,通过识别带有国家信息的接入点),内核便会向CRDA请求新区域的法规权限,进而强制各驱动程序遵照执行。

架构

整个架构如下:
crda.webp

注: 从内核 v4.15 版本开始,由于提交 007f6c5e6eb45 (“cfg80211: 支持将监管数据库加载为固件文件”) 添加了 支持使用内核的固件请求 API,该 API 在 /lib/firmware 上查找固件。

组件

监管基础设施包括三个主要组成部分:

  • 内核80211协议栈部分
  • CRDA-用户空间代理
  • wireless-regdb-无线监管数据库

CRDA:

CRDA(Central Regulatory Domain Agent) 是我们的用户空间代理,将监管域上传到内核,它作为 udev 辅助程序。它依赖于nl80211进行通信。CRDA 仅设计为通过内核的udev通信运行。用户通常不需要手动运行它,除非在调试udev问题时。

https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/crda.git/

wireless-regdb:

wireless-regdb 是用于 CRDA 的无线监管数据库

https://git.kernel.org/pub/scm/linux/kernel/git/wens/wireless-regdb.git/

安装管理组件

安装 CRDA 和无线监管数据库:

# Debian/Ubuntu
sudo apt install crda wireless-regdb

修改默认国家码:
编辑 /etc/default/crda 文件(如果不存在则创建):

sudo nano /etc/default/crda

添加或修改以下行:

REGDOMAIN=US

查看当前国家码

使用 iw reg get 命令查看当前的国家码:

iw reg get

输出示例 1(已正确设置):

global
country US: DFS-FCC
    (2402 - 2472 @ 40), (N/A, 30), (N/A)
    (5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
    (5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
    (5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
    (5735 - 5835 @ 80), (N/A, 30), (N/A)
    (57240 - 71000 @ 2160), (N/A, 40), (N/A)

这里显示国家码是 US(美国),并列出了该国允许的频段、信道带宽、发射功率等规则。

输出示例 2(默认设置,通常是 00):

global
country 00: DFS-UNSET
    (2402 - 2472 @ 40), (N/A, 20), (N/A)
    (2457 - 2482 @ 20), (N/A, 20), (N/A), PASSIVE-SCAN
    (2474 - 2494 @ 20), (N/A, 20), (N/A), NO-OFDM, PASSIVE-SCAN
    (5170 - 5250 @ 80), (N/A, 20), (N/A), PASSIVE-SCAN
    ...

country 00DFS-UNSET 表示没有设置特定的国家码,此时设备通常会使用一个限制最严格的通用配置,这可能导致很多信道(尤其是 5GHz)无法使用。

执行流程:

  1. iw 工具通过 netlink 协议族 (AF_NETLINK) 和 nl80211 套接字与内核通信
  2. 内核的 cfg80211 子系统接收 NL80211_CMD_GET_REG 请求
  3. cfg80211 返回当前设置的监管域信息
  4. 信息经过解析后显示给用户

设置国家码

设置国家码也有临时和永久两种方法。

临时设置(重启后失效)

使用 iw 命令可以立即更改监管域。

# 将国家码设置为中国
sudo iw reg set CN

重要提示:执行此命令后,你需要重新启动 Wi-Fi重新加载相应的驱动模块,才能使新的国家码规则生效。

设置完成后,务必再次运行 iw reg get 来确认更改已生效。

内核交互流程:

  1. 用户命令执行

    iw reg set US
  2. Netlink 通信

    • iw 创建 AF_NETLINK 套接字,类型为 NETLINK_GENERIC
    • 发送 NL80211_CMD_SET_REG 消息,包含国家码 “US”
  3. 内核处理(cfg80211)

    • 接收并验证国家码有效性
    • 检查权限(需要 CAP_NET_ADMIN 权限)
    • 更新全局监管域设置:regulatory->country_code = "US"
  4. 驱动通知

    • cfg80211 调用 regulatory_hint() 函数
    • 通知所有已注册的无线驱动更新硬件设置
    • 驱动根据新的国家码限制信道和功率
  5. 接口重新配置

永久设置

为了让国家码在每次启动时都自动设置,你需要修改系统配置。方法有多种:

方法 1:使用 cfg80211 内核参数

对于稍微高版本的内核,可以直接通过grub启动参数来或设置模块参数来传递国家码。

b) 通过grub启动参数
编辑 /etc/default/grub 文件,
GRUB_CMDLINE_LINUX_DEFAULT 行中添加 cfg80211.ieee80211_regdom=<country_code>

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash cfg80211.ieee80211_regdom=US"

注:不同系统可能具体细节不一样,添加对应grub启动参数即可

然后更新 GRUB 配置并重启。

# 对于 Debian/Ubuntu
sudo update-grub 
sudo reboot

b) 通过设置模块参数

sudo nano /etc/modprobe.d/cfg80211.conf

添加:

options cfg80211 ieee80211_regdom=US

方法 2:通过 wpa_supplicant 设置

如果使用wpa_supplicant,则只需要在其配置文件中添加一行内容即可,类似于:

COUNTRY=US

它可以在连接时设置国家码。
由于 Network Manager 使用 wpa_supplicant,所以使用 NetworkManager 也是类似。

参考