问题背景:
设备:IPC Camera,其wifi支持80211.bgn协议,支持WPA,WPA2安全协议。 路由器:2.4G和5G双频WIFI,支持WPA+WPA2,WPA2, WPA2+WPA3安全协议。
~ # wpa_cli -i wlan0wpa_cli v2.9Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributorsInteractive mode<3>CTRL-EVENT-SCAN-STARTED<3>CTRL-EVENT-SCAN-RESULTS<3>CTRL-EVENT-SSID-REENABLED id=0 ssid="your-ssid"<3>SME: Trying to authenticate with 2c:3a:fd:2c:fa:97 (SSID='your-ssid' freq=2437 MHz)<3>Trying to associate with 2c:3a:fd:2c:fa:97 (SSID='your-ssid' freq=2437 MHz)<3>Associated with 2c:3a:fd:2c:fa:97<3>CTRL-EVENT-SUBNET-STATUS-UPDATE status=0<4>WPA: Failed to configure IGTK to the driver # 可以看到此处是在配置IGTK时报错,<3>RSN: Failed to configure IGTK # 可以看到此处是在配置IGTK时报错,<3>CTRL-EVENT-DISCONNECTED bssid=2c:3a:fd:2c:fa:97 reason=1 locally_generated=1<3>CTRL-EVENT-SSID-TEMP-DISABLED id=0 ssid="your-ssid" auth_failures=3 duration=46 reason=CONN_FAILED<3>CTRL-EVENT-SCAN-STARTED<3>CTRL-EVENT-SCAN-RESULTS
分析步骤:
根据log报错信息可知,wifi的认证(authenticate )和关联(associated)步骤都是成功的,设置IGTK步骤失败了。百度一下IGTK是个什么东西。

IGTK也就是管理帧加密策略,那不就是ieee80211w协议支持的mfp(Management Frame Protection)功能嘛,因为设备中是应用通过wpa_cli工具进行配网的,所以/etc/wpa_supplicant.conf文件中没有具体网络信息,使用save_config命令导出配置进行确认。
> save_configOK>q~ # cat /etc/wpa_supplicant.confctrl_interface=/var/run/wpa_supplicantupdate_config=1network={ssid="your-ssid"scan_ssid=1psk="your-psk"key_mgmt=WPA-PSK WPA-EAP IEEE8021X WPA-PSK-SHA256 WPA-EAP-SHA256ieee80211w=1 # 这里设置为1,开启了mfp功能}
果然,network中配置了ieee80211w=1,设备开启了mfp功能。因为路由器支持WPA3,所以路由器肯定支持mfp(WPA3需要强制开启mfp,WPA2可选择是否开启), 那就是可能是设备不支持mfp。尝试关掉ieee80211w试一下。
> set_network 0 ieee80211w 0OK> reconnectOK<3>CTRL-EVENT-SCAN-STARTED<3>CTRL-EVENT-SCAN-RESULTS<3>CTRL-EVENT-SSID-REENABLED id=0 ssid="your-ssid"<3>SME: Trying to authenticate with 2c:3a:fd:2c:fa:97 (SSID='your-ssid' freq=2412 MHz)<3>Trying to associate with 2c:3a:fd:2c:fa:97 (SSID='your-ssid' freq=2412 MHz)<3>Associated with 2c:3a:fd:2c:fa:97<3>CTRL-EVENT-SUBNET-STATUS-UPDATE status=0<3>WPA: Key negotiation completed with 2c:3a:fd:2c:fa:97 [PTK=CCMP GTK=CCMP]<3>CTRL-EVENT-CONNECTED - Connection to 2c:3a:fd:2c:fa:97 completed [id=0 id_str=]<3>WPA: Group rekeying completed with 2c:3a:fd:2c:fa:97 [GTK=CCMP]
果然,关掉mfp后设备就能够正常联网了,那就证明确实是因为设备不支持mfp。所以最终解决方案就是去掉ieee80211w=1?
NONONO,同一个平台可能会搭配不同的WIFI模组,并不是所有模组都不支持mfp,在允许的情况下,我们还是需要开启该功能的,毕竟能够提供更强的安全性。所以我们需要想办法让同一套配置兼容两种不同场景,保证不支持mfp的设备能够正常联网,支持mfp的设备开启该功能。
先问问百度吧:

百度AI真牛逼啊,老铁666, 改一把试试。
~ # vi /etc/wpa_supplicant.confctrl_interface=/var/run/wpa_supplicantupdate_config=1network={ssid="your-ssid"scan_ssid=1psk="your-psk"key_mgmt=WPA-PSK WPA-EAP IEEE8021X WPA-PSK-SHA256 WPA-EAP-SHA256mfp=no}
测试一把
~ # wpa_cli -i wlan0Interactive mode> reconfigureFAIL<5>Failed to parse the configuration file '/etc/wpa_supplicant.conf' - exiting> >
What fuck? wpa_supplicant压根不认这个参数,百度你TM在逗我吗?
算了算了,还是重新编译个带debug日志的wpa_suplicant吧。换用带debug日志的wpa_supplicant之后,分别将路由器设置到WPA2模式和WPA2+WPA3兼容模式,对比log看到如下差异。

关键差异如下:
# WPA2模式下, 协商的结果mgmt_group_cipher=0x0,表示不启用mfpwlan0: WPA: AP mgmt_group_cipher 0x20 network profile mgmt_group_cipher 0x0; available mgmt_group_cipher 0x0wlan0: WPA: not using MGMT group cipherWPA: Set own WPA IE default - hexdump(len=22): 30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 80 00RSN: Set own RSNXE default - hexdump(len=0):PSK (set in config) - hexdump(len=32): [REMOVED]WPA: Set PMK based on external data - hexdump(len=32): [REMOVED]# WPA2+WPA3模式下,协商的结果mgmt_group_cipher=0x20,表示启用mfpwlan0: WPA: AP mgmt_group_cipher 0x20 network profile mgmt_group_cipher 0x0; available mgmt_group_cipher 0x20wlan0: WPA: using MGMT group cipher AES-128-CMACWPA: Set own WPA IE default - hexdump(len=28): 30 1a 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 80 00 00 00 00 0f ac 06RSN: Set own RSNXE default - hexdump(len=0):PSK (set in config) - hexdump(len=32): [REMOVED]WPA: Set PMK based on external data - hexdump(len=32): [REMOVED]wlan0: SME: Selected AP supports MFP: require MFP
不同模式下,协商的mfp状态不一样,WPA2+WPA3模式下开启了mfp功能。源码中搜索打印“AP mgmt_group_cipher 0x20 network profile”找到对应函数位置:
root@pc:~/hostap_2_10/wpa_supplicant$ grep -rn "WPA: AP mgmt_group_cipher" .Binary file ./wpa_supplicant matches./wpa_supplicant.c:1312: "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",./events.c:2857: "WPA: AP mgmt_group_cipher 0x%x network mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
打开wpa_supplicant.c的1312行,如下:
void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,struct wpa_ssid *ssid, struct wpa_ie_data *ie){int sel;sel = ie->mgmt_group_cipher;if (ssid->group_mgmt_cipher)sel &= ssid->group_mgmt_cipher;if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||!(ie->capabilities & WPA_CAPABILITY_MFPC))sel = 0;wpa_dbg(wpa_s, MSG_DEBUG,"WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);if (sel & WPA_CIPHER_AES_128_CMAC) {wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;wpa_dbg(wpa_s, MSG_DEBUG,"WPA: using MGMT group cipher AES-128-CMAC");} else if (sel & WPA_CIPHER_BIP_GMAC_128) {wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;wpa_dbg(wpa_s, MSG_DEBUG,"WPA: using MGMT group cipher BIP-GMAC-128");} else if (sel & WPA_CIPHER_BIP_GMAC_256) {wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;wpa_dbg(wpa_s, MSG_DEBUG,"WPA: using MGMT group cipher BIP-GMAC-256");} else if (sel & WPA_CIPHER_BIP_CMAC_256) {wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;wpa_dbg(wpa_s, MSG_DEBUG,"WPA: using MGMT group cipher BIP-CMAC-256");} else {wpa_s->mgmt_group_cipher = 0;wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");}wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,wpa_s->mgmt_group_cipher);wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,}
分析代码可知,也就是wpas_get_ssid_pmf返回的结果不一样,查看wpas_get_ssid_pmf函数实现。
int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid){if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&!(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {/** Driver does not support BIP -- ignore pmf=1 default* since the connection with PMF would fail and the* configuration does not require PMF to be enabled.*/return NO_MGMT_FRAME_PROTECTION;}if (ssid &&(ssid->key_mgmt &~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {/** Do not use the default PMF value for non-RSN networks* since PMF is available only with RSN and pmf=2* configuration would otherwise prevent connections to* all open networks.*/return NO_MGMT_FRAME_PROTECTION;}return wpa_s->conf->pmf;}return ssid->ieee80211w;}
根据代码分析,其基本策略如下:
如果ssid->ieee80211w不等于默认值,即MGMT_FRAME_PROTECTION_DEFAULT时,返回ssid->ieee80211w值。 如果ssid->ieee80211w等于默认值时,需要考虑wpa_s->conf->pmf的情况。 如果wpa_s->conf->pmf为可选(即MGMT_FRAME_PROTECTION_OPTIONAL),且设备不支持BIP加密(即不支持mfp),则不起用mfp功能。 如果ssid->key_mgmt属于非RSN协议,则不起用mfp功能。 否则,返回wpa_s->conf->pmf的值。
所以,最终解决方案也就出来了,只需要如下设置就可以了:
设置ssid->ieee80211w=MGMT_FRAME_PROTECTION_DEFAULT,使用mfp的值。 设置wpa_s->conf->pmf=MGMT_FRAME_PROTECTION_OPTIONAL,根据设备是否支持mfp,选择性开启mfp功能。
具体到配置就是:
pmf=1 #选择性开启mfp功能ctrl_interface=/var/run/wpa_supplicantnetwork={ssid="your-ssid"key_mgmt=WPA-PSKpsk="your-psk"ieee80211w=3 # 即MGMT_FRAME_PROTECTION_DEFAULT,可缺省scan_ssid=1}
OK, 该问题至此圆满结束!


