Cerbot failing to authenticate domain: unauthorized

I'm trying to stage a certificate for a nginx server. in the nginx file I am redirecting port 80 traffic to a node app running in pm2 on port 3000. You can hit the website with an insecure connection just fine.
Letsdebug.net said no issues where found. I have used [ nc -zv IPADDRESS PORT ] to verify that ports 80, 8080, 443, and 3000 are open.
Feel like i'm going crazy.

My domain is:
brdgdev.com

I ran this command:
sudo certbot --nginx --staging -d brdgdev.com

It produced this output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for brdgdev.com

Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
Domain: brdgdev.com
Type: unauthorized
Detail: 35.234.250.45: Invalid response from http://brdgdev.com/.well-known/acme-challenge/97rzjZ7470MI_GPTaP0YToQ6ErrUbky8VtyxtMhhAlM: 404

Hint: The Certificate Authority failed to verify the temporary nginx configuration changes made by Certbot. Ensure the listed domains point to this nginx server and that it is accessible from the internet.

My web server is (include version):
nginx 1.22.1

The operating system my web server runs on is (include version):
Debian 12

My hosting provider, if applicable, is: google cloud platform is running the server as a vm instance, hostinger is hosting the domain name

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

The version of my client is 2.1.0

And here is my /etc/nginx/sites-available/default file:

server {
server_name brdgdev.com;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            #try_files $uri $uri/ =404;
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            proxy_redirect off;
    }

}

Your server block does not have a listen statement for port 80.

That is the default so regular HTTP requests would be processed by that server block.

But, using the --nginx option might require an explicit listen statement. I'm not certain.

The --nginx option inserts temp code into a suitable server block for that domain. If it doesn't find one it makes a temporary one. We could verify more about what is happening by looking at the log in /var/log/letsencrypt. But, try adding a listen anyway as no harm done.

Also, requests to that domain get a response for "BRDG JPMP API". Is that for sure coming from that nginx server? Could you have your local port / network routing such that it goes directly to that backend server rather than nginx?

Both of the above things can cause a 404 error (HTTP Not found).

3 Likes

I have modified my nginx config as follows, retried the certbot staging command, and am still seeing the unauthorized error:
In "/etc/nginx/sites-available/default":

    server {
      listen 80 default_server;
      listen [::]:80 default_server;
      server_name brdgdev.com www.brdgdev.com;
      gzip off;
      
      root /var/www/html;
      
      index index.html index.htm index.nginx-debian.html;
      
      server_name _;

      location / {
              proxy_pass http://127.0.0.1:3000;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-NginX-Proxy true;

              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";

              proxy_redirect off; 
        }
     }

I know it's bad practice to write everything in the default file, but could that be the problem? I'm attempting to forward port 80 traffic to port 3000 which points to a node server that lives elsewhere on my server, could it be that it's not placing the acme challenge file in the correct root folder?

Here's my iptables as well, where the port forwarding is done:

Chain PREROUTING (policy ACCEPT)
target prot opt source destination
REDIRECT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 redir ports 3000
REDIRECT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 redir ports 3000
REDIRECT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 redir ports 3000
DOCKER 0 -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER 0 -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 0 -- 172.17.0.0/16 0.0.0.0/0

Chain DOCKER (2 references)
target prot opt source destination

I don't think two server_name directives are alllowed. You don't need the second one.

No.

Not because of the proxy anyway. Certbot's --nginx option adds temporary statements into your nginx server block to return the value directly. It does not place an actual file. These statements take precedence over those proxy statements. Certbot removes those when the cert request completes.

This looks like the problem. I am not an IPTABLES expert but doesn't this send all HTTP (port 80) requests directly to port 3000? That means the requests don't even arrive at your nginx which is only listening on port 80.

If you want to get a cert using the --nginx option that nginx server must be the one to handle the incoming port 80 request

3 Likes

Thanks, Mike. Yeah, I had the redirect bypassing nginx completely. Removing the redirects fixed my problem. Also I noticed some certbot behavior that confused me, personally: if you use the --staging flag certbot creates a test certificate. You have to manually delete the test certificate and go into the nginx server block and wipe all certbot managed lines before you can properly install the fully functional certificate. I guess this is by design?

1 Like

Just use --dry-run instead of --staging? :man_shrugging:

3 Likes

Hmm. That doesn't sound quite right. Yes, the --staging flag issues a test cert. But, they are placed in the same directory as when getting a production cert. So, once you got a production cert your nginx should have just started using it. When trying to get the production cert Certbot may have warned about the cert not yet being expired or something like that. But, you should have been able to proceed.

It's been a long time since I've used --staging for a new nginx install so I am not 100% on that although am pretty confident.

As @griffin pointed out the --dry-run option is usually better for testing than --staging. It checks that your system can satisfy the challenge but does not permanently modify nginx config and does not overlay any existing certs.

The "trick" with --dry-run and --nginx is you must use it with certonly command. Like:

sudo certbot certonly --dry-run --nginx -d example.com

Certbot will issue an error if --dry-run and --nginx are used without certonly.

Let us know if you want us to look into the behavior of --staging followed by not with --staging. I could setup a test although note I'd be using the current version of Certbot which is 5.2.2. I don't recall seeing this reported before so maybe some kind of glitch was present in your older version.

3 Likes

...which is ironic since the default command of certbot when no other command is given (e.g. certonly) is... run. You heard that right: --dry-run does not work with the run command. :zany_face:

1 Like