Certbot Nginx method fails: Server is speaking HTTP/2 over HTTP

Hi! I am trying to get a certificate by using the nginx challenge. It is a reverse proxy. It worked for the first 2 domains, but the other ones started to fail.

Good to know; the standalone method does work. So it is not a DNS or network issue, that’s for sure.

The virtual host config that I use for this domain looks like this:
server {
server_name bilbo.realify.dev;

    listen 80 http2;
    listen [::]:80 http2;

    # redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$server_name$request_uri;
}
server {
    server_name bilbo.realify.dev;

    location / {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://xxx.xxx.xxx.xxx:xxxx/;
        client_max_body_size 10M;
    }

    listen 443 ssl http2; // ssl config settings will be added by certbot later on
}

My domain is: bilbo.realify.dev

I ran this command: certbot --nginx -d bilbo.realify.dev

It produced this output:
[…]
Failed authorization procedure. bilbo.realify.dev (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://bilbo.realify.dev/.well-known/acme-challenge/NB6x53gKgPBQL7RUr3CcYPhdyCnwXOC0mW1PlaG3tVw: Server is speaking HTTP/2 over HTTP

IMPORTANT NOTES:

My web server is (include version): Nginx (as a reverse proxy)

The operating system my web server runs on is (include version):
Ubuntu Server 18.04.

I can login to a root shell on my machine (yes or no, or I don’t know):
yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel):
no

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot):
certbot 0.31.0

1 Like

Hi @BjarnBronsveld, welcome to the community forum :wave:

Your problem lies here. HTTP/2 is a protocol over HTTPS and you have it configured for your port 80 server. Instead this server should be speaking HTTP to redirect to the port 443 server listening for ssl http2. You can also see that the problem detail message says similar:

You can fix this by removing the http2 part from each of the listen directives for port 80. You’ll also have to reload the nginx configuration (systemctl reload nginx).

1 Like

Hello!

Thanks a lot. Didn’t know about the http2 not being available for port 80 at all. Learned something new today :-).

Currently editing my configs, hoping they’ll all work.

Will update this post.

//edit:

Seems to work great! I remember that I did remove the http2 parts, but since I had a default vhost running, still on http2, it might’ve still failed because of that, I think.
Anyway, all is fine now. Thanks!

I seem to be one of the few people with this issue since Google doesn’t find anything useful for it haha :sweat_smile:

1 Like

HTTP2 isn’t limited to TLS enabled connections. However, all major browsers decided they won’t implement HTTP2 on non-encrypted connections.

Therefore, I’m enclined the error from Boulder is actually incomplete. How it is stated now, it shouldn’t raise an error. The fact the server speaks HTTP/2 over HTTP isn’t illegal. It’s just not implemented in Boulder. IMHO the error should be something like “Server is speaking HTTP/2 over HTTP, which isn’t implemented in Boulder”.

Connecting to an HTTP/2 cleartext server is done one of two ways:

  1. You connect first using HTTP/1.1 and the client includes an Upgrade: h2c header in its first request. Meaning that the port simultaneously supports HTTP/1.1 and h2c.
  2. You connect directly using HTTP/2 (what’s called “prior knowledge”). Meaning that the port only supports the binary HTTP/2 protocol.

In nginx, when you do listen 80 http2, it’s actually doing (2), and (1) isn’t possible at all.

So it’s not that Boulder doesn’t support cleartext HTTP/2 - it’s that without prior knowledge about the server you’re connecting to, any HTTP client has to assume (1) is the case.

I think this is on nginx for having (arguably) unhelpful cleartext HTTP/2 behavior.

1 Like

Well, that's a bummer.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.