From 2f5ced6d7c3d1f31305d8c0935a2ff0d3da3d56a Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 9 Jan 2022 12:29:30 +0100 Subject: [PATCH 1/2] nixos/wireless: enable PMF by default Alternative solution to PR #152443. This fixes authentication failures to WPA3 networks (issue #151729) by enabling protected management frames. Note: old client without 802.11w support will still fail. --- nixos/modules/services/networking/wpa_supplicant.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index 07dec8ea7181..29c9d5ca78c2 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -18,6 +18,7 @@ let "ctrl_interface_group=${cfg.userControlled.group}" "update_config=1" ]) + ++ [ "pmf=1" ] ++ optional cfg.scanOnLowSignal ''bgscan="simple:30:-70:3600"'' ++ optional (cfg.extraConfig != "") cfg.extraConfig); From 2eed89bbe1fd431079b6c824bbcb66a92d3bff7c Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Tue, 11 Jan 2022 22:01:32 +0100 Subject: [PATCH 2/2] nixos/wireless: implement opportunistic WPA3 It turns out it's actually possible to fall back to WPA2 in case the authentication fails with WPA3. This was suggested to me in the hostapd mailing list: add another network block with only WPA2 and lower priority, for each network with WPA3. For clients with missing/broken WPA3, wpa_supplicant will: 1. try the network block with higher priority first 2. fail and temporarily disable the network block 3. try the fallback network block and connect This takes a little more time (still <5s) because wpa_supplicant retries a couple times before disabling the network block, but it allows old client to gracefully fall back to WPA2 on mixed WPA2/WPA3 networks. To avoid downgrade attacks, clients with proper WPA3 should disable this; in the future we may want to disable this option by default. --- .../services/networking/wpa_supplicant.nix | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index 29c9d5ca78c2..9989b6df6594 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -10,9 +10,35 @@ let cfg = config.networking.wireless; opt = options.networking.wireless; + wpa3Protocols = [ "SAE" "FT-SAE" ]; + hasWPA3 = opts: !mutuallyExclusive opts.authProtocols wpa3Protocols; + + # Gives a WPA3 network higher priority + increaseWPA3Priority = opts: + opts // optionalAttrs (hasWPA3 opts) + { priority = if opts.priority == null + then 1 + else opts.priority + 1; + }; + + # Creates a WPA2 fallback network + mkWPA2Fallback = opts: + opts // { authProtocols = subtractLists wpa3Protocols opts.authProtocols; }; + + # Networks attrset as a list + networkList = mapAttrsToList (ssid: opts: opts // { inherit ssid; }) + cfg.networks; + + # List of all networks (normal + generated fallbacks) + allNetworks = + if cfg.fallbackToWPA2 + then map increaseWPA3Priority networkList + ++ map mkWPA2Fallback (filter hasWPA3 networkList) + else networkList; + # Content of wpa_supplicant.conf generatedConfig = concatStringsSep "\n" ( - (mapAttrsToList mkNetwork cfg.networks) + (map mkNetwork allNetworks) ++ optional cfg.userControlled.enable (concatStringsSep "\n" [ "ctrl_interface=/run/wpa_supplicant" "ctrl_interface_group=${cfg.userControlled.group}" @@ -34,7 +60,7 @@ let finalConfig = ''"$RUNTIME_DIRECTORY"/wpa_supplicant.conf''; # Creates a network block for wpa_supplicant.conf - mkNetwork = ssid: opts: + mkNetwork = opts: let quote = x: ''"${x}"''; indent = x: " " + x; @@ -44,7 +70,7 @@ let else opts.pskRaw; options = [ - "ssid=${quote ssid}" + "ssid=${quote opts.ssid}" (if pskString != null || opts.auth != null then "key_mgmt=${concatStringsSep " " opts.authProtocols}" else "key_mgmt=NONE") @@ -176,6 +202,18 @@ in { ''; }; + fallbackToWPA2 = mkOption { + type = types.bool; + default = true; + description = '' + Whether to fall back to WPA2 authentication protocols if WPA3 failed. + This allows old wireless cards (that lack recent features required by + WPA3) to connect to mixed WPA2/WPA3 access points. + + To avoid possible downgrade attacks, disable this options. + ''; + }; + environmentFile = mkOption { type = types.nullOr types.path; default = null;