# Tcp router with tls and default certs

**URL:** <https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375>\
**Category:** Traefik v2\
**Tags:** docker\
**Created:** [February 5, 2024, 5:37pm UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375 "2024-02-05T17:37:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![youngt2](https://sea2.discourse-cdn.com/flex020/user_avatar/community.traefik.io/youngt2/32/6055_2.png) [@youngt2](https://community.traefik.io/u/youngt2)\
**Post date:** [February 5, 2024, 5:37pm UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375/1 "2024-02-05T17:37:53Z")

</div>

I am trying to use traefik to terminate a DNS-over-TLS server. Current using unbound because I was already using it.

I cannot get traefik to serve the proper certificate for this entrypoint. It only seems to serve the default traefik cert which results in an error due to mismatch. [This post](https://community.traefik.io/t/traefik-doesnt-route-tcp-host-sni/20851/6) seems similiar, but not quite and answer does't seem to help me.

relevant docker-compose.yml sections

```auto
services:
  unbound:
    container_name: unbound
    image: mvance/unbound:latest
    hostname: unbound
    networks:
      - dot-net
    ports:
      - 53:53/tcp
      - 53:53/udp
    environment:
      TZ: $TZ
    volumes:
      - ./unbound/unbound.conf:/opt/unbound/etc/unbound/unbound.conf
      - ./unbound/unbound.log:/opt/unbound/etc/unbound/unbound.log
    restart: unless-stopped
    labels:
      - traefik.enable=true
      - traefik.tcp.routers.dnsovertls.rule=HostSNI(`dot.$DOMAINNAME`)
      - traefik.tcp.routers.dnsovertls.entrypoints=dot
      - traefik.tcp.routers.dnsovertls.tls.certResolver=cloudflare
      - traefik.tcp.routers.dnsovertls.service=unbound
      - traefik.tcp.services.unbound.loadbalancer.server.port=53

  traefik:
    image: traefik:v3.0.0-beta5
    container_name: traefik
    logging:
      options:
        max-size: "3m"
        max-file: "3"
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - dot-net
    ports:
      - 80:80
      - 443:443
      - 853:853
      - 8082:8080
    secrets:
      - cf_dns_api
      - cf_zone_api_all
      - cf_api_email
    environment:
      - CF_ZONE_API_TOKEN_FILE=/run/secrets/cf_zone_api_all
      - CF_DNS_API_TOKEN_FILE=/run/secrets/cf_dns_api
      - CF_API_EMAIL_FILE=/run/secrets/cf_api_email
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik:/etc/traefik
    command:
      - --api.dashboard=true
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=dot-net
      - --providers.file.filename=/etc/traefik/dynamic-conf.yml
      - --log.level=DEBUG #DEBUG INFO WARN ERROR PANIC FATAL
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.dot.address=:853
      - --certificatesresolvers.cloudflare.acme.storage=/etc/traefik/acme.json
      - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
      - --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53

```

dynamic-conf.yml

```auto
tls:
  options:
    default:
      alpnProtocols:
        - http/1.1
        - h2
        - dot
        - acme-tls/1

```

Plain DNS resolution works:  
`dig +tcp @192.168.2.6 example.com` results in NOERROR and returned IP

dns-over-tls results in error:

```auto
kdig -d @192.168.2.6 +tls-ca +tls-host=dot.mydomain.com example.com
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(192.168.2.6), port(853), protocol(TCP)
;; DEBUG: TLS, imported 137 system certificates
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG: #1, CN=TRAEFIK DEFAULT CERT
;; DEBUG: SHA-256 PIN: Q3IXFGc1HQA5pgq462PVzUeHUT1op8utxDFNSy62jk4=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is NOT trusted. The certificate issuer is unknown. The name in the certificate does not match the expected.
;; WARNING: TLS, handshake failed (Error in the certificate.)
;; ERROR: failed to query server 192.168.2.6@853(TCP)

```

and in traefik I see:

```auto
2024-02-05T12:32:32-05:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:220 > Serving default certificate for request: ""
2024-02-05T12:32:32-05:00 DBG log/log.go:245 > http: TLS handshake error from 192.168.1.10:50785: read tcp 172.24.0.3:853->192.168.1.10:50785: read: connection reset by peer

```

Seems it sends the default certificate because there is no host name sent. Am I doing something wrong with my router?

I am able to get around this if I set the default certificate as my ACME certificate, because then the 'default' matches what my request is expecting, but I was hoping to avoid this.

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [February 5, 2024, 9:37pm UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375/2 "2024-02-05T21:37:21Z")

</div>

Does unbound show up in Traefik dashboard? How do you create the Docker network?

---

<div class="post-metadata">

**Author:** ![youngt2](https://sea2.discourse-cdn.com/flex020/user_avatar/community.traefik.io/youngt2/32/6055_2.png) [@youngt2](https://community.traefik.io/u/youngt2)\
**Post date:** [February 6, 2024, 1:28pm UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375/3 "2024-02-06T13:28:14Z")

</div>

> [bluepuma77](https://community.traefik.io/u/bluepuma77)
> 
> Does unbound show up in Traefik dashboard? How do you create the Docker network?

TCP router looks ok. See screenshots below.  
My simple docker network is setup in my compose:

```auto
version: '3.9'

networks:
  dot-net:
    name: dot-net

```

 ![image](https://us1.discourse-cdn.com/flex020/uploads/containo/original/2X/0/0435d651a24e35a03fc93a0e9ce5e194f4f6d0a4.png)

 ![image](https://us1.discourse-cdn.com/flex020/uploads/containo/original/2X/e/e6f4f327653ac637c67f2ea0b2501022dc98fae2.png)

I have no issues browsing a sample 'whoami' container through traefik as seen below. The proper LE cert is used.

```auto
  whoamilocal:
    image: traefik/whoami:v1.10.1
    container_name: whoamilocal
    restart: unless-stopped
    networks:
      - dot-net
    labels:
      - traefik.enable=true
      - traefik.http.routers.whoamilocal.rule=Host(`whoami.$DOMAINNAME`)
      - traefik.http.routers.whoamilocal.entrypoints=websecure

```

Are TCP routers supposed to recieve the HostSNI? Perhaps it is a problem with the way I'm testing my request. I tried doing a router with `HostSNI(*)` as I saw in some examples, but I guess that won't work with TLS connection.

---

<div class="post-metadata">

**Author:** ![youngt2](https://sea2.discourse-cdn.com/flex020/user_avatar/community.traefik.io/youngt2/32/6055_2.png) [@youngt2](https://community.traefik.io/u/youngt2)\
**Post date:** [March 25, 2024, 1:56am UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375/4 "2024-03-25T01:56:09Z")

</div>

@bluepuma77  
got any other ideas for this issue?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [March 26, 2024, 9:13am UTC](https://community.traefik.io/t/tcp-router-with-tls-and-default-certs/21375/5 "2024-03-26T09:13:15Z")

</div>

When using modern TLS, the domain should be included in the TLS request and `HostSNI()` should be able to read it.

Even when using with `*`, Traefik should still serve an existing matching cert, only then fall back to default.

What’s the default port for `DNS-over-TLS`?

Do you see a cert for `dot.<domain>` in `acme.json` file?

Compare to [simple Traefik TCP example](https://github.com/bluepuma77/traefik-best-practice/tree/main/docker-traefik-tcp).

Are you sure `kdig` command is correct?

Note that you don’t need `ports:` on unbound, Traefik should use the Docker network, within all ports are open.
