From 821ca7d4cc96722c9ec297b99a64b1d3f26e9fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Sun, 11 Apr 2021 19:43:39 +0200 Subject: [PATCH] nixos/nginx: add option rejectSSL exposing ssl_reject_handshake --- .../services/web-servers/nginx/default.nix | 38 ++++++++++++------- .../web-servers/nginx/vhost-options.nix | 12 ++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 0e99aabcfc0..ebb3c38d6c2 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -230,13 +230,13 @@ let defaultListen = if vhost.listen != [] then vhost.listen - else ((optionals hasSSL ( - singleton { addr = "0.0.0.0"; port = 443; ssl = true; } - ++ optional enableIPv6 { addr = "[::]"; port = 443; ssl = true; } - )) ++ optionals (!onlySSL) ( - singleton { addr = "0.0.0.0"; port = 80; ssl = false; } - ++ optional enableIPv6 { addr = "[::]"; port = 80; ssl = false; } - )); + else optionals (hasSSL || vhost.rejectSSL) ( + singleton { addr = "0.0.0.0"; port = 443; ssl = true; } + ++ optional enableIPv6 { addr = "[::]"; port = 443; ssl = true; } + ) ++ optionals (!onlySSL) ( + singleton { addr = "0.0.0.0"; port = 80; ssl = false; } + ++ optional enableIPv6 { addr = "[::]"; port = 80; ssl = false; } + ); hostListen = if vhost.forceSSL @@ -303,6 +303,9 @@ let ${optionalString (hasSSL && vhost.sslTrustedCertificate != null) '' ssl_trusted_certificate ${vhost.sslTrustedCertificate}; ''} + ${optionalString vhost.rejectSSL '' + ssl_reject_handshake on; + ''} ${mkBasicAuth vhostName vhost} @@ -771,20 +774,27 @@ in } { - assertion = all (conf: with conf; - !(addSSL && (onlySSL || enableSSL)) && - !(forceSSL && (onlySSL || enableSSL)) && - !(addSSL && forceSSL) + assertion = all (host: with host; + count id [ addSSL (onlySSL || enableSSL) forceSSL rejectSSL ] <= 1 ) (attrValues virtualHosts); message = '' Options services.nginx.service.virtualHosts..addSSL, - services.nginx.virtualHosts..onlySSL and services.nginx.virtualHosts..forceSSL - are mutually exclusive. + services.nginx.virtualHosts..onlySSL, + services.nginx.virtualHosts..forceSSL and + services.nginx.virtualHosts..rejectSSL are mutually exclusive. + ''; + } + + { + assertion = any (host: host.rejectSSL) (attrValues virtualHosts) -> versionAtLeast cfg.package.version "1.19.4"; + message = '' + services.nginx.virtualHosts..rejectSSL requires nginx version + 1.19.4 or above; see the documentation for services.nginx.package. ''; } { - assertion = all (conf: !(conf.enableACME && conf.useACMEHost != null)) (attrValues virtualHosts); + assertion = all (host: !(host.enableACME && host.useACMEHost != null)) (attrValues virtualHosts); message = '' Options services.nginx.service.virtualHosts..enableACME and services.nginx.virtualHosts..useACMEHost are mutually exclusive. diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index 1f5fe6a368c..1c7d4024479 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -118,6 +118,18 @@ with lib; ''; }; + rejectSSL = mkOption { + type = types.bool; + default = false; + description = '' + Whether to listen for and reject all HTTPS connections to this vhost. Useful in + default + server blocks to avoid serving the certificate for another vhost. Uses the + ssl_reject_handshake directive available in nginx versions + 1.19.4 and above. + ''; + }; + sslCertificate = mkOption { type = types.path; example = "/var/host.cert";