Table of Content
Table of Content
Mutual TLS (mTLS) is the security protocol that requires both the IoT device and the management server to present and verify X.509 certificates before exchanging any data. Unlike standard TLS — where only the server authenticates itself — mTLS enforces bidirectional authentication, ensuring that neither side can be impersonated by an attacker who intercepts the connection.
This guide walks through the complete implementation of mTLS in an IoT deployment using SocketXP’s built-in BastionXP CA module, from obtaining the first certificate to running a fully authenticated fleet.
For a complete architectural reference on mTLS PKI design, certificate lifecycle, and revocation, see the companion guide: Scaling mTLS IoT Security: The Developer’s Guide to Automated IoT Device Certificates.
What You Need Before You Start
- A SocketXP account with a valid auth token (available from the SocketXP portal)
- An IoT device running Linux (Raspberry Pi, NVIDIA Jetson, industrial gateway, or any embedded Linux board)
- The SocketXP agent installed on the device (download)
- Port 9444 accessible outbound from the device (this is SocketXP’s dedicated mTLS gateway port)
Step 1: Understand the Two Gateway Ports
SocketXP runs two endpoints:
| Port | Mode | What it enforces |
|---|---|---|
| 9443 | Standard TLS | Server-only authentication — device verifies gateway, gateway does NOT verify device certificate |
| 9444 | Mutual TLS (mTLS) | Both sides authenticate — device verifies gateway AND gateway verifies device certificate |
When you connect on port 9443 (the default), your devices are not individually authenticated at the transport layer. Enabling mTLS means explicitly directing your device agent to port 9444 and providing the device certificate and key.
Step 2: Obtain the Device Server Certificate
SocketXP’s built-in BastionXP CA module issues X.509 TLS certificates to your devices. The device server certificate has a long validity period and authenticates the device to the gateway.
On the IoT device (or during your provisioning process), run:
sudo socketxp ca login--server "device001.fleet.example"
The device name argument (e.g., device001.fleet.example) becomes the Common Name in the certificate Subject, uniquely identifying this device in the CA’s records.
After the command completes, two files appear in /var/lib/socketxp/:
ls -la /var/lib/socketxp/ # tls_server.crt ← device certificate signed by BastionXP CA module # tls_server.key ← device private key (never leaves the device)
Verify the certificate is valid:
openssl x509 -in /var/lib/socketxp/tls_server.crt -noout -subject -dates # subject= /CN=device001.fleet.example # notBefore=... # notAfter=...
Step 3: Register the Device on the mTLS Port
With the certificate in place, authenticate to the SocketXP gateway on the mTLS port:
socketxp login\ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_client.crt \ --key /var/lib/socketxp/tls_client.key
The --gateway-port 9444 flag is the critical difference from a standard registration. Without it, the agent connects to port 9443 and the mTLS handshake is not performed.
Step 4: Expose a Local Service Through the mTLS Tunnel
After registration, connect a local service through the mutually authenticated tunnel. To expose the device’s SSH service:
socketxp connect tcp://127.0.0.1:22 \ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_server.crt \ --key /var/lib/socketxp/tls_server.key
To expose multiple services (SSH and an embedded web interface):
socketxp connect tcp://127.0.0.1:22 \ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_server.crt \ --key /var/lib/socketxp/tls_server.key & socketxp connect http://127.0.0.1:8080 \ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_server.crt \ --key /var/lib/socketxp/tls_server.key
Step 5: Configure the Agent Persistently via config.json
For production deployments where the agent runs as a systemd service, put the mTLS configuration in /etc/socketxp/config.json:
{
"gateway_port": 9444,
"mtls": {
"enable": true,
"cert": "/var/lib/socketxp/tls_server.crt",
"key": "/var/lib/socketxp/tls_server.key"
},
"tunnels": [
{
"destination": "tcp://127.0.0.1:22"
},
{
"destination": "http://127.0.0.1:8080"
}
]
}
Install and enable the agent as a system service so it starts automatically on boot and reconnects with mTLS after any reboot or network interruption:
sudo socketxp service install --config /etc/socketxp/config.json sudo systemctl enable socketxp sudo systemctl start socketxp # Verify it is running sudo systemctl status socketxp
Step 6: Set Up Operator Access with IoT Slave Mode
When a developer or field engineer needs to connect to a device in the fleet, they authenticate with a short-lived 24-hour user client certificate — the operator-facing side of the mTLS channel.
On the operator’s machine, obtain a user client certificate:
sudo socketxp ca login--client "[email protected]"
This generates tls_client.crt and tls_client.key in /var/lib/socketxp/. The certificate is valid for 24 hours and expires automatically.
Connect to a specific device in IoT Slave Mode:
sudo socketxp connect tcp://127.0.0.1:2222 \ --iot-slave \ --peer-device-id\ --peer-device-port 22 \ --authtoken \ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_client.crt \ --key /var/lib/socketxp/tls_client.key
The <device-id> is the unique device identifier visible in the SocketXP portal. After running this command, SSH to the local port:
ssh -p 2222 pi@localhost
The connection is tunneled through the SocketXP gateway to the remote device’s SSH service, with both sides (operator and gateway, device and gateway) mutually authenticated via their respective certificates.
Step 7: Verify the mTLS Handshake Is Working
Confirm that mTLS is enforced correctly. Attempt to connect to port 9444 without a client certificate — the gateway should reject the connection:
# This should FAIL — no client certificate provided openssl s_client -connect gateway.socketxp.com:9444 -brief # Expected: handshake failure or certificate_required # This should SUCCEED — device certificate provided openssl s_client \ -connect gateway.socketxp.com:9444 \ -cert /var/lib/socketxp/tls_server.crt \ -key /var/lib/socketxp/tls_server.key \ -brief # Expected: CONNECTION ESTABLISHED, Verification: OK
Automating mTLS Certificate Issuance Across a Fleet
For a fleet of hundreds or thousands of devices, run socketxp ca login --server as part of the device provisioning script that executes at first boot:
#!/bin/bash # first_boot_provisioning.sh # Runs once at first network connection AUTH_TOKEN="" DEVICE_NAME="$(hostname)-$(cat /etc/machine-id | head -c 8)" # Obtain device certificate from BastionXP CA module sudo socketxp ca login "${AUTH_TOKEN}" --server "${DEVICE_NAME}" if [ $? -ne 0 ]; then echo "Certificate issuance failed. Will retry on next boot." exit 1 fi # Register on mTLS port socketxp login "${AUTH_TOKEN}" \ --gateway-port 9444 \ --mtls \ --cert /var/lib/socketxp/tls_client.crt \ --key /var/lib/socketxp/tls_client.key # Start the persistent service sudo systemctl start socketxp # Self-delete after successful provisioning rm -f "$0"
This script integrates naturally with SocketXP’s zero-touch provisioning workflow: embed it in a golden disk image, and each cloned device generates its own unique certificate on first boot.
What Changes After Enabling mTLS
Once your fleet is on port 9444 with mTLS:
- Unauthenticated devices are rejected at the TLS layer. A decommissioned device, a cloned device, or an attacker using captured firmware cannot establish a tunnel connection. The mTLS handshake fails before any data flows.
- Operator access is time-bounded. User client certificates expire every 24 hours. There are no long-lived shared credentials that can be extracted and reused indefinitely.
- Each device has a unique cryptographic identity. Audit logs in the SocketXP portal tie every management action to a specific, individually authenticated device — not just an IP address or a shared API key.
Next Steps
- Scaling mTLS IoT Security: The Complete Developer Guide — hub page covering PKI design, certificate lifecycle, CRL/OCSP/SCEP, and BastionXP as an alternate CA
- Automating IoT Certificate Rotation with mTLS — keeping certificates current at fleet scale
- MQTT mTLS Authentication Setup — applying mTLS to your MQTT messaging layer
- Zero-Touch Provisioning for IoT Devices — fleet-scale device onboarding with automatic certificate issuance
