cloudflare / quiche

🥧 Savoury implementation of the QUIC transport protocol and HTTP/3
https://docs.quic.tech/quiche/
BSD 2-Clause "Simplified" License
9.3k stars 700 forks source link

NGINX server doenst establish HTTP3 connection #709

Closed Samy432 closed 3 years ago

Samy432 commented 3 years ago

Im using macOS Catalina Version 10.15.7

nginx version: nginx/1.16.1 (quiche-c2703b3) built by clang 11.0.3 (clang-1103.0.32.62) built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL) TLS SNI support enabled configure arguments: --prefix=/Users/samy/NGINX-New/nginx-1.16.1 --build=quiche-c2703b3 --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-openssl=../quiche/deps/boringssl --with-quiche=../quiche

Nginx Conf file: http { server {

Enable QUIC and HTTP/3.

    listen 443 quic reuseport;

    # Enable HTTP/2 (optional).
listen 443 ssl http2;

    ssl_certificate      cert.pem;
    ssl_certificate_key  key.pem;

    # Enable all TLS versions (TLSv1.3 is required for QUIC).
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

    # Request buffering in not currently supported for HTTP/3.
    proxy_request_buffering off;

    # Add Alt-Svc header to negotiate HTTP/3.
    add_header alt-svc 'h3-29=":443"; ma=86400';

}

}

When i start the nginx server, and try to fetch the page from GOOGLE CHROME CANARY(with enable quic flag and quic-version=h3-29 set), it still goes through HTTP2 and not HTTP3.

If i comment out listen 443 ssl http2(To enable HTTP/2), i get Connection refused in the browser. With curl it returns, HTTP/2 200 server: nginx/1.16.1 date: Tue, 10 Nov 2020 02:32:54 GMT content-type: text/html content-length: 608 last-modified: Mon, 09 Nov 2020 21:43:41 GMT etag: "5fa9b80d-260" alt-svc: h3-29=":443"; ma=86400 accept-ranges: bytes

LPardue commented 3 years ago

Chrome can be fussy about the certificates. Are you using certs from a publicly trusted CA?

There's several possible variable, can you try with a different HTTP/3 client such as quiche-client with trace logging?

Samy432 commented 3 years ago

It is a selfsigned certificate for localhost generated with openssl. The certificate is trusted and added into the keychain. I have attached the logs with quiche client.It times out after 30s. log.txt

LPardue commented 3 years ago

From the client log, you're not getting anything back from the server. I think you'll need to gather some server-side logs.

Samy432 commented 3 years ago

The access log from nginx has these when invoked from the browser. There is no entry while i invoke from the quiche client 127.0.0.1 - - [10/Nov/2020:11:26:04 -0500] "GET / HTTP/2.0" 200 608 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4320.0 Safari/537.36"

Whereas, in error log entry for browser and for quiche client:

2020/11/10 11:25:16 [error] 62729#0: *27 open() "/Users/sam/nginx-1.16.1/html/favicon.ico" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /favicon.ico HTTP/2.0", host: "localhost", referrer: "https://localhost/"

2020/11/10 11:25:49 [notice] 62850#0: signal process started

Samy432 commented 3 years ago

I still wondering why its not establishing a http3 connection. Chrome canary might be concerned about the self signed certificate. But the quiche client and curl(http3 enabled) doesn’t respond. What would be the reason?

sam@sam mac objs % /usr/local/opt/curl/bin/curl --http3 -I https://localhost:443 ^C sam@sam mac objs % /usr/local/opt/curl/bin/curl -I https://localhost:443 HTTP/2 200 server: nginx/1.16.1 date: Wed, 11 Nov 2020 13:45:12 GMT content-type: text/html content-length: 608 last-modified: Mon, 09 Nov 2020 21:43:41 GMT etag: "5fa9b80d-260" alt-svc: h3-29=":443"; ma=86400 accept-ranges: bytes

LPardue commented 3 years ago

Can you gather some debug level logs? General instructions for nginx are here https://nginx.org/en/docs/debugging_log.html

Once nginx is buils with debugging (--with-debug), to gather quiche-level logs in nginx.conf, put error_log logs/error.log debug; on toplevel (not inside http { }).

Samy432 commented 3 years ago

I have gathered the debug logs with quiche client, Google Canary and Firefox nightly. Due to SSL error it falls back to http2. I imported the certificate in Firefox Nightly. Even then it goes to http2. debug_Google Canary.log debug_with quiche client.log debug_firefox nightly.log

LPardue commented 3 years ago

Your quiche client logs indicates that it tried to use HTTP/2. That is not possible. Can you please try with the quiche-client tool.

Samy432 commented 3 years ago

Yeah.It contains the logs when used with Google CAnany as well.

Here is the log with quiche client. I could see no connection is established between the quiche client and nginx server. It just times out after 30seconds. I have attached the trace logs from the quiche client also. debug.log log.txt

junhochoi commented 3 years ago

From the logs, looks like no response from the server. Can you check your network is not filtering udp/443, or ports configured in nginx. A packet capture on the server side will help to show the udp packet is actually delivered to the server.

Samy432 commented 3 years ago

The port 443 is not filtered. The firewall is turned off too. I too a wireshark capture for it.

I also changed the port in the nginx server configuration to 4433. Surprisingly, quiche client reports TLS fail. I have attached the debug log, client log and packet capture for port 4433 as well.

client -log.txt trace_port443.pcapng.zip trace_port4433.pcapng.zip debug.log

junhochoi commented 3 years ago

From the logs port 4433 looks fine. you need to add --no-verify in quiche-client if you are using a self signed certificate. If there is no filtering in the network, I think there is some other daemon listening on udp:443

Samy432 commented 3 years ago

I can run with --no-verify in quiche client. But i want to fetch the content through a browser with HTTP3 support. In the configuration of Nginx sever, if i get rid of "listen 443 ssl http2" , i cant fetch any content in the browser.

LPardue commented 3 years ago

The errors suggest that your certificate is not fully trusted and/or your server is not receiving traffic on UDP port 443. Both of those are going to prevent a browser from working but aren't problems with quiche itself. So unless you have alternative information I don't know what more can be said.

Samy432 commented 3 years ago

Okay. Now, I run my nginx server in port 443. I have a few questions,

  1. Is there any way to generate a self signed certificate(for localhost) which works on a browser?
  2. Since localhost didnt work for me, I tried with Lets encrypt too. I have a certificate generated by lets encrypt for a Linux machine which runs nginx. I still need --no-verify in quiche client or else i get TLS error. Is this the expected behavior? I thought Lets encrypt certificates will work fine without the use of --no-verify. Also it doesn’t work with Browser too.
  3. Can the content from quiche server be fetched from the browser too?
Samy432 commented 3 years ago

Finally it worked! thanks @LPardue and @junhochoi for your suggestions.