Skip to content

TLS SNI Router & Filter (tls_sni) ​

The TLS SNI Plugin extracts the Server Name Indication (SNI) extension from raw TLS ClientHello packets at Layer 4 without decrypting or terminating TLS certificates. This enables operators to enforce domain allowlists/blocklists, prevent malware command-and-control access, and route encrypted traffic to backends with zero cryptographic overhead and zero access to private keys.


Capabilities & Threat Defense ​

Threat / Attack VectorDefense MechanismAction Taken
Unauthorized Domain ProbingInspects TLS ClientHello SNI extensionConnection dropped before TLS handshake completes
Malicious Outbound / C2 ConnectionsFilters SNI against blocked_domainsConnection terminated immediately
Unencrypted Traffic on TLS PortValidates TLS record header (0x16 0x03)Non-TLS traffic immediately rejected
Private Key ExposurePure zero-decryption Layer 4 inspectionNever requires certificates or private keys

Installation ​

Install the plugin via CLI or declaratively:

# Install using short nametcp-warden plugins install tls_sni# Or install via Git repository URLtcp-warden plugins install https://github.com/routewarden/plugins/tls_sni

Configuration Reference ​

Add a TLS SNI guard service to tcp-warden.yaml:

services:  tls_proxy:    listen: ":8443"    upstream: "127.0.0.1:443"    protocol: "tls"    rate_limit:      connections_per_minute: 120      burst: 20    plugin_config:      allowed_domains:        - "*.routewarden.io"        - "routewarden.io"        - "api.internal"      blocked_domains:        - "*.malware.example"        - "c2.threat.org"

Configuration Options ​

FieldTypeDefaultDescription
listenstring":8443"Local proxy listen address and port.
upstreamstring"127.0.0.1:443"Target TLS service or downstream reverse proxy.
protocolstring"tls"Must be set to "tls", "tls-sni", or "sni".
plugin_config.allowed_domains[]string[]List of allowed domain patterns (supports wildcards *.domain.com). If empty, all unblocked domains are allowed.
plugin_config.blocked_domains[]string[]List of explicitly blocked domain patterns.

Network & Deployment Architecture ​

Option A: Kernel Firewall Redirection (nftables / iptables) ​

Redirect incoming external HTTPS/TLS traffic on port 443 to RouteWarden port 8443:

# Redirect incoming external HTTPS/TLS traffic on port 443 to RouteWarden port 8443sudo nft add rule ip routewarden_nat prerouting iifname "eth0" tcp dport 443 redirect to :8443

Option B: Docker Compose Network Isolation ​

Route encrypted TLS traffic to an internal TLS-terminating container without exposing the backend directly:

services:  routewarden:    image: ghcr.io/routewarden/tcp-warden:latest    ports:      - "443:8443"  # Map host HTTPS/TLS port 443 to RouteWarden      - "9091:9091" # Management API    volumes:      - ./tcp-warden.yaml:/etc/routewarden/tcp-warden.yaml:ro    depends_on:      - web-tls  web-tls:    image: caddy:alpine    # Do NOT publish host ports; RouteWarden transparently routes TLS SNI upstream

Testing & Verification ​

Verify allowed domains, test blocked domains, and verify immediate drop of non-TLS connections:

# Test allowed domain through SNI proxycurl -vk --resolve routewarden.io:8443:127.0.0.1 https://routewarden.io:8443/

Released under the MIT License.