Home > IoT > How to Implement mTLS in IoT: A Step-by-Step Guide

How to Implement mTLS in IoT: A Step-by-Step Guide

Author: Ganesh Velrajan

Last Updated: Jul 28, 2026

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:

PortModeWhat it enforces
9443Standard TLSServer-only authentication — device verifies gateway, gateway does NOT verify device certificate
9444Mutual 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

SocketXP IoT Remote Access and Device Management Platform

Remotely access, manage, and update your IoT & AIoT edge fleet with SocketXP's secure and scalable platform.

Start Your Free Trial Now!

Join thousands of satisfied users who trust SocketXP for a secure, reliable, and scalable IoT Edge device management solution. Start your free trial now.