lol

nixos/h2o: enable HTTP/3 via QUIC (#388953)

authored by

Florian Klink and committed by
GitHub
5a2d8c3b 78f33e12

+68 -30
+20 -13
nixos/modules/services/web-servers/h2o/default.nix
··· 221 221 headerSet ++ [ hsts ]; 222 222 } 223 223 ); 224 - in 225 - value.settings 226 - // headerRecAttrs 227 - // { 224 + 228 225 listen = 229 226 let 230 227 identity = ··· 233 230 key-file = "${certs.${names.cert}.directory}/key.pem"; 234 231 certificate-file = "${certs.${names.cert}.directory}/fullchain.pem"; 235 232 }; 233 + 234 + baseListen = 235 + { 236 + port = port.TLS; 237 + ssl = (lib.recursiveUpdate tlsRecAttrs value.tls.extraSettings) // { 238 + inherit identity; 239 + }; 240 + } 241 + // lib.optionalAttrs (value.host != null) { 242 + host = value.host; 243 + }; 244 + 245 + # QUIC, if used, will duplicate the TLS over TCP directive, but 246 + # append some extra QUIC-related settings 247 + quicListen = lib.optional (value.tls.quic != null) (baseListen // { inherit (value.tls) quic; }); 236 248 in 237 249 { 238 - port = port.TLS; 239 - ssl = (lib.recursiveUpdate tlsRecAttrs value.tls.extraSettings) // { 240 - inherit identity; 241 - }; 242 - } 243 - // lib.optionalAttrs (value.host != null) { 244 - host = value.host; 250 + listen = [ baseListen ] ++ quicListen; 245 251 }; 246 - }; 252 + in 253 + value.settings // headerRecAttrs // listen; 247 254 }; 248 255 in 249 256 # With a high likelihood of HTTP & ACME challenges being on the same port, ··· 351 358 "hydra.example.com" = { 352 359 tls = { 353 360 policy = "force"; 354 - indentity = [ 361 + identity = [ 355 362 { 356 363 key-file = "/path/to/key"; 357 364 certificate-file = "/path/to/cert";
+19
nixos/modules/services/web-servers/h2o/vhost-options.nix
··· 152 152 ''; 153 153 }; 154 154 recommendations = tlsRecommendationsOption; 155 + quic = mkOption { 156 + type = types.nullOr types.attrs; 157 + default = null; 158 + description = '' 159 + Enables HTTP/3 over QUIC on the UDP port for TLS. The attrset 160 + provides fine-turning for QUIC behavior, but can be empty. See 161 + <https://h2o.examp1e.net/configure/http3_directives.html#quic-attributes>. 162 + ''; 163 + example = 164 + literalExpression 165 + # nix 166 + '' 167 + { 168 + amp-limit = 2; 169 + handshake-timeout-rtt-multiplier = 300; 170 + retry = "ON"; 171 + } 172 + ''; 173 + }; 155 174 extraSettings = mkOption { 156 175 type = types.attrs; 157 176 default = { };
+27 -13
nixos/tests/web-servers/h2o/basic.nix
··· 43 43 server = 44 44 { pkgs, ... }: 45 45 { 46 + environment.systemPackages = [ 47 + pkgs.curlHTTP3 48 + ]; 49 + 46 50 services.h2o = { 47 51 enable = true; 48 52 defaultHTTPListenPort = port.HTTP; ··· 60 64 "${domain.TLS}" = { 61 65 tls = { 62 66 policy = "force"; 67 + quic = { 68 + retry = "ON"; 69 + }; 63 70 identity = [ 64 71 { 65 72 key-file = ../../common/acme/server/acme.test.key.pem; ··· 99 106 ]; 100 107 101 108 networking = { 102 - firewall.allowedTCPPorts = with port; [ 103 - HTTP 104 - TLS 105 - ]; 109 + firewall = { 110 + allowedTCPPorts = with port; [ 111 + HTTP 112 + TLS 113 + ]; 114 + allowedUDPPorts = with port; [ 115 + TLS 116 + ]; 117 + }; 106 118 extraHosts = '' 107 119 127.0.0.1 ${domain.HTTP} 108 120 127.0.0.1 ${domain.TLS} ··· 110 122 }; 111 123 }; 112 124 }; 113 - 114 125 testScript = 115 126 let 116 127 portStrHTTP = builtins.toString port.HTTP; ··· 122 133 server.wait_for_open_port(${portStrHTTP}) 123 134 server.wait_for_open_port(${portStrTLS}) 124 135 125 - http_hello_world_body = server.succeed("curl --fail-with-body 'http://${domain.HTTP}:${portStrHTTP}/hello_world.txt'") 126 - assert "${sawatdi_chao_lok}" in http_hello_world_body 136 + assert "${sawatdi_chao_lok}" in server.succeed("curl --fail-with-body 'http://${domain.HTTP}:${portStrHTTP}/hello_world.txt'") 127 137 128 138 tls_hello_world_head = server.succeed("curl -v --head --compressed --http2 --tlsv1.3 --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'").lower() 129 139 assert "http/2 200" in tls_hello_world_head 130 140 assert "server: h2o" in tls_hello_world_head 131 141 assert "content-type: text/x-rst" in tls_hello_world_head 132 142 133 - tls_hello_world_body = server.succeed("curl -v --http2 --tlsv1.3 --compressed --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'") 134 - assert "${sawatdi_chao_lok}" in tls_hello_world_body 143 + assert "${sawatdi_chao_lok}" in server.succeed("curl -v --http2 --tlsv1.3 --compressed --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'") 135 144 136 - tls_hello_world_head_redirected = server.succeed("curl -v --head --fail-with-body 'http://${domain.TLS}:${builtins.toString port.HTTP}/hello_world.rst'").lower() 137 - assert "redirected" in tls_hello_world_head_redirected 145 + quic_hello_world_head = server.succeed("curl -v --head --compressed --http3-only --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'").lower() 146 + assert "http/3 200" in quic_hello_world_head 147 + assert "server: h2o" in quic_hello_world_head 148 + assert "content-type: text/x-rst" in quic_hello_world_head 149 + 150 + assert "${sawatdi_chao_lok}" in server.succeed("curl -v --http3-only --compressed --fail-with-body 'https://${domain.TLS}:${portStrTLS}/hello_world.rst'") 151 + 152 + assert "redirected" in server.succeed("curl -v --head --fail-with-body 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'").lower() 138 153 139 154 server.fail("curl --location --max-redirs 0 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'") 140 155 141 - tls_hello_world_body_redirected = server.succeed("curl -v --location --fail-with-body 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'") 142 - assert "${sawatdi_chao_lok}" in tls_hello_world_body_redirected 156 + assert "${sawatdi_chao_lok}" in server.succeed("curl -v --location --fail-with-body 'http://${domain.TLS}:${portStrHTTP}/hello_world.rst'") 143 157 ''; 144 158 }
+2 -4
nixos/tests/web-servers/h2o/mruby.nix
··· 58 58 server.wait_for_unit("h2o.service") 59 59 server.wait_for_open_port(${portStr}) 60 60 61 - hello_world = server.succeed("curl --fail-with-body http://${domain}:${portStr}/hello_world") 62 - assert "${sawatdi_chao_lok}" in hello_world 61 + assert "${sawatdi_chao_lok}" in server.succeed("curl --fail-with-body http://${domain}:${portStr}/hello_world") 63 62 64 - file_handler = server.succeed("curl --fail-with-body http://${domain}:${portStr}/file_handler") 65 - assert "FILE_HANDLER" in file_handler 63 + assert "FILE_HANDLER" in server.succeed("curl --fail-with-body http://${domain}:${portStr}/file_handler") 66 64 ''; 67 65 }