feat: configure sni tcp routes

This commit is contained in:
Alfredo Di Stasio
2026-06-30 10:00:45 +02:00
parent 7dfc23d69e
commit b5beb27623
5 changed files with 52 additions and 16 deletions
+11 -5
View File
@@ -12,19 +12,25 @@ Docker Compose deployment for Traefik used as a TCP load balancer with TLS passt
## Configuration
Edit backend targets in `config/dynamic/tcp-services.yml`:
Edit SNI routes and backend targets in `config/dynamic/tcp-services.yml`:
```yaml
tcp:
routers:
lab-younerd:
rule: "HostSNI(`lab.younerd.org`)"
service: lab-younerd
tls:
passthrough: true
services:
ssl-backends:
lab-younerd:
loadBalancer:
servers:
- address: "192.0.2.10:443"
- address: "192.0.2.11:443"
- address: "host.docker.internal:8443"
```
The example addresses use the documentation-only `192.0.2.0/24` range. Replace them with the real backend IP addresses and ports before deploying. If a backend listens on the Docker host itself, use `host.docker.internal:PORT`.
`HostSNI(...)` matches the hostname sent by the client during the TLS handshake. If a backend listens on the Docker host itself, use `host.docker.internal:PORT`.
## Run
+18 -6
View File
@@ -1,16 +1,28 @@
tcp:
routers:
tls-passthrough:
lab-younerd:
entryPoints:
- tls
rule: "HostSNI(`*`)"
service: ssl-backends
rule: "HostSNI(`lab.younerd.org`)"
service: lab-younerd
tls:
passthrough: true
azionelab:
entryPoints:
- tls
rule: "HostSNI(`azionelab.org`) || HostSNI(`www.azionelab.org`)"
service: azionelab
tls:
passthrough: true
services:
ssl-backends:
lab-younerd:
loadBalancer:
servers:
- address: "192.0.2.10:443"
- address: "192.0.2.11:443"
- address: "host.docker.internal:8443"
azionelab:
loadBalancer:
servers:
- address: "host.docker.internal:9443"
+13 -3
View File
@@ -8,12 +8,22 @@
## Configuration
Update `config/dynamic/tcp-services.yml` with the real backend addresses:
Update `config/dynamic/tcp-services.yml` with the required SNI hostnames and backend addresses:
```yaml
tcp:
routers:
example:
rule: "HostSNI(`example.org`)"
service: example
tls:
passthrough: true
services:
example:
loadBalancer:
servers:
- address: "10.0.0.10:443"
- address: "10.0.0.11:443"
- address: "host.docker.internal:8443"
```
If a backend listens on the Docker host, use `host.docker.internal:PORT`. Compose maps that name through Docker's `host-gateway` feature.
+1 -1
View File
@@ -54,4 +54,4 @@ For backends running on the Docker host, use `host.docker.internal:PORT` rather
- TLS passthrough prevents Traefik from inspecting HTTP paths, headers, or certificate contents.
- Backend certificates and renewal jobs must be monitored on each backend.
- The default configuration routes all SNI names to the same backend pool. Use more specific `HostSNI(...)` rules if different names need different pools.
- SNI routing depends on clients sending the expected hostname during the TLS handshake. Clients that connect by IP address or omit SNI will not match hostname-specific routers.
+8
View File
@@ -20,6 +20,14 @@ openssl s_client -connect LOAD_BALANCER_HOST:443 -servername EXPECTED_DNS_NAME
The certificate shown by `openssl` should be the backend certificate, not a certificate stored by Traefik.
For the included SNI example:
```bash
openssl s_client -connect LOAD_BALANCER_HOST:443 -servername lab.younerd.org
openssl s_client -connect LOAD_BALANCER_HOST:443 -servername azionelab.org
openssl s_client -connect LOAD_BALANCER_HOST:443 -servername www.azionelab.org
```
## Test categories
- Docker/Compose validation: `docker compose config`.