I have a DMZ vlan setup from services I port forward to. Everything else sits on another vlan. I have my regular LAN separate.
I am trying to accomplish a public facing traefik instance (that handle DMZ services), and this forwarding to internally facing traefik instance ( that manages the rest of services). I have two different entry points on the public facing (port 4043) traefik for external and internal services (port 443). I have firewall rules set to allow this flow between vlans.
The problem, I am unable to hit the internal 443 entry point without setting up a DNS overrride rule on my pfsense. This is too much work for each service. Am I missing something?
I don’t understand your setup.
You have Traefik 1 in DMZ, using port 4043 for public services?
Port 443 is forwarding all traffic to Traefik 2?
What’s the static and dynamic config? How do you create TLS certs? What’s the issue?
The idea is that I would like to separate my public facing reverse proxy physically from my internal servers. I would like to proxy all my services through this instance of Traefik for I own one domain. I have it working now to create firewall rules to allow traffic to my internal services but it is time consuming. I thought to have another internal traefik instance and make this one route anything internal. I created different ports of entry for my internal services to create some barrier from the public side of the internet. Here is my static config:
services:
# Traefik 3 - Reverse Proxy
traefik:
container_name: traefik
image: traefik:3.0
security_opt:
- no-new-privileges:true
restart: unless-stopped
profiles: ["core", "all"]
networks:
t3_proxy:
ipv4_address: 192.168.90.254 # You can specify a static IP
socket_proxy:
command: # CLI arguments
- --global.checkNewVersion=true
- --global.sendAnonymousUsage=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.traefik.address=:8080
# - --entrypoints.ping.address=:8081
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --api=true
- --api.dashboard=true
# - --api.insecure=true
# - --ping=true
# - --serversTransport.insecureSkipVerify=true
# Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
- --entrypoints.websecure.forwardedHeaders.trustedIPs=$CLOUDFLARE_IPS,$LOCAL_IPS
- --log=true
- --log.filePath=/logs/traefik.log
- --log.level=INFO # (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=204-299,400-499,500-599
- --providers.docker=true
# - --providers.docker.endpoint=unix:///var/run/docker.sock # Disable for Socket Proxy. Enable otherwise.
- --providers.docker.endpoint=tcp://socket-proxy:2375 # Enable for Socket Proxy. Disable otherwise.
- --providers.docker.exposedByDefault=false
- --providers.docker.network=t3_proxy
# - --providers.docker.swarmMode=false # Traefik v2 Swarm
# - --providers.swarm.endpoint=tcp://127.0.0.1:2377 # Traefik v3 Swarm
- --entrypoints.websecure.http.tls=true
- --entrypoints.websecure.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.websecure.http.tls.certresolver=dns-cloudflare
- --entrypoints.websecure.http.tls.domains[0].main=$DOMAINNAME_HS
- --entrypoints.websecure.http.tls.domains[0].sans=*.$DOMAINNAME_HS
- --entrypoints.websecure.http.tls.domains[1].main=$DOMAINNAME_1
- --entrypoints.websecure.http.tls.domains[1].sans=*.$DOMAINNAME_1
# - --entrypoints.websecure.http.tls.domains[2].main=$DOMAINNAME_2 # Pulls main cert for third domain
# - --entrypoints.websecure.http.tls.domains[2].sans=*.$DOMAINNAME_2 # Pulls wildcard cert for third domain
- --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory
- --providers.file.watch=true # Only works on top level files in the rules folder
# - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
- --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
- --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
# - --metrics.prometheus=true
# - --metrics.prometheus.buckets=0.1,0.3,1.2,5.0
# - --metrics.prometheus.addEntryPointsLabels=true
# - --metrics.prometheus.addrouterslabels=true
# - --metrics.prometheus.addServicesLabels=true
# - --metrics.influxdb2=true
# - --metrics.influxdb2.address=http://192.168.1.111:8086
# - --metrics.influxdb2.token=$INFLUXDB_TOKEN
# - --metrics.influxdb2.org=zHome
# - --metrics.influxdb2.bucket=traefik-hs
# - --metrics.influxdb2.addEntryPointsLabels=true
# - --metrics.influxdb2.addrouterslabels=true
# - --metrics.influxdb2.addServicesLabels=true
# - --metrics.influxdb2.pushInterval=30s
# - --metrics.influxdb2.additionallabels.host=$DOMAINNAME_HS
#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 # external http port
published: 8080
protocol: tcp
mode: host
- target: 4043 # external https port
published: 4043
protocol: tcp
mode: host
# - target: 8080 # need to enable --api.insecure=true
# published: 8080
# protocol: tcp
# mode: host
volumes:
- $DOCKERDIR/appdata/traefik3/rules/$HOSTNAME:/rules # Dynamic File Provider directory
# - /var/run/docker.sock:/var/run/docker.sock:ro # Enable if not using Socket Proxy
- $DOCKERDIR/appdata/traefik3/acme/acme.json:/acme.json # Certs File
- $DOCKERDIR/logs/$HOSTNAME/traefik:/logs # Traefik logs
environment:
- TZ=$TZ
- CF_DNS_API_TOKEN_FILE=/run/secrets/cf_dns_api_token
- HTPASSWD_FILE=/run/secrets/basic_auth_credentials # HTTP Basic Auth Credentials
- DOMAINNAME_HS # Passing the domain name to traefik container to be able to use the variable in rules.
- DOMAINNAME_1 # Additional Domain variable passthrough to container
- DOMAINNAME_AT # Additional Domain variable passthrough to container
secrets:
- cf_dns_api_token
- basic_auth_credentials
labels:
#- "autoheal=true"
- "traefik.enable=true"
# HTTP Routers
- "traefik.http.routers.traefik-rtr.entrypoints=websecure"
- "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME_HS`)"
# Services - API
- "traefik.http.routers.traefik-rtr.service=api@internal"
# Healthcheck/ping
#- "traefik.http.routers.ping.rule=Host(`traefik.$DOMAINNAME_HS`) && Path(`/ping`)"
#- "traefik.http.routers.ping.tls=true"
#- "traefik.http.routers.ping.service=ping@internal"
# Middlewares
# - "traefik.http.routers.traefik-rtr.middlewares=chain-no-auth@file" # For No Authentication
#- "traefik.http.routers.traefik-rtr.middlewares=chain-basic-auth@file" # For Basic HTTP Authentication
- "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file" # For Google OAuth
#- "traefik.http.routers.traefik-rtr.middlewares=chain-authelia@file" # For Authelia Authentication
I forward port 80 and 443 on the WAN to 8080 and 4043 respectively for any public facing service, while my internal services use port 80 and 443 natively. I also use this to specify middlewares per port of entry.
The problem is that when I access my internal services internally, it shows my public IP in Traefik logs instead of my internal IP. I am not sure why. I am not sure if there is an easier way to do this while keeping the DMZ vlan separate from the rest..