Iptables *nat Pre-Routing


I’m having trouble getting the --standalone plugin to complete the authentication process. I believe I know why. Just not sure the best practice to resolve it. In case it matters, my server environment is Arch. For reference, here are the flags I’m passing:

$ sudo certbot certonly --standalone --preferred-challenges tls-sni -d example.com

My Iptables logic is to:

  1. Preroute all traffic from port 80 and port 443 to port 3000 (where I listen with a node application).
  2. Accept traffic on 3000 and 22(for SSH)
  3. Drop all other inbound traffic
  4. I am not blocking any outbound traffic at the moment.

Since the command I’m using asks Certbot to verify via port 443, this is probably where the issue is. I tried ammending my rules to allow traffic directly in on 443. No dice. So my next step is to get rid of the pre-routing rule on 443. This will probably solve it, but obviously stop routing https to my web app.

What’s the best solution here?

Before you ask why I’m not just listening on 80 and 443, it is for several reasons:

  • I do not want to run my node app as root, for security.
  • Using root would also add an extra layer of complexity to my automated deployment process

Using the webroot plugin may have avoided this, as (I think) LetsEncrypt would work with authenticating from the app directory by following the preroute to port 3000. But, I can’t do this because I’m using a SymLink for the app. Meaning I would end up wiping my certs every time I deploy.

Thanks for your help.

Hi @Ten-Taken,

The prerequisite for using --standalone is that inbound connections to the externally-visible port 443 will reach Certbot’s own listener (which by default runs on port 443, but can be changed with --tls-sni-01-port), or else that you specify --preferred-challenges http-01 and then inbound connections to the externally-visible port 80 will reach Certbot’s own listener (which by default runs on port 80, but can be changed with --http-01-port).

The prerequisite for using --webroot is that there’s an existing service speaking HTTP on the publicly-visible port 80 speaking HTTP and that Certbot can modify what appears in the /.well-known/acme-challenge directory of that service by writing its own files under /.well-known/acme-challenge within the directory specified with -w.

I hope that helps!


Thank you so much! I didn’t know you could bind certbot’s listener to a different port. However I’m having trouble with the syntax.

$ sudo certbot certonly --standalone --preferred-challenges tls-sni-01-port 3000 -d example.com

certbot: error: argument --preferred-challenges: Unrecognized challenges: tls-sni-01-port

$ sudo certbot certonly --standalone --preferred-challenges --tls-sni-01-port 3000 -d example.com

certbot: error: argument --preferred-challenges: expected one argument


$ sudo certbot certonly --standalone --preferred-challenges tls-sni-01 --tls-sni-01-port 3000 -d example.com

1 Like


That did it! You’re awesome, thank you.

As the docs I read suggested, I had to pull my “server” service down to do this. So I’ll have to adjust the renewal cron job accordingly. Thanks again, both of you.

1 Like

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