MQTT Broker wss

Hello everyone,

I have set up a Mosquitto broker on a server with a domain name. To allow internet clients to connect to the broker, I'm using port 9001 with the WebSocket protocol. Now, I want to secure the client connections by using a CA (Certificate Authority) certificate. This is necessary for building a web application that communicates with this broker.

However, I have a specific requirement: I want to keep port 80 closed and only use port 9001 as the public-facing port.

Is it possible to use Certbot with Let's Encrypt to obtain SSL/TLS certificates in this scenario?

I attempted to use the following command after stopping the broker container to make port 9001 available:

sudo certbot certonly --standalone --http-01-port 9001 -d <server's domain> -v

Unfortunately, I encountered an error message stating that "Some challenges have failed."

I'm confident that the domain name with port 9001 is accessible for MQTT over WebSocket, as I've tested it. My server is running Ubuntu 22.04.3 LTS.

Is there a way to resolve this issue and obtain SSL/TLS certificates while keeping port 80 closed?

The ACME HTTP Challenge needs port 80 open. But, you could use the DNS Challenge or possibly TLS-ALPN

The --http-01-port option changes the port that Certbot listens on. That is for when the local network re-routes the incoming port 80 request to a local network service on a different port (such as by using router NAT).

3 Likes

When using a wildcard domain and also if I don't have access to the DNS configuration files, do I still have the option of using TLS-ALPN? Or are there no alternatives? Am I required to open port 80?

The DNS Challenge is required to use a wildcard domain name. But, a DNS Challenge works for non-wildcard too. This is probably best if only port 9001 is available.

Certbot does not support TLS-ALPN but if you have an alternate service that can do TLS-ALPN that would use port 443. I mentioned it only as alternate to port 80.

Update:
Oh, you changed your post while I was typing :slight_smile: Yes, the HTTP challenge needs port 80 and TLS-ALPN needs port 443.

3 Likes

Just expanding and clarifing what @MikeMcQ wrote above:

  1. for the http-01 challenge, your server must accept a port 80 connection from LetsEncrypt. the Certbot command flag you used is designed for situations where you want to put a proxypass on port 80 to the higher port.

  2. you can use a DNS-01 challenge

  3. since you do not have other services on port 80, the simplest solution is to run Certbot in --standalone mode and use the pre/post hooks to toggle firewall rules for port 80 traffic. I actually do this with port 53 and acme-dns for DNS-01 challenges myself, only running the DNS server and allowing traffic when completing ACME orders. this is relatively simple to set up. if you're unfamiliar, i can share instructions.

2 Likes

I probably won't check this site for a while so in case this is needed...

adapted from someone helping me on toggle port rule on an ubuntu iptables firewall? - Server Fault

Initial Configuration

create the acme-dns chain

iptables -N acme-dns

set the tables to run it BEFORE the port 53 deny

iptables -A INPUT -j acme-dns

it make make sense to first..

iptables-save > iptables.dump
vi iptables.dump

then manually add in the acme-dns line as the first chain. e.g.

:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [451:186415]
:acme-dns - [0:0]
:f2b-postfix - [0:0]
:f2b-sshd - [0:0]
:f2b-sshd-invalid_accounts - [0:0]
:f2b-sshd-system_accounts - [0:0]
-A INPUT -j acme-dns

and reload

iptables-restore < iptables.dump

Usage with Certbot hooks

start (--pre-hook)

iptables -A acme-dns -p tcp --dport 53 -j ACCEPT
iptables -A acme-dns -p udp --dport 53 -j ACCEPT
iptables -A acme-dns -p tcp --dport 8011 -j ACCEPT
systemctl start acme-dns.service

stop (--post-hook)

iptables -F acme-dns
systemctl stop acme-dns.service

Adapting to HTTP-01

1- during intial config, set the rule to run before rejecting on port 80
2- the hook scripts will be simpler and can even run on the commandline (not as a script invoked on the commandline):

start (--pre-hook)

iptables -A acme-dns -p tcp --dport 80 -j ACCEPT

stop (--post-hook)

iptables -F acme-dns

Then just run Certbot as....

certbot [args] --standalone --pre-hook="iptables -A acme-dns -p tcp --dport 80 -j ACCEPT" --post-hook="iptables -F acme-dns"

In this situation, while you are accepting traffic on port 80, both the firewall rules and server only exist when running Certbot. Running an ephemeral service like this should be fine for your security model.

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