Skip to content

Image nginx: 1.25.4-alpine3.18 does not have support for HTTPS enabled, and after container startup, an error message is reported using HTTP 3 #867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chenxudong2020 opened this issue Feb 21, 2024 · 6 comments

Comments

@chenxudong2020
Copy link

chenxudong2020 commented Feb 21, 2024

Describe the bug

Image nginx: 1.25.4-alpine3.18
does not have support for HTTPS enabled,
and after container startup, an error message is reported using HTTP 3

My configuration file is as follows:
server {
listen $HTTP_PORT default_server;
listen [::]:$HTTP_PORT default_server;
server_name localhost;
index index.php index.html index.htm index.nginx-debian.html;
root /web;
}
server {
listen $HTTPS_PORT ssl default_server;
listen $HTTPS_PORT http3 reuseport default_server;
listen [::]:$HTTPS_PORT ssl default_server;
listen [::]:$HTTPS_PORT http3 reuseport default_server;
http2 on;
ssl_certificate /cert/$SSL_PUBLIC;
ssl_certificate_key /cert/$SSL_KEY;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
add_header Alt-Svc 'quic=":$HTTPS_PORT"; h3-27=":$HTTPS_PORT";h3-25=":$HTTPS_PORT"; h3-T050=":$HTTPS_PORT"; h3-Q050=":$HTTPS_PORT";h3-Q049=":$HTTPS_PORT";h3-Q048=":$HTTPS_PORT"; h3-Q046=":$HTTPS_PORT"; h3-Q043=":$HTTPS_PORT"'; server_name localhost;
index index.php index.html index.htm index.nginx-debian.html;
root /web;
error_page 400 = /400.html;

    location ~ \\.php$ {
        
    }

    location $TUNNEL_PATH {
        proxy_redirect off;
        proxy_pass http://$OVERTLS_HOST:$OVERTLS_PORT;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$http_host;
    }
}

Error reported after running:
2024/02/21 09:06:23 [emerg] 12#12: invalid parameter "http3" in /etc/nginx/conf.d/overtls.conf:10

To reproduce

Steps to reproduce the behavior:

Expected behavior

A clear and concise description of what you expected to happen.

Your environment

  • Version/release of Docker and method of installation (e.g. Docker Desktop / Docker Server)
  • Version/tag of the NGINX Docker image (e.g. nginx:alpine)
  • Target deployment platform (e.g. OpenShift / Kubernetes / Docker Compose / etc...)

Additional context

Add any other context about the problem here.

@thresheek
Copy link
Member

Hi @chenxudong2020!

There is no http3 parameter for the listen directive. You probably want quic instead: http://nginx.org/en/docs/http/ngx_http_v3_module.html

@DJviolin
Copy link

For some reason, http3 also not working for me in my compose project. I'm assuming the error is in my settings, but even when I try a very minimal setup with defaults, always http2 version returning. This haunting me for 2 days already.

@DJviolin
Copy link

My Nginx settings:

nginx.conf:

user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 1024000;
error_log /dev/stderr crit;
pid /run/nginx.pid;
daemon off;
pcre_jit on;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    charset UTF-8;
    access_log /dev/stdout combined;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 75s;
    keepalive_disable none;
    keepalive_requests 4096;

    client_max_body_size 20M;

    http2 on;
    quic_retry on;
    quic_gso on;
    map $http3 $alt_svc_value {
        default '';
        'h3' 'h3=":$server_port"; ma=86400';
    }
    add_header Alt-Svc $alt_svc_value;

    ssl_session_timeout 1h;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.3;
    ssl_early_data on;
    proxy_set_header Early-Data $ssl_early_data;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    proxy_buffering on;
    proxy_cache_path /var/cache/nginx
        levels=1:2
        use_temp_path=off
        keys_zone=mycache:10m
        inactive=24h
        max_size=1g
    ;
    proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
    proxy_cache_valid 200 302 24h;
    proxy_cache_valid 404      1m;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_background_update on;
    proxy_cache_lock on;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-available/*.conf;
}

Server file:

server {
    listen [::]:443 quic reuseport;
    listen 443 quic reuseport;
    listen [::]:443 ssl deferred reuseport;
    listen 443 ssl deferred reuseport;

    server_name docker.test;

    ssl_certificate /run/secrets/ssl_certificate;
    ssl_certificate_key /run/secrets/ssl_certificate_key;

    # ...

    location /benchmark_json {
        default_type application/json;
        return 200 '{"status": "ok", "message": "Service is up and running"}';
    }
}

In Docker Compose, I exposing Nginx ports like this:

ports:
  - 80:80
  - 443:443/udp
  - 443:443/tcp

@thresheek
Copy link
Member

@DJviolin, browsers can be picky about enabling http3 - I'd suggest testing with cli tools like curl.

@DJviolin
Copy link

DJviolin commented Feb 21, 2024

It works with curl, but not with latest Firefox and Edge. I'm absolutely exhausted, why it's not working... Can be an issue with the local certificate? I created it with this command:

$ docker run -it --rm -v "./secrets/:/secrets/" alpine/openssl:latest req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /secrets/docker.test.key -out /secrets/docker.test.crt -subj "/C=HU/ST=Pest/L=Budapest/O=Docker Compose Company/CN=docker.test"

Here is the curl output for HTTP3 request:

HTTP/3 200
date: Wed, 21 Feb 2024 18:20:06 GMT
content-type: application/json
content-length: 56
content-security-policy: upgrade-insecure-requests
permissions-policy: autoplay=(), camera=(), microphone=()
referrer-policy: strict-origin-when-cross-origin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
alt-svc: h3=":443"; ma=86400
x-protocol: HTTP/3.0
strict-transport-security: max-age=63072000; includeSubDomains; preload

I tried the minimal http block from the nginx docs with this certs and still the same. Curl returns http3, but the browsers only http2.

@DJviolin
Copy link

DJviolin commented Mar 6, 2024

The problem was caused by the browser's strict policy about locally signed certificates and certificate authorities with HTTP3/QUIC. Longer explanation can be found here why the browsers doing this:

This is because non-official TLS certificates are often used by companies to decrypt their employees’ TLS traffic (so that they can, for example, have their firewalls scan inside encrypted traffic). However, if companies would start doing that with QUIC, we would again have custom middlebox implementations that make their own assumptions about the protocol. This could lead to them potentially breaking protocol support in the future, which is exactly what we tried to prevent by encrypting QUIC so extensively in the first place! As such, Chrome takes a very opinionated stance on this: If you’re not using an official TLS certificate (signed by a certificate authority or root certificate that is trusted by Chrome, such as Let’s Encrypt), then you cannot use QUIC. This, sadly, also includes self-signed certificates, which are often used for local test set-ups.

How to whitelist your localhost domains in the browsers can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants