
TLS and Mutual TLS
Secure your mesh with TLS encryption and mutual authentication.
TLS Basics
All Muti Metroo peer connections use TLS 1.3:
- Encryption: AES-256-GCM or ChaCha20-Poly1305
- Key Exchange: ECDHE with X25519 or P-256
- Authentication: ECDSA certificates (EC-only, RSA not supported)
- Forward Secrecy: New keys per session
Global TLS Configuration
TLS is configured once in the global tls: section and automatically used by all listeners and peer connections:
tls:
ca: "./certs/ca.crt" # CA for verifying peers and clients
cert: "./certs/agent.crt" # Agent's identity certificate
key: "./certs/agent.key" # Agent's private key
mtls: true # Enable mutual TLS on listeners
Server Authentication (TLS)
Basic TLS validates the server's certificate. With mtls: false, listeners accept any connecting peer:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: false # Don't require client certs
listeners:
- transport: quic
address: "0.0.0.0:4433"
peers:
- id: "abc123..."
transport: quic
address: "peer.example.com:4433"
# Uses global CA to validate server, global cert as client cert
What This Provides
- Server identity verified
- Client can trust it's connecting to the right agent
- Traffic encrypted
- Peers still present certificates (using global cert)
What This Does NOT Provide
- No mandatory validation of client identity on listeners
- Any client can connect (if they can reach the port)
Mutual TLS (mTLS)
mTLS requires both sides to present valid certificates. Enable it globally:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true # Require client certs on listeners
With mTLS enabled:
- Listeners require connecting peers to present valid certificates
- The global CA is used to verify client certificates
- Peers automatically use the global agent certificate as their client certificate
What mTLS Provides
- Mutual authentication (both sides verified)
- Only authorized peers can connect
- Strong defense against unauthorized access
- Certificate-based access control
EC-Only Certificates
Important: Muti Metroo only accepts EC (Elliptic Curve) certificates. RSA certificates are rejected.
# Generate EC certificates using the CLI
muti-metroo cert ca -n "My Mesh CA" -o ./certs
muti-metroo cert agent -n "agent-1" \
--ca ./certs/ca.crt \
--ca-key ./certs/ca.key \
-o ./certs
The only exception is WebSocket connections through a proxy - external servers may use any certificate type since mTLS is not available through proxies.
Certificate Types
CA Certificate
Signs all other certificates. Never share the private key:
muti-metroo cert ca -n "My Mesh CA" -o ./certs
# Files created:
# ./certs/ca.crt - Share with all agents
# ./certs/ca.key - KEEP SECRET!
Agent Certificate
Used for both server and client authentication:
muti-metroo cert agent -n "agent-1" \
--ca ./certs/ca.crt \
--ca-key ./certs/ca.key \
--dns "agent1.example.com" \
--ip "192.168.1.10" \
-o ./certs
Features:
- Extended Key Usage: Server Authentication, Client Authentication
- Used by listeners for server TLS
- Used by peers as client certificate for mTLS
Configuration Examples
Development (mTLS Disabled)
tls:
ca: "./dev-certs/ca.crt"
cert: "./dev-certs/agent.crt"
key: "./dev-certs/agent.key"
mtls: false # Disable for easier development
listeners:
- transport: quic
address: "0.0.0.0:4433"
Production (Full mTLS)
tls:
ca: "/etc/muti-metroo/certs/ca.crt"
cert: "/etc/muti-metroo/certs/agent.crt"
key: "/etc/muti-metroo/certs/agent.key"
mtls: true
listeners:
- transport: quic
address: "0.0.0.0:4433"
peers:
- id: "abc123..."
transport: quic
address: "peer.example.com:4433"
Per-Listener Override
Disable mTLS for a specific listener:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true # Global default
listeners:
# Uses global mTLS setting
- transport: quic
address: "0.0.0.0:4433"
# Override: disable mTLS for this listener
- transport: h2
address: "0.0.0.0:8443"
tls:
mtls: false
Kubernetes (Inline Certs)
tls:
ca_pem: "${CA_CRT}"
cert_pem: "${TLS_CRT}"
key_pem: "${TLS_KEY}"
mtls: true
listeners:
- transport: quic
address: "0.0.0.0:4433"
Certificate Validation
What's Validated
- Certificate signature (signed by trusted CA)
- Validity period (not expired, not future)
- Subject Alternative Names (hostname/IP matches)
- Key usage (appropriate for server/client)
- Key type (must be ECDSA)
Peer ID Validation
In addition to TLS, Muti Metroo validates the peer's Agent ID:
peers:
- id: "abc123def456..." # Expected Agent ID
This provides defense-in-depth: even if an attacker has a valid certificate, they must also have the correct Agent ID.
Troubleshooting
Certificate Not Trusted
Error: x509: certificate signed by unknown authority
- Verify CA certificate is correct
- Check CA was used to sign the certificate:
openssl verify -CAfile ca.crt agent.crt
Certificate Expired
Error: x509: certificate has expired
- Check expiration:
openssl x509 -enddate -noout -in agent.crt - Generate new certificate
Name Mismatch
Error: x509: certificate is valid for agent1.example.com, not agent2.example.com
- Use correct hostname in peer address
- Generate certificate with correct SANs
RSA Certificate Rejected
Error: certificate must use ECDSA, got RSA
- Muti Metroo only accepts EC certificates
- Regenerate using ECDSA:
muti-metroo cert agent -n "agent-1" \
--ca ./certs/ca.crt \
--ca-key ./certs/ca.key \
-o ./certs
Client Certificate Required
Error: tls: client didn't provide a certificate
- The listener has mTLS enabled
- Connecting peer must have a valid certificate configured
- Check global
tls.certandtls.keyare set
Best Practices
- Always use mTLS in production
- Use EC certificates only (RSA is not supported)
- Protect CA private key (HSM, vault, or encrypted storage)
- Use short certificate validity (90-365 days)
- Automate certificate rotation
- Include all necessary SANs when generating certs
- Monitor certificate expiration
- Revoke compromised certificates immediately
Next Steps
- Authentication - Additional authentication layers
- TLS Certificates - Configuration reference
- Best Practices - Production hardening