Single IP, Multiple Domains and Host

I am trying to get SSL Passthrough working, I have:

  • a single IP address
  • Domains are fronted by Cloudflare
  • multiple domains i.e. www.domaina.com & www.999domainb.com
  • I have 2 hosts both running the same version of Traefik 2.5, both on the same backend network
  • I want Host A to deal with all requests from www.domaina.com & pass through www.999domainb.com to Host B
  • Host B to deal with www.999domainb.com
  • Docker config is not Swarm mode as Host B is not always available

Traefik definition for Host A & B

services:
  ############################# FRONTENDS

  # Traefik 2 - Reverse Proxy
  traefik:
    container_name: traefik
    hostname: traefik
    image: traefik:v2.5.6 # traefik:livarot # picodon v2.3.x # chevrotin v2.2.x
    # image: traefik:v2.4.7 # :picodon # chevrotin # the chevrotin tag refers to v2.2.x
    restart: unless-stopped
    command: # CLI arguments
      - --global.checkNewVersion=false
      - --global.sendAnonymousUsage=false
      - --entryPoints.http.address=:80
      - --entryPoints.https.address=:443
      - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22
      - --entryPoints.traefik.address=:8080 # 8093
      # - --entryPoints.ping.address=:8081
      - --api=true
      - --api.insecure=true
      - --api.dashboard=true
      #- --ping=true
      - --pilot.token=$TRAEFIK_PILOT_TOKEN
      # - --serversTransport.insecureSkipVerify=true
      - --log=true
      - --log.level=Debug # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
      - --accessLog=true
      - --accessLog.filePath=/logs/access.log
      - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
      - --accessLog.filters.statusCodes=200,300-302,400-499
      - --accesslog.format=json
      - --accesslog.filters.retryattempts
      - --accesslog.filters.minduration=10ms
      - --accesslog.fields.defaultmode=keep
      - --accesslog.fields.names.ClientUsername=drop
      - --accesslog.fields.headers.defaultmode=keep
      - --accesslog.fields.headers.names.User-Agent=redact
      - --accesslog.fields.headers.names.Authorization=drop
      - --accesslog.fields.headers.names.Content-Type=keep
      - --providers.docker=true
      - --providers.docker.endpoint=tcp://socket-proxy:2375
      # Automatically set Host rule for services
      - --providers.docker.exposedByDefault=false
      # - --entrypoints.https.http.middlewares=chain-oauth@file
      - --entrypoints.https.http.tls.options=tls-opts@file
      # Add dns-cloudflare as default certresolver for all services. Also enables TLS and no need to specify on individual services
      - --entrypoints.https.http.tls.certresolver=dns-cloudflare
      - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME0
      - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME0
      # - --entrypoints.https.http.tls.domains[1].main=$DOMAINNAME1 # Pulls main cert for second domain
      # - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAINNAME1 # Pulls wildcard cert for second domain
      - --providers.docker.network=t2_proxy
      - --providers.docker.swarmMode=false
      - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory
      # - --providers.file.filename=/path/to/file # Load dynamic configuration from a file
      - --providers.file.watch=true # Only works on top level files in the rules folder
      # Acme settings
      # - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
      # ## ACME info
      - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
      - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
      # ## DNS Challenge
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 # To delay DNS check and reduce LE hitrate
    networks:
      t2_proxy:
        # ipv4_address: xxx.xxx.xxx.xxx # You can specify a static IP
      socket_proxy:
        # ipv4_address: xxx.xxx.xxx.xxx
    security_opt:
      - no-new-privileges:true
    #healthcheck:
    #  test: ["CMD", "traefik", "healthcheck", "--ping"]
    #  interval: 5s
    #  retries: 3
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: host
      #- target: 8081
      #  published: 8082
      #  protocol: tcp
      #  mode: host
    volumes:
      - $DOCKERDIR/traefik2/rules:/rules # file provider directory
      - $DOCKERDIR/traefik2/acme/acme.json:/acme/acme.json # cert location - you must touch this file and change permissions to 600
      - $DOCKERDIR/traefik2/traefik.log:/logs/traefik.log # for fail2ban - make sure to touch file before starting container
      - $DOCKERDIR/traefik2/access.log:/logs/access.log
      - $DOCKERDIR/shared:/shared
    environment:
      - CF_API_EMAIL_FILE=/run/secrets/cloudflare_email
      - CF_API_KEY_FILE=/run/secrets/cloudflare_api_key
    secrets:
      - cloudflare_email
      - cloudflare_api_key
    labels:
      #- "autoheal=true"
      - "traefik.enable=true"
      # HTTP-to-HTTPS Redirect
      - "traefik.http.routers.http-catchall.entrypoints=http"
      - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME0`)"
      ## Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      ## Healthcheck/ping
      #- "traefik.http.routers.ping.rule=HostHeader(`traefik.$DOMAINNAME0`) && Path(`/ping`)"
      #- "traefik.http.routers.ping.tls=true"
      #- "traefik.http.routers.ping.service=ping@internal"
      ## Middlewares
      # - "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file"
      - "traefik.http.routers.traefik-rtr.middlewares=chain-authelia@file"
      # portainer labels
      - system=true
      - systemservices=true

Domain passthrough yaml config

tcp:
  routers:
    development-rtr:
      entryPoints:
        - "https"
      rule: "HostSNI(`*.999domainb.com.`,`app1.999domainb.com`,`app2.999domainb.com`,`www.999domainb.com`)"
      service: development-svc
      tls:
        passthrough: true
  services:
    development-svc:
      loadBalancer:
        servers:
          - address: "xxx.xxx.xxx.hostb:80"  # or whatever your external host's IP:port is
          - address: "xxx.xxx.xxx.hostb:443"

Image of what I am trying to achieve (sorry it's not perfect)

When I have tried to set this up I do not see errors in logs but Cloudflare says the host is unavailable.

Just an update to this i have since doing upgraded my firewall which has haproxy. it offloads to both, while I have not checked my configuration shown above to get it working I believe the answer is to make sure on the Treaefik devices that are receiving from another proxy do not forget to add the following config.

  # behind haproxy
  - --entryPoints.https.proxyProtocol.insecure
  - --entryPoints.https.proxyProtocol.trustedIPs=xxx.xxx.xxx.xxx/xx

hope this will help someone else

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.