fill in mosquitto tls section

This commit is contained in:
Jon Roeber 2023-11-25 16:09:02 -05:00
parent 7311909609
commit 7f11e484bd
3 changed files with 185 additions and 29 deletions

View File

@ -1,65 +1,210 @@
# Mosquitto TLS Setup
Ref: <https://www.chirpstack.io/docs/guides/mosquitto-tls-configuration.html>
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.
You generate a certificate authority which has the following purposes:
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.
- Generate a Mosquitto server certificate so gateways can connect to it via TLS
- Generate client certificates for gateways so they can prove their identity to the Mosquitto server
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.
When you create the CA, three files are generated:
## 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`
Then when you create the MQTT cert, three more files are generated:
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`
Then you add the CA (with its key) to the ChirpStack config. Make sure to change ownership to `chirpstack` when copying certs to `/etc/chirpstack/certs`.
You can discard `mqtt-server.csr`.
Then create a folder for MQTT cert and copy files.
## Configure MQTT Server
Set ownership and permission on the key:
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
```
Once set up, you can create a Gateway in ChirpStack and generate a TLS certificate. It is only shown after being created; clicking the TLS tab again later will not show the cert but will let you generate a new one. Certs don't seem to be stored anywhere.
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:
Don't forget to allow `8883` in the firewall.
```sh
per_listener_settings true
## Gateway Bridge Config
listener 1883 127.0.0.1
allow_anonymous true
Create `/etc/chirpstack-gateway-bridge/certs` folder and copy certs in. Make everything owned by `gatewaybridge`. Set permission to `640`.
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
```
Modify the config, ref: <https://www.chirpstack.io/docs/chirpstack-gateway-bridge/configuration.html>
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:
Don't forget to change `tcp` to `ssl` in the server list.
```sh
cat <<EOF > /etc/mosquitto/acl
pattern readwrite +/gateway/%u/#
pattern readwrite application/%u/#
EOF
```
Check `journalctl` on both the bridge and Mosquitto to see that the connection is established.
With the configuration files in place, restart Mosquitto:
Be sure to set the Gateway ID in both the `chirpstack-gateway-bridge` and `packet-forwarder` configs (though this doesn't seem to matter? Need to experiment). Also be sure the UDP port matches between the two.
```sh
sudo systemctl restart mosquitto
```
## Troubleshooting
Finally, if your server is running `ufw`, allow external traffic in to the port you configured Mosquitto to use for TLS:
Install `mosquitto-clients` on the Gateway.
```sh
sudo ufw allow 8883
```
Send a message to the `test` topic:
## 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 `<GATEWAY_ID>` accordingly:
```sh
mosquitto_pub \
-h chirpstack.roeber.dev \
-h your.site.name \
-p 8883 \
--cafile /etc/chirpstack-gateway-bridge/certs/ca.crt \
--cert /etc/chirpstack-gateway-bridge/certs/cert.crt \
--key /etc/chirpstack-gateway-bridge/certs/cert.key \
-t "test" \
--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**

View File

@ -74,9 +74,8 @@ Experience with the following is recommended but not required if you are able to
- Rent compute from a cloud vendor
- Secure shell (SSH)
- Caddy web server
- TLS certificate generation
- Let's Encrypt
- DNS-01 protocol
- Transport Layer Security (TLS)
- Certificates and secret keys
- Self-generated certificate authority
- [`cfssl`](https://github.com/cloudflare/cfssl)
- Mosquitto MQTT

View File

@ -58,4 +58,16 @@ Add/change some values:
```toml
event_topic_template="us915_1/gateway/{{ .GatewayID }}/event/{{ .EventType }}"
command_topic_template="us915_1/gateway/{{ .GatewayID }}/command/#"
````
```
## Gateway Bridge Config
Create `/etc/chirpstack-gateway-bridge/certs` folder and copy certs in. Make everything owned by `gatewaybridge`. Set permission to `640`.
Modify the config, ref: <https://www.chirpstack.io/docs/chirpstack-gateway-bridge/configuration.html>
Don't forget to change `tcp` to `ssl` in the server list.
Check `journalctl` on both the bridge and Mosquitto to see that the connection is established.
Be sure to set the Gateway ID in both the `chirpstack-gateway-bridge` and `packet-forwarder` configs (though this doesn't seem to matter? Need to experiment). Also be sure the UDP port matches between the two.