TLS Transport
The TLS transport provides encrypted communication with optional mutual TLS (mTLS) authentication for secure cross-datacenter and external service communication.
Overview
| Property | Value |
|---|---|
| Plugin Assembly | StellaOps.Router.Transport.Tls.dll |
| Transport Name | tls |
| Default Port | 5101 |
| Security | TLS 1.3, optional mTLS |
| Use Case | Cross-datacenter, external services, compliance-required environments |
Configuration
router.yaml (Gateway/Server)
Router:
Transport:
Type: tls
Tls:
Host: "0.0.0.0"
Port: 5101
CertificatePath: /certs/server.pfx
CertificatePassword: ${TLS_CERT_PASSWORD:-}
RequireClientCertificate: true # Enable mTLS
AllowedClientCertificates:
- /certs/trusted/client1.cer
- /certs/trusted/client2.cer
TlsProtocols: Tls13 # TLS 1.3 only
CheckCertificateRevocation: true
microservice.yaml (Client)
routers:
- host: gateway.external.company.com
port: 5101
transportType: Tls
priority: 1
tls:
clientCertificatePath: /certs/client.pfx
clientCertificatePassword: ${CLIENT_CERT_PASSWORD:-}
validateServerCertificate: true
serverCertificateThumbprints:
- "A1B2C3D4E5F6..."
Environment Variables
ROUTER__TRANSPORT__TYPE=tls
ROUTER__TRANSPORT__TLS__PORT=5101
ROUTER__TRANSPORT__TLS__CERTIFICATEPATH=/certs/server.pfx
ROUTER__TRANSPORT__TLS__CERTIFICATEPASSWORD=secret
ROUTER__TRANSPORT__TLS__REQUIRECLIENTCERTIFICATE=true
Options Reference
Server Options
| Option | Type | Default | Description |
|---|---|---|---|
Host | string | 0.0.0.0 | Bind address |
Port | int | 5101 | TLS port number |
CertificatePath | string | - | Path to server certificate (PFX/P12) |
CertificatePassword | string | - | Password for certificate file |
RequireClientCertificate | bool | false | Enable mutual TLS |
AllowedClientCertificates | string[] | - | Paths to trusted client certs |
TlsProtocols | TlsProtocols | Tls12,Tls13 | Allowed TLS versions |
CheckCertificateRevocation | bool | true | Check CRL/OCSP |
CipherSuites | string[] | - | Allowed cipher suites (TLS 1.3) |
Client Options
| Option | Type | Default | Description |
|---|---|---|---|
ClientCertificatePath | string | - | Path to client certificate (PFX/P12) |
ClientCertificatePassword | string | - | Password for client certificate |
ValidateServerCertificate | bool | true | Validate server certificate |
ServerCertificateThumbprints | string[] | - | Pinned server cert thumbprints |
AllowUntrustedCertificates | bool | false | Allow self-signed certs (dev only) |
Mutual TLS (mTLS)
For zero-trust environments, enable mutual TLS authentication:
┌──────────────────┐ ┌──────────────────┐
│ Microservice │ │ Gateway │
│ │ │ │
│ Client Cert │◄───── TLS ────────►│ Server Cert │
│ (identity) │ Handshake │ (identity) │
│ │ │ │
│ Validates: │ │ Validates: │
│ - Server cert │ │ - Client cert │
│ - Thumbprint │ │ - Allowlist │
└──────────────────┘ └──────────────────┘
Certificate Requirements
Server Certificate:
- Extended Key Usage:
Server Authentication (1.3.6.1.5.5.7.3.1) - Subject Alternative Name: Include all DNS names clients will connect to
Client Certificate:
- Extended Key Usage:
Client Authentication (1.3.6.1.5.5.7.3.2) - Common Name or SAN identifying the service
Performance Characteristics
| Metric | Typical Value |
|---|---|
| Latency (p50) | < 2ms |
| Latency (p99) | < 10ms |
| Throughput | 80,000+ rps |
| Memory per connection | ~8KB |
TLS 1.3 with session resumption on 10Gbps network
Certificate Management
Generating Certificates
# Generate CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/CN=StellaOps Internal CA"
# Generate server certificate
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
-subj "/CN=gateway.internal" \
-addext "subjectAltName=DNS:gateway.internal,DNS:localhost"
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt \
-extfile <(echo "subjectAltName=DNS:gateway.internal,DNS:localhost")
# Package as PFX
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt \
-certfile ca.crt -passout pass:changeit
Certificate Rotation
- Generate new certificate before expiry
- Update
CertificatePathin configuration - Restart Gateway (no connection interruption with graceful shutdown)
- Update client thumbprint pins if using certificate pinning
TLS Validation Contract (post-C8 hardening)
As of sprint SPRINT_20260501_013 (audit finding C8), the TLS transport enforces strict validation rules on every handshake. The full contract is documented in Router architecture, “TLS Validation Contract”; the highlights:
- Hostname mismatch is always fatal. Even with
AllowSelfSigned=trueand a matching pin, aRemoteCertificateNameMismatchis rejected unconditionally. AllowSelfSigned=truerequires a pin set. Construction ofTlsTransportServer/TlsTransportClientthrows ifCertificatePinningis empty in this configuration. Any pre-C8 compose file that setAllowSelfSigned: truewithout pinning will fail at startup.- Pinning is any-of: thumbprint OR subject OR SAN. Use thumbprint pinning in production-like environments (tightest posture); subject pinning to a private CA is appropriate when leaf certs rotate frequently.
Self-signed + pinning (worked example)
For a development cluster issuing leaf certs from a private CA where each microservice presents a self-signed cert:
# router.yaml — gateway side accepting microservice mTLS clients
Router:
Transport:
Type: tls
Tls:
Host: "0.0.0.0"
Port: 5101
ServerCertificatePath: /certs/gateway.pfx
ServerCertificatePassword: ${TLS_CERT_PASSWORD:-}
RequireClientCertificate: true
AllowSelfSigned: true
CertificatePinning:
# Tightest posture — list each microservice's leaf SHA-256 thumbprint.
ThumbprintsSha256:
- "F2A1B3C4D5E6F708091A2B3C4D5E6F708091A2B3C4D5E6F708091A2B3C4D5E6F"
- "A1B2C3D4E5F60718293A4B5C6D7E8F90A1B2C3D4E5F60718293A4B5C6D7E8F90"
# OR pin the private CA subject so leaf rotation does not require config updates:
# AllowedSubjects:
# - "CN=stellaops-internal-ca, O=stellaops"
# microservice.yaml — service validating the gateway
routers:
- host: gateway.stellaops.local
port: 5101
transportType: Tls
priority: 1
tls:
clientCertificatePath: /certs/service.pfx
clientCertificatePassword: ${CLIENT_CERT_PASSWORD:-}
AllowSelfSigned: true
CertificatePinning:
ThumbprintsSha256:
- "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"
Compose-style env vars:
ROUTER__TRANSPORT__TLS__ALLOWSELFSIGNED=true
ROUTER__TRANSPORT__TLS__CERTIFICATEPINNING__THUMBPRINTSSHA256__0=F2A1B3...
ROUTER__TRANSPORT__TLS__CERTIFICATEPINNING__THUMBPRINTSSHA256__1=A1B2C3...
To compute a SHA-256 thumbprint matching the format expected by the pin set:
openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -hex \
| awk '{print toupper($2)}'
Separators (:, -, spaces) and lower-case input are accepted — the validator normalises to upper-case hex with no separators before comparison.
Migration from the pre-C8 permissive validator
If a previous deployment ran with AllowSelfSigned: true and no pinning, the service will now fail to start with:
TlsTransportOptions: AllowSelfSigned=true requires at least one of
CertificatePinning.ThumbprintsSha256, CertificatePinning.AllowedSubjects, or
CertificatePinning.AllowedSans to be populated.
Two recovery paths:
- Tighten (recommended): compute the leaf thumbprint(s) and add them to
CertificatePinning.ThumbprintsSha256. This restores the previous acceptance behaviour for the specific certs in use, but rejects any other self-signed cert that may be presented. - Disable self-signed acceptance: set
AllowSelfSigned: falseand rely on a properly trusted CA. Required for production.
Air-Gap Deployment
For offline environments:
- Pre-provision all certificates
- Disable CRL/OCSP checks:
CheckCertificateRevocation: false - Use certificate pinning instead of chain validation
Router:
Transport:
Type: tls
Tls:
CheckCertificateRevocation: false
AllowedClientCertificates:
- /certs/trusted/client1.cer
Troubleshooting
Certificate Validation Failed
Error: The remote certificate is invalid according to the validation procedure
- Verify certificate is not expired:
openssl x509 -in cert.pem -noout -dates - Check certificate chain is complete
- Verify CA is trusted by the system or explicitly configured
mTLS Handshake Failed
Error: The client certificate is not provided
- Ensure client certificate is configured with correct path
- Verify certificate has Client Authentication EKU
- Check certificate is in Gateway’s allowlist
TLS Protocol Mismatch
Error: A call to SSPI failed, TLS version mismatch
- Ensure both sides support compatible TLS versions
- Update
TlsProtocolsto include common version - TLS 1.3 recommended for new deployments
Compliance
The TLS transport supports compliance requirements:
| Standard | Configuration |
|---|---|
| PCI-DSS | TLS 1.2+, strong ciphers, certificate validation |
| HIPAA | TLS 1.2+, mTLS for service-to-service |
| FedRAMP | TLS 1.3, FIPS-validated crypto modules |
For FIPS mode, ensure .NET is configured for FIPS compliance and use FIPS-approved cipher suites.
See Also
- TCP Transport - Unencrypted variant for internal use
- Transport Overview
- Security Hardening Guide
