Connect through a TLS broker
The PDComm simulator connects to brokers over plain TCP only. In this tutorial, you put a local broker (the edge) next to the simulator and let it forward the data to a remote broker (the site) over TLS with a client certificate.
simulator ── plain TCP ──▶ edge broker ══ TLS bridge ══▶ site broker ══ TLS ══▶ operator (publisher) 127.0.0.1:1883 (edge.conf) cert CN=pdcomm-edge 127.0.0.1:8883 cert CN=operator- The site broker accepts only TLS on port 8883 and requires every client to present a certificate issued by the tutorial CA.
- The edge broker accepts plain MQTT on port 1883 of the loopback address and bridges the
opcua/#topics to the site. - An operator connects to the site with their own certificate and receives the data.
Both brokers run on one computer here. In a real deployment, only the site address and the certificate names change.
Before you begin
Section titled “Before you begin”- Mosquitto 2.x and
mosquitto_sub - The OpenSSL command-line tool. The certificate commands work with both OpenSSL 3 and the LibreSSL that ships with macOS; the
openssl s_clientoptions in step 8 assume OpenSSL 3. - The PDComm OPC UA simulator package and
publisher-scenario.jsonfrom OPC UA PubSub over MQTT - Four terminal windows, and no other broker on ports 1883 and 8883
-
Create a working directory and save five files in it:
터미널 창 mkdir mqtt-tlscd mqtt-tlscp ../mqtt-lab/publisher-scenario.json .These are the certificate extensions. The subjectAltName of the broker certificate lists the names and addresses that clients connect to.
server.ext # X.509 extensions for the broker certificate. The subjectAltName entries# must match the host name or address that clients and bridges connect to.basicConstraints = critical, CA:FALSEkeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuthsubjectAltName = DNS:localhost, IP:127.0.0.1client.ext # X.509 extensions for client certificates (the edge bridge and operators).basicConstraints = critical, CA:FALSEkeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = clientAuthThis is the site broker configuration:
site.conf # Site broker: MQTT over TLS on port 8883. Every client must present a# certificate issued by the tutorial CA; its common name becomes the user name.listener 8883 127.0.0.1cafile ca.crtcertfile site.crtkeyfile site.keyrequire_certificate trueuse_identity_as_username trueallow_anonymous falsepersistence falselog_dest stdoutSetting Meaning cafile,certfile,keyfileThe CA that verifies client certificates, the broker certificate, and the broker’s private key require_certificate trueDrop clients that present no certificate during the TLS handshake. use_identity_as_username trueUse the CN of the client certificate as the user name. allow_anonymous falseRefuse connections without a user name. This is the edge broker configuration:
edge.conf # Edge broker: plain TCP for local clients such as the PDComm simulator,# and a TLS bridge that forwards their OPC UA topics to the site broker.listener 1883 127.0.0.1allow_anonymous truepersistence falselog_dest stdoutconnection siteaddress 127.0.0.1:8883bridge_protocol_version mqttv50bridge_cafile ca.crtbridge_certfile edge.crtbridge_keyfile edge.keyremote_clientid pdcomm-edge-bridgetopic opcua/# out 1Setting Meaning connection siteStart a bridge named site.address 127.0.0.1:8883The site broker the bridge connects to; the address must appear in the site certificate’s subjectAltName. bridge_protocol_version mqttv50Bridge with MQTT 5.0 so that the Content Type and user properties pass through unchanged. bridge_cafile,bridge_certfile,bridge_keyfileThe CA that verifies the site certificate, and the bridge’s client certificate and private key topic opcua/# out 1Send local opcua/#messages to the site (out) at QoS 1. -
Create the tutorial CA and three certificates:
터미널 창 openssl req -x509 -new -newkey rsa:2048 -nodes -sha256 -days 365 \-subj "/CN=PDComm Tutorial CA" -keyout ca.key -out ca.crtopenssl req -new -newkey rsa:2048 -nodes -subj "/CN=localhost" -keyout site.key -out site.csropenssl x509 -req -in site.csr -CA ca.crt -CAkey ca.key -CAcreateserial -sha256 -days 365 \-extfile server.ext -out site.crtopenssl req -new -newkey rsa:2048 -nodes -subj "/CN=pdcomm-edge" -keyout edge.key -out edge.csropenssl x509 -req -in edge.csr -CA ca.crt -CAkey ca.key -CAcreateserial -sha256 -days 365 \-extfile client.ext -out edge.crtopenssl req -new -newkey rsa:2048 -nodes -subj "/CN=operator" -keyout operator.key -out operator.csropenssl x509 -req -in operator.csr -CA ca.crt -CAkey ca.key -CAcreateserial -sha256 -days 365 \-extfile client.ext -out operator.crtchmod 600 *.keyCheck that every certificate chains to the CA:
터미널 창 openssl verify -CAfile ca.crt site.crt edge.crt operator.crtsite.crt: OKedge.crt: OKoperator.crt: OK -
Work in the
mqtt-tlsdirectory in all four terminals. In the first terminal, start the site broker:터미널 창 mosquitto -c site.confConfig loaded from site.conf.Opening ipv4 listen socket on port 8883.mosquitto version 2.1.2 running -
In the second terminal, connect to the site with the operator certificate and subscribe:
터미널 창 mosquitto_sub -h 127.0.0.1 -p 8883 --cafile ca.crt --cert operator.crt --key operator.key \-V 5 -t 'opcua/#' -F '%t qos=%q retain=%r content-type=%C user-properties=%P %l bytes'The site log shows the TLS 1.3 connection and the user name taken from the certificate:
New client connected from 127.0.0.1:53292 as auto-A75E2731-… (p5, c1, k60, u'operator').Client auto-A75E2731-… negotiated TLSv1.3 cipher TLS_AES_256_GCM_SHA384 -
In the third terminal, start the edge broker:
터미널 창 mosquitto -c edge.confOpening ipv4 listen socket on port 1883.Connecting bridge site (127.0.0.1:8883)mosquitto version 2.1.2 runningThe bridge connection appears in the site log, with
pdcomm-edge, the CN of the edge certificate, as the user name:New client connected from 127.0.0.1:53293 as pdcomm-edge-bridge (p5, c0, k60, u'pdcomm-edge').Client pdcomm-edge-bridge negotiated TLSv1.3 cipher TLS_AES_256_GCM_SHA384 -
In the fourth terminal, run the simulator publisher. It connects to the edge at
127.0.0.1:1883over plain TCP:터미널 창 "$PDCOMM_APPS/bin/pdcomm-opcua-headless" --scenario publisher-scenario.jsonIn a new terminal without
PDCOMM_APPS, first runPDCOMM_APPS=<simulator package directory>. The scenario exits with code 0, and both messages reach the operator in the second terminal over TLS:opcua/uadp/data/100/line1 qos=0 retain=0 content-type=application/opcua+uadp user-properties=UAMessageType:ua-data 52 bytesopcua/uadp/data/100/line1 qos=0 retain=0 content-type=application/opcua+uadp user-properties=UAMessageType:ua-data 52 bytesThe Content Type and
UAMessageTypesurvive the bridge, so an OPC UA subscriber on the site side can accept these messages too. -
Check that a connection without a certificate is refused. Run this in the fourth terminal:
터미널 창 mosquitto_sub -h 127.0.0.1 -p 8883 --cafile ca.crt -t 'opcua/#' -C 1 -W 3Error: The connection was lostThe site log records why:
OpenSSL Error while trying to get the error[0]: error:0A0000C7:SSL routines::peer did not return a certificateClient 127.0.0.1 [127.0.0.1:53299] disconnected: Protocol error. -
You can also check the TLS setup on its own, without MQTT, with
openssl s_client:터미널 창 openssl s_client -connect 127.0.0.1:8883 -CAfile ca.crt -cert operator.crt -key operator.key \-verify_ip 127.0.0.1 -verify_return_error -brief < /dev/nullThe key lines of the output are:
CONNECTION ESTABLISHEDProtocol version: TLSv1.3Ciphersuite: TLS_AES_256_GCM_SHA384Peer certificate: CN=localhost-verify_ipchecks that the IP address appears in the certificate’s subjectAltName. When you connect by host name, use-verify_hostname <name>instead.
Clean up
Section titled “Clean up”- Stop
mosquitto_subin the second terminal with Ctrl+C. - Stop the brokers in the third and first terminals with Ctrl+C.
- Delete the
mqtt-tlsdirectory when you’re done, and don’t leave a copy ofca.keyanywhere.
Common errors
Section titled “Common errors”| Output | Cause | Fix |
|---|---|---|
Error: The connection was lost, and peer did not return a certificate in the site log |
The client presented no certificate. | Pass --cert and --key. |
Error: Protocol error, and tlsv1 alert unknown ca in the site log |
The client doesn’t trust the site certificate. | Pass --cafile ca.crt. |
certificate verify failed and Bridge site next backoff will be … ms in the edge log |
The bridge couldn’t verify the site certificate. | Check that bridge_cafile and address match the certificate. |
MQTT broker connection failed: MQTT transport I/O: ConnectionReset from the simulator |
You pointed the simulator at the TLS port (8883). | Point the simulator at the edge’s plain port (1883). |
TLS problems explains each message in more detail.