211 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Mosquitto TLS Setup
 | |
| 
 | |
| There is an [official guide](https://www.chirpstack.io/docs/guides/mosquitto-tls-configuration.html) from ChirpStack, which you can cross-reference. It is fairly complete, so some details are omitted here for brevity.
 | |
| 
 | |
| In the previous guide, you set up a Caddy web server to proxy the ChirpStack web interface, and you saw that Caddy automatically sets up TLS for you. This secures traffic between web browsers and ChirpStack.
 | |
| 
 | |
| However, you *also* need to secure traffic between gateways and ChirpStack. Because the communication protocol between the gateways and ChirpStack is MQTT and not HTTP, security is a little bit trickier. You will still use transport-layer security (TLS) to secure the traffic, but you need to create a certificate authority (CA). The CA is, itself, a certificate with corresponding secret key which you can use to issue certificates for the Mosquitto server and all the gateways connecting to it.
 | |
| 
 | |
| ## Create a CA
 | |
| 
 | |
| Start by installing the CloudFlare SSL tool:
 | |
| 
 | |
| ```sh
 | |
| sudo apt install golang-cfssl
 | |
| ```
 | |
| 
 | |
| Run these commands wherever you like (your home folder is fine) to create a few files:
 | |
| 
 | |
| ```sh
 | |
| # Certificate Signing Request (CSR) to create CA
 | |
| # The "request" is local; no third-party involved.
 | |
| cat <<EOF > ca-csr.json
 | |
| {
 | |
|   "CN": "ChirpStack CA",
 | |
|   "key": {
 | |
|     "algo": "rsa",
 | |
|     "size": 4096
 | |
|   }
 | |
| }
 | |
| EOF
 | |
| 
 | |
| # Settings for CA creation
 | |
| cat <<EOF > ca-config.json
 | |
| {
 | |
|   "signing": {
 | |
|     "default": {
 | |
|       "expiry": "8760h"
 | |
|     },
 | |
|     "profiles": {
 | |
|       "server": {
 | |
|         "expiry": "8760h",
 | |
|         "usages": [
 | |
|           "signing",
 | |
|           "key encipherment",
 | |
|           "server auth"
 | |
|         ]
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| EOF
 | |
| ```
 | |
| 
 | |
| With those files in place, generate the CA:
 | |
| 
 | |
| ```sh
 | |
| cfssl gencert -initca ca-csr.json | cfssljson -bare ca
 | |
| ```
 | |
| 
 | |
| This creates three files:
 | |
| 
 | |
| - `ca.csr`
 | |
| - `ca.pem`
 | |
| - `ca-key.pem`
 | |
| 
 | |
| You can discard `ca.csr`.
 | |
| 
 | |
| ## (Re-)Configure ChirpStack
 | |
| 
 | |
| Copy the remaining two files to a more permanent place and set ownership/permissions:
 | |
| 
 | |
| ```sh
 | |
| mkdir -p /etc/chirpstack/certs
 | |
| cp ca.pem /etc/chirpstack/certs
 | |
| cp ca-key.pem /etc/chirpstack/certs
 | |
| chown -R chirpstack:chirpstack /etc/chirpstack/certs
 | |
| chmod 400 /etc/chirpstack/certs/*
 | |
| ```
 | |
| 
 | |
| Then configure ChirpStack to use the CA by modifying `/etc/chirpstack/chirpstack.toml` to have the following:
 | |
| 
 | |
| ```toml
 | |
| [gateway]
 | |
|   client_cert_lifetime="12months"
 | |
|   ca_cert="/etc/chirpstack/certs/ca.pem"
 | |
|   ca_key="/etc/chirpstack/certs/ca-key.pem"
 | |
| ```
 | |
| 
 | |
| The official guide also recommends editing the `[integration.mqtt.client]` section, but you don't need to in this setup. **TODO learn about and explain [downlinks](https://www.chirpstack.io/docs/chirpstack/integrations/mqtt.html#scheduling-a-downlink)**
 | |
| 
 | |
| Finally, restart Chirpstack to use the updated configuration:
 | |
| 
 | |
| ```sh
 | |
| sudo systemctl restart chirpstack
 | |
| ```
 | |
| 
 | |
| ## Generate MQTT Server Certificate
 | |
| 
 | |
| Create a CSR for the MQTT server in the same place you created the CA, ensuring you replace the CN with your own site name:
 | |
| 
 | |
| ```sh
 | |
| cat <<EOF > mqtt-server.json
 | |
| {
 | |
|     "CN": "your.site.name",
 | |
|     "hosts": [
 | |
|         "your.site.name"
 | |
|     ],
 | |
|     "key": {
 | |
|         "algo": "rsa",
 | |
|         "size": 4096
 | |
|     }
 | |
| }
 | |
| EOF
 | |
| ```
 | |
| 
 | |
| Generate the certificate:
 | |
| 
 | |
| ```sh
 | |
| cfssl gencert -ca ca.pem -ca-key ca-key.pem -config ca-config.json -profile server mqtt-server.json | cfssljson -bare mqtt-server
 | |
| ```
 | |
| 
 | |
| Three more files are generated:
 | |
| 
 | |
| - `mqtt-server.csr`
 | |
| - `mqtt-server.pem`
 | |
| - `mqtt-server-key.pem`
 | |
| 
 | |
| You can discard `mqtt-server.csr`.
 | |
| 
 | |
| ## Configure MQTT Server
 | |
| 
 | |
| You need to move the other two files, as well as the CA certificate, to a place where Mosquitto can access them:
 | |
| 
 | |
| ```sh
 | |
| mkdir -p /etc/mosquitto/certs
 | |
| cp ca.pem /etc/mosquitto/certs
 | |
| cp mqtt-server.pem /etc/mosquitto/certs
 | |
| cp mqtt-server-key.pem /etc/mosquitto/certs
 | |
| chown root:mosquitto /etc/mosquitto/certs/mqtt-server-key.pem
 | |
| chmod 640 /etc/mosquitto/certs/mqtt-server-key.pem
 | |
| ```
 | |
| 
 | |
| Next, add a configuration for Mosquitto to use a local, non-TLS listener (for use by ChirpStack and for debugging) and an internet-accessible TLS listener that uses the certificate files you just copied:
 | |
| 
 | |
| ```sh
 | |
| per_listener_settings true
 | |
| 
 | |
| listener 1883 127.0.0.1
 | |
| allow_anonymous true
 | |
| 
 | |
| listener 8883 0.0.0.0
 | |
| cafile /etc/mosquitto/certs/ca.pem
 | |
| certfile /etc/mosquitto/certs/mqtt-server.pem
 | |
| keyfile /etc/mosquitto/certs/mqtt-server-key.pem
 | |
| allow_anonymous false
 | |
| require_certificate true
 | |
| use_identity_as_username true
 | |
| acl_file /etc/mosquitto/acl
 | |
| ```
 | |
| 
 | |
| The `acl_file` setting references an access control list that doesn't exist yet but which will prevent gateways from reading/writing topics that don't belong to them. Create the file by running the following:
 | |
| 
 | |
| ```sh
 | |
| cat <<EOF > /etc/mosquitto/acl
 | |
| pattern readwrite +/gateway/%u/#
 | |
| pattern readwrite application/%u/#
 | |
| EOF
 | |
| ```
 | |
| 
 | |
| With the configuration files in place, restart Mosquitto:
 | |
| 
 | |
| ```sh
 | |
| sudo systemctl restart mosquitto
 | |
| ```
 | |
| 
 | |
| Finally, if your server is running `ufw`, allow external traffic in to the port you configured Mosquitto to use for TLS:
 | |
| 
 | |
| ```sh
 | |
| sudo ufw allow 8883
 | |
| ```
 | |
| 
 | |
| ## Testing/Troubleshooting
 | |
| 
 | |
| Once set up, you can create a Gateway in ChirpStack and generate a TLS certificate. The certificate is only shown after being created; clicking the TLS tab again later will not show the cert but will let you generate another one. ChirpStack does not store these generated certs anywhere **(TODO confirm)**. **TODO add screenshots**
 | |
| 
 | |
| Save the certs as `ca.crt`, `cert.crt`, and `cert.key` onto a test machine such as your local computer or a different cloud instance.
 | |
| 
 | |
| Install `mosquitto-clients` onto the test machine.
 | |
| 
 | |
| On the ChirpStack server, open a terminal window and subscribe to all messages:
 | |
| 
 | |
| ```sh
 | |
| mosquitto_sub  -h localhost -t "#" -v -d
 | |
| ```
 | |
| 
 | |
| Keep the terminal open, and on the test machine, send a message to the `us915_1/gateway/<GATEWAY_ID>/test` topic, substituting `your.site.name` and `<GATEWAY_ID>` accordingly:
 | |
| 
 | |
| ```sh
 | |
| mosquitto_pub \
 | |
|   -h your.site.name \
 | |
|   -p 8883 \
 | |
|   --cafile ca.crt \
 | |
|   --cert cert.crt \
 | |
|   --key cert.key \
 | |
|   -t "us915_1/gateway/<GATEWAY_ID>/test" \
 | |
|   -d \
 | |
|   -m "hello"
 | |
| ```
 | |
| 
 | |
| In the terminal window on the ChirpStack server, you should see a message show up. **TODO add troubleshooting procedures and other expected output**
 |