Unable to generate certbot SSL certificate for ec2 website

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. crt.sh | example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is: lawrence-sanzogni.com, www.lawrence-sanzogni.com

I ran this command:

$ sudo certbot certonly -d lawrence-sanzogni.com -d www.lawrence-sanzogni.com

It produced this output:

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Runs an HTTP server locally which serves the necessary validation files under
the /.well-known/acme-challenge/ request path. Suitable if there is no HTTP
server already running. HTTP challenge only (wildcards not supported).
(standalone)
2: Saves the necessary validation files to a .well-known/acme-challenge/
directory within the nominated webroot path. A seperate HTTP server must be
running and serving files from the webroot path. HTTP challenge only (wildcards
not supported). (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Requesting a certificate for lawrence-sanzogni.com and www.lawrence-sanzogni.com

Certbot failed to authenticate some domains (authenticator: standalone). The Certificate Authority reported these problems:
  Domain: lawrence-sanzogni.com
  Type:   unauthorized
  Detail: 3.134.161.84: Invalid response from http://lawrence-sanzogni.com/.well-known/acme-challenge/bFTq0syd2SurkjDxqfsqo_qO8AmGpv7KAFQcMYc8JcY: "<!DOCTYPE html>\n<html lang=\"en\">\n  <head charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1"

  Domain: www.lawrence-sanzogni.com
  Type:   unauthorized
  Detail: 3.134.161.84: Invalid response from http://www.lawrence-sanzogni.com/.well-known/acme-challenge/8bql4YO23z_QGxamewGaDYilVYxK_u6OL581Q7ewaWo: "<!DOCTYPE html>\n<html lang=\"en\">\n  <head charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1"

Hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.

My web server is (include version): Chrome

The operating system my web server runs on is (include version): Ubuntu 22.04.1 LTS

My hosting provider, if applicable, is: AWS

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):
AWS

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

You have an "Express" web service responding to HTTP (port 80) requests. You must stop that before using --standalone which needs exclusive use of port 80.

Or, use the webroot method and specify the document root used by your express service.

You could also consider a DNS Challenge. Certbot has a Route53 plugin although requires some care to set the permissions correctly. See the Certbot docs for that.

Read about the different kinds of challenges here

4 Likes

Thank you for the response. If I stop my express server from running, then I get another error

Certbot failed to authenticate some domains (authenticator: standalone). The Certificate Authority reported these problems:
  Domain: lawrence-sanzogni.com
  Type:   connection
  Detail: 3.134.161.84: Fetching http://lawrence-sanzogni.com/.well-known/acme-challenge/4RwRXPVJAOg1dJF-b5deks92TMXZD6Ci3u2bvhcZoOw: Connection refused

  Domain: www.lawrence-sanzogni.com
  Type:   connection
  Detail: 3.134.161.84: Fetching http://www.lawrence-sanzogni.com/.well-known/acme-challenge/DPwDLdYSiw6azWHySSOOA3qUsv0v9PLU8gdqk4gTdZs: Connection refused

Hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.

the same error message appears if I keep the server running but change port numbers

Maybe I'm misunderstanding

How is the firewall configured to handle inbound HTTP (TCP port 80)?

2 Likes

I have inbound rules set up on AWS. Port 80 should be open to receiving inbound requests

Something doesn't add up :frowning:

2 Likes

Yeah, this is odd. I can still see your Express server responding to HTTP requests. In fact, I get a 200 OK even when should see 404 Not Found.

But, it makes no sense that if you stop and then try --standalone that it would error for "reset by peer".

You should try adding this debug option

sudo certbot certonly --standalone --dry-run --debug-challenges -v -d lawrence-sanzogni.com -d www.lawrence-sanzogni.com

Certbot will pause with a "press enter" or similar. Leave it paused - do Not press Enter. While paused open a different window or device to connect to the URL it will show you. You could even try a simple curl to your domain while it is paused. You should be able to get a response. If it works from inside your AWS VPC make sure to try from the public internet (even a cell phone with wifi off).

If possible, still while Certbot is paused, try this in another window to that EC2 instance

sudo netstat -pant | grep ':80' | grep -i listen

You should see Certbot as the listener on port 80

4 Likes

That all said, why not just use the running Express server and --webroot?

You won't have to take Express down to renew your cert each time.

Although, you'll need to figure out why Express does not issue a 404 (and instead would return the file in that location if one existed)

curl -i lawrence-sanzogni.com/.well-known/acme-challenge/Test404
HTTP/1.1 200 OK
X-Powered-By: Express
2 Likes

So I did this:
I have 3 terminal windows open - each one connected to my EC2 instance via ssh....

  • #1 is running my express server
    nodemon server.js
  • #2 is running the debug option:
    sudo certbot certonly --standalone --dry-run --debug-challenges -v -d lawrence-sanzogni.com -d www.lawrence-sanzogni.com
    it is PAUSED.
  • #3 is running
sudo netstat -pant | grep ':80' | grep -i listen

It doesn't look like Certbot is the listener

tcp6       0      0 :::80                   :::*                    LISTEN      4553/python3
1 Like

No, sorry, yeah Python probably is Certbot standalone. Certbot is written in python

3 Likes

Is Python still on port 80? Because I am getting response from Express

curl -i lawrence-sanzogni.com/MikeTest
HTTP/1.1 200 OK
X-Powered-By: Express
3 Likes

What I should've mentioned as well is that I'm redirecting requests from port 80 to port 3000:

$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

because if I try to run my express server in port 80 it denies me due to not having root privileges

Error: listen EACCES: permission denied 0.0.0.0:80

I've read that you shouldn't run Nodejs as the root user since it poses as a security risk.

As for Express returning a file as opposed to a 404, I believe it's due to this endpoint handler in my server.js file:

app.get('/*', (req, res) => {
  res.sendFile(path.join(__dirname, '../client/dist/index.html'), (err) => {
    err && alert('err:', err);
  })
});

I'm using react-router-dom, and I was having issues with my website not returning files from other than the root / endpoint
I had an entire stackoverflow question dedicated to that: node.js - React-Router V6 issue, only the root "/" route works, any other endpoint returns a 404 - Stack Overflow

It seems to be, I'm still getting the same thing printed back:

tcp6       0      0 :::80                   :::*                    LISTEN      4553/python3   

Well, the HTTP request that arrives from Let's Encrypt on port 80 must reach Certbot --standalone. With your port forwarding I don't see how that can work. You can tell --standalone to listen on a different port but then you need to change your forward to that port. But, if you were going to do that just disable the forward while --standalone running

I think you are better off trying to get --webroot working with Express or maybe even better is the DNS Challenge. That takes out all the comms routing from the picture.

It is not ideal to return 200 when 404 is better. But, for the HTTP Challenge to succeed all Express has to do is return the contents of the file created by Certbot in the path you tell it.

I don't know Express at all but this might be the right value for the --webroot-path (you will need to test) although make it explicit if you can at least while testing.

4 Likes

UPDATE: First, thanks everyone for the help.

  • So I issued a certificate using webroot and it seems to have been successful. This is evidence by checking the status of my certs:
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: lawrence-sanzogni.com
    Serial Number: 49441a6770997fa4c85400c1a00f394c1d3
    Key Type: ECDSA
    Domains: lawrence-sanzogni.com www.lawrence-sanzogni.com
    Expiry Date: 2024-02-13 16:40:59+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/lawrence-sanzogni.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/lawrence-sanzogni.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Unfortunately, I'm now running into the issue where my server can't find the pem files using the given filepaths.
Does anyone have some insight to this?

1 Like

How did you come to know this?
Please show any/all related messages/logs.

2 Likes

My apologies.

This issue is becoming a bit too elaborate with new problems presenting themselves. My original question was indeed answered. I assume nobody wants this thread to veer off topic so I'll give a brief explanation then make another thread if necessary.
My application is written in Nodejs, so I'll post excerpts of the bare essentials just to show how my server works as this community focuses on LetsEncrypt specific issues.

  • backend server code
 try {
  const cred = {
    key: readFileSync("/etc/letsencrypt/live/lawrence-sanzogni.com/privkey.pem", 'utf8'),
    cert: readFileSync("/etc/letsencrypt/live/lawrence-sanzogni.com/cert.pem", 'utf8'),
    ca: readFileSync("/etc/letsencrypt/live/lawrence-sanzogni.com/chain.pem", 'utf8')    
  };

  const httpsServer = https.createServer(cred, app);

   httpsServer.listen(8443, () => {
     console.log(`listening to localhost:8443`);
   });
  } catch(err) { 
    console.log('HTTPS err:', err.stack);
  }
  • My Express server is running and it appears to have accepted my certificates now, evidenced that it executes the code nested in the try statement and not the error handler. And proceeds to log my console commands:
listening to localhost:8443
  • When I run a curl command to my website it still results that PEM files can't be found
$ curl -i https://lawrence-sanzogni.com/.well-known/acme-challenge/Test404

logs

curl: (35) LibreSSL/3.3.6: error:1404B42E:SSL routines:ST_CONNECT:tlsv1 alert protocol version
  • I've used ls and cat to double check if my certificates are there and they are in fact there


$ sudo cat ../../etc/letsencrypt/live/lawrence-sanzogni.com/fullchain.pem

logs

-----BEGIN CERTIFICATE-----
MIIERzCCAy+gAwIBAgISBJRBpnc....

I'm not sure what the issue is at this point but I think I might have to move to another thread...

How do the HTTPS requests [TCP port 443] reach port 8443?:

1 Like

Through port forwarding. I'm not the root user, so I don't have access to ports below 1024

$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443

My Express server won't accept port 443 as a parameter, so I use 8443 instead

1 Like

Are you Geo-Location blocking [or other]?
I can't reach your site :frowning:

curl -i --connect-timeout 10 https://lawrence-sanzogni.com/
curl: (28) Connection timeout after 10000 ms
2 Likes