Failing to get Synology NAS behind Traefik w/wildcard cert

I think i'm getting my networking piece with docker and traefik container configuration mixed up causing this problem where my NAS is still untrusted when i navigate to the URL.

My docker service is running on my Firewalla Gold which is also my router (DHCP) server. It's IP is 192.168.169.1/24 Firewalla Gold: Multi-Gigabit Cyber Security Firewall & Router Protect | Firewalla

(Firewalla) $ sudo docker network list
NETWORK ID          NAME                DRIVER              SCOPE
d0caa1dff116        bridge              bridge              local
0a1ebbb11363        host                host                local
258e4dfaef53        none                null                local
7ce54a31f032        pi-hole_default     bridge              local
b4811b1e7816        proxy               bridge              local
5e7b53f332b8        unifi_default       bridge              local

Proxy is the network defined for traefik using 172.18.0.1/16
Portainer is using IP 172.18.0.3

in this, i have successfully put Portainer behind it getting a wildcard from Cloudflare.

Also to note, i'm running pihole container with 172.16.0.2 and local DNS entries for traefik, portainer pointed to 172.18.0.2 (traefik) and this is working fine.

Now when i put my NAS (located in my LAN 192.168.169.161/24) in my rules, dashboard shows it like this but navigating to it is untrusted and still shows synology cert when inspecting.

I can ping my NAS from inside traefik container as well so this tells me routing is fine i think.

$ sudo docker network inspect bridge
[
{
"Name": "bridge",
"Id": "d0caa1dff1163676e16da802955ee692f8323c58722fcf7263696bf2affb412d",
"Created": "2023-01-03T16:50:13.207842281-10:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]

My firewalla IP is 192.168.169.1 as the GW for all my devices in my LAN.

Why i think this is happening is because i'm supposed to be using docker host network which would be 192.168.169.0/24 instead of proxy (which creates 172.18.0.3 automatically).

docker compose

version: '3'

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    environment:
      - CF_API_EMAIL=****
      - CF_DNS_API_TOKEN=****
      # - CF_API_KEY=YOU_API_KEY
      # be sure to use the correct one depending on if you are using a token or key
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /mnt/traefik/data/traefik.yml:/traefik.yml:ro
      - /mnt/traefik/data/acme.json:/acme.json
      - /mnt/traefik/data/config.yml:/config.yml:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard-internal.local.mydomain.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:****"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard-internal.local.mydomain.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
      - "traefik.http.routers.traefik-secure.tls.domains[0].main=local.mydomain.com"
      - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.local.mydomain.example.com"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true

config.yml

http:
  routers:
    dsm:
      entryPoints:
        - "https"
      rule: "Host(`nas.local.mydomain.home`)"
      middlewares:
        - default-headers
      tls: {}
      service: dsm

  services:
    dsm:
      loadBalancer:
        servers:
          - url: "https://192.168.169.161:5001"
        passHostHeader: true

  middlewares:

    default-headers:
      headers:
        frameDeny: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 15552000
        customFrameOptionsValue: SAMEORIGIN
        customRequestHeaders:
          X-Forwarded-Proto: https

    default-whitelist:
      ipWhiteList:
        sourceRange:
        - "10.0.0.0/24"
        - "192.168.0.0/16"
        - "172.0.0.0/8"

    secured:
      chain:
        middlewares:
        - default-whitelist
        - default-headers

traefik.yml


api:
  dashboard: true
  debug: true
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
serversTransport:
  insecureSkipVerify: true

log:
  level: DEBUG
  filePath: /traefik.log

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /config.yml
certificatesResolvers:
  cloudflare:
    acme:
      email: myemail
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        #disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

Am i thinking correctly here or way off on config?

You should assign your certresolver, too.

If you see a Synology cert I would think you have the Syno IP in your DNS and not connect to Traefik. If Traefik has the wrong cert (no LetsEncrypt), you would see a custom Traefik cert. Check you Traefik access logs.

1 Like

Thanks for the info. I added in the certResolver: cloudflare and no change.

Configured access.log and detail looks bleak.

when i nslookup my nas from my machine, it points to my syno IP. If i lookup on the nas.local.mydomain.home, shows my syno IP.

Hmm, are you saying i should change the local record in pihole from traefik IP to 192.168.169.161 instead? I thought anything put behind traefik should have the same local record > 172.18.0.2?

traefik.log shows:

time="2023-01-07T13:01:44-10:00" level=debug msg="Trying to challenge certificate for domain [nas.local.mydomain.home] found in HostSNI rule" providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.home`)"
time="2023-01-07T13:01:44-10:00" level=debug msg="Looking for provided certificate(s) to validate [\"local.mydomain.com\" \"*.local.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=cloudflare.acme
time="2023-01-07T13:01:44-10:00" level=debug msg="No ACME certificate generation required for domains [\"local.mydomain.com\" \"*.local.mydomain.com\"]." providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
time="2023-01-07T13:01:44-10:00" level=debug msg="Looking for provided certificate(s) to validate [\"nas.local.mydomain.home\"]..." providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.home`)"
time="2023-01-07T13:01:44-10:00" level=debug msg="No ACME certificate generation required for domains [\"nas.local.mydomain.home\"]." ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.home`)" providerName=cloudflare.acme
time="2023-01-07T13:01:44-10:00" level=debug msg="Using DNS Challenge provider: cloudflare" providerName=cloudflare.acme
time="2023-01-07T13:01:44-10:00" level=debug msg="legolog: [INFO] [nas.local.mydomain.home] acme: Obtaining bundled SAN certificate"
time="2023-01-07T13:01:44-10:00" level=error msg="Unable to obtain ACME certificate for domains \"nas.local.mydomain.home\": unable to generate a certificate for the domains [nas.local.mydomain.home]: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for \"nas.local.mydomain.home\": Domain name does not end with a valid public suffix (TLD)" providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" rule="Host(`nas.local.mydomain.home`)" routerName=dsm@file

my cloudflare DNS is set for

A record 'mydomain.com > WAN IP'
'CNAME * > mydomain.com'

So i changed the local record to nas.local.mydomain.com > 172.18.0.2 and recreated traefik.

logs


time="2023-01-07T13:36:32-10:00" level=debug msg="Creating server 0 https://192.168.169.161:5001" serviceName=dsm entryPointName=https routerName=dsm@file serverName=0
time="2023-01-07T13:36:32-10:00" level=debug msg="child https://192.168.169.161:5001 now UP"
time="2023-01-07T13:36:32-10:00" level=debug msg="Propagating new UP status"
time="2023-01-07T13:36:32-10:00" level=debug msg="Added outgoing tracing middleware dsm" routerName=dsm@file middlewareName=tracing middlewareType=TracingForwarder entryPointName=https
time="2023-01-07T13:36:32-10:00" level=debug msg="Creating middleware" routerName=dsm@file entryPointName=https middlewareType=Headers middlewareName=default-headers@file
time="2023-01-07T13:36:32-10:00" level=debug msg="Setting up secureHeaders from {map[X-Forwarded-Proto:https] map[] false [] [] [] [] [] 0 false [] [] false false  map[] false 15552000 true true true true SAMEORIGIN true true       false}" routerName=dsm@file entryPointName=https middlewareType=Headers middlewareName=default-headers@file
time="2023-01-07T13:36:32-10:00" level=debug msg="Setting up customHeaders/Cors from {map[X-Forwarded-Proto:https] map[] false [] [] [] [] [] 0 false [] [] false false  map[] false 15552000 true true true true SAMEORIGIN true true       false}" entryPointName=https middlewareType=Headers middlewareName=default-headers@file routerName=dsm@file
time="2023-01-07T13:36:32-10:00" level=debug msg="Adding tracing to middleware" entryPointName=https routerName=dsm@file middlewareName=default-headers@file
time="2023-01-07T13:36:32-10:00" level=debug msg="Creating middleware" entryPointName=https middlewareName=traefik-internal-recovery middlewareType=Recovery
time="2023-01-07T13:36:32-10:00" level=debug msg="Adding route for traefik-dashboard-internal.local.mydomain.com with TLS options default" entryPointName=https
time="2023-01-07T13:36:32-10:00" level=debug msg="Adding route for nas.local.mydomain.com with TLS options default" entryPointName=https
time="2023-01-07T13:36:32-10:00" level=debug msg="Adding route for portainer.local.mydomain.com with TLS options default" entryPointName=https
time="2023-01-07T13:36:32-10:00" level=debug msg="Trying to challenge certificate for domain [nas.local.mydomain.com] found in HostSNI rule" providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.com`)"
time="2023-01-07T13:36:32-10:00" level=debug msg="Looking for provided certificate(s) to validate [\"local.mydomain.com\" \"*.local.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=cloudflare.acme
time="2023-01-07T13:36:32-10:00" level=debug msg="Looking for provided certificate(s) to validate [\"nas.local.mydomain.com\"]..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.com`)" providerName=cloudflare.acme
time="2023-01-07T13:36:32-10:00" level=debug msg="No ACME certificate generation required for domains [\"local.mydomain.com\" \"*.local.mydomain.com\"]." providerName=cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
time="2023-01-07T13:36:32-10:00" level=debug msg="No ACME certificate generation required for domains [\"nas.local.mydomain.com\"]." ACME CA="https://acme-v02.api.letsencrypt.org/directory" routerName=dsm@file rule="Host(`nas.local.mydomain.com`)" providerName=cloudflare.acme

Same logs if i change local record in pihole to nas.local.mydomain.com > 192.168.169.161

In the docker compose file, under networks config, if the 'proxy' network created works for any services in same subnet 172.18.0.0/16, how can include services in other subnets like pihole running in 172.16.0.0/24 or my LAN NAS using 192.168.169.0/24?

networks:
default:
driver: bridge
t2_proxy:
name: t2_proxy
driver: bridge
ipam:
config:
- subnet: 192.168.169.0/24

This is a forum for Treafik reverse proxy, not for Docker networking :grinning:

For containers to be able to connect to each other, you place them on the same Docker network. Then you can access them via their container name, Docker provides automatic DNS service. If you have a basic networking service like pi-hole for DNS, you should probably assign a fixed IP to it.

More Docker questions? -> Check Reddit or Stackoverflow.

This is a slightly updated example for WireGuard with wg-easy and pi-hole. (Source):

version: "3.8"

services:
  wg-easy:
    environment:
      # ⚠️ Change the server's hostname (clients will connect to):
      - WG_HOST=wg.example.com

      # ⚠️ Change the Web UI Password:
      - PASSWORD=password

      # 💡 This is the Pi-Hole Container's IP Address
      - WG_DEFAULT_DNS=10.8.1.3
      - WG_DEFAULT_ADDRESS=10.8.0.x
    image: weejewel/wg-easy
    container_name: wg-easy
    volumes:
      - ~/.wg-easy:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
    networks:
      wg-easy:
        ipv4_address: 10.8.1.2

  pihole:
    image: pihole/pihole
    container_name: pihole
    environment:
      # ⚠️ Change the Web UI Password:
      - WEBPASSWORD=password
    volumes:
      - '~/.pihole/etc-pihole:/etc/pihole'
      - './.pihole/etc-dnsmasq.d:/etc/dnsmasq.d'
    ports:
      - "5353:80/tcp"
    restart: unless-stopped
    networks:
      wg-easy:
        ipv4_address: 10.8.1.3

networks:
  wg-easy:
    ipam:
      config:
        - subnet: 10.8.1.0/24