diff options
| author | rnhmjoj <rnhmjoj@inventati.org> | 2022-01-11 22:01:32 +0100 |
|---|---|---|
| committer | Jonathan Ringer <jonringer@users.noreply.github.com> | 2022-02-09 21:15:53 -0800 |
| commit | 841700a6a744dbc460ccd1661163b35a6af33693 (patch) | |
| tree | e2776784d8ded110f01135f2b49392e772acd26d | |
| parent | nixos/wireless: enable PMF by default (diff) | |
| download | nixpkgs-841700a6a744dbc460ccd1661163b35a6af33693.tar.gz | |
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.
(cherry picked from commit 2eed89bbe1fd431079b6c824bbcb66a92d3bff7c)
| -rw-r--r-- | nixos/modules/services/networking/wpa_supplicant.nix | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index cf227f096a5d..7d18163a17f8 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -9,9 +9,35 @@ let cfg = config.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}" @@ -33,7 +59,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; @@ -43,7 +69,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") @@ -175,6 +201,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; |
