Http entryPoint redirect doesn't work for https:// URI

I'm in process to extend my traefik installation with few applications with crowdsec. I added crowdsec container, consumed the logs, added the bouncer - so far everything works.

After few weeks crowdsec console told me there are too many alerts for a free tier and I should switch to enterprise subscription - which is an absolute overkill for a private instance with one family as users.. so I checked the logs and found many requests crowdsec counts as "alerts" are very dumb crawler which don't even try to access a service but simply connect to my public IP and enumerate some common URIs like /.git,/.env and similar so I decided to create a "catchall" router (credits to https://stackoverflow.com/questions/60321335/default-router-with-traefik)

router
  routers:
    catchall-router:
      # PathPrefix(/) will match any request because all paths start with /
      rule: "PathPrefix(`/`)"
      service: catchall@file
      # lower number - lowest priority
      priority: -999
      middlewares:
        - deny-all-ip@file
      tls: {}
      entryPoints:
        - web-secure
  • take all requests not handled by other routers
    • because of PathPrefix / (basicaly speaking everything)
    • and low priority -999
  • process the request through "deny-all-ip" middleware - handling all weird requests with 403

this covered most of the crawlers but still there are some leftovers like this

request
{
  "ClientAddr": "164.52.24.188:38707",
  "ClientHost": "164.52.24.188",
  "ClientPort": "38707",
  "ClientUsername": "-",
  "DownstreamContentSize": 19,
  "DownstreamStatus": 404,
  "Duration": 143702,
  "GzipRatio": 0,
  "OriginContentSize": 0,
  "OriginDuration": 0,
  "OriginStatus": 0,
  "Overhead": 143702,
  "RequestAddr": "83.xxx.xxx.86",
  "RequestContentSize": 0,
  "RequestCount": 324296,
  "RequestHost": "83.xxx.xxx.86",
  "RequestMethod": "GET",
  "RequestPath": "/favicon.ico",
  "RequestPort": "-",
  "RequestProtocol": "HTTP/1.1",
  "RequestScheme": "https",
  "RetryAttempts": 0,
  "SpanId": "0000000000000000",
  "StartLocal": "2025-05-21T21:23:28.591126147+02:00",
  "StartUTC": "2025-05-21T19:23:28.591126147Z",
  "TLSCipher": "TLS_AES_128_GCM_SHA256",
  "TLSVersion": "1.3",
  "TraceId": "00000000000000000000000000000000",
  "downstream_Content-Type": "text/plain; charset=utf-8",
  "entryPointName": "web",
  "level": "info",
  "msg": "",
  "request_User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
  "request_X-Real-Ip": "164.52.24.188",
  "time": "2025-05-21T21:23:28+02:00"
}

which made me wonder - why this request doesn't hit the catchall router like all other requests simply connecting to the IP.

It took me a while until I spot the request hits plain-http entryPoint "web" but uses "RequestScheme": "https".

Testing with curl.exe -k -v https://83.xxx.xxx.86:80/ confirms the issue (notice port :80 in the URI):

my web entryPoint redirect to web-secure

entryPoint redirect
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: web-secure
          scheme: https
          permanent: true

doesn't work for requests using https scheme.

I solved my specific problem adding web entryPoint to my router but still wondering if this is expected or rather a bug why the request to plain-http entrypoint using https scheme doesn't follow the redirections directive?

Your router is by default listening on all entrypoints, so probably web and websecure. By enabling TLS on the router, you enable it on both entrypoints.

The mysterious request is probably https://domain.com:80, so using https on the web entrypoint.

Share your full Traefik static and dynamic config, and Docker compose file(s) if used.

I'm sorry my question was maybe unclear. The problem is definitely related to a request coming to a plain http endpoint but using https scheme. The question is why it doesn't follow the web to web-secure entryPoint redirect - is it a bug do I miss something? one can easily see the difference running

command entryPoint http status code
curl.exe -k -v https://83.xxx.xxx.86:80/ web 404
curl.exe -k -v http://83.xxx.xxx.86:443/ web 404
curl.exe -k -v http://83.xxx.xxx.86:80/ web 301

initially I had only bind the router to web-secure endpoint, in the assumption my entryPoint redirect will cover all plain http requests. but this is not the case and why I'm curios.

compose.yml
services:
  traefik:
    image: traefik:${TRAEFIK_VERSION}
    container_name: traefik
    restart: always
    depends_on:
      dockerproxy:
        condition: service_healthy
      crowdsec:
        condition: service_started
    user: "1999:1999"
    mem_limit: 2G
    cpus: 1.0
    read_only: true
    security_opt:
      - no-new-privileges:true
    environment:
      - TZ=${TZ}
    networks:
      docker-proxynet:
      proxy_ipv4:
      proxy:
        aliases:
          - dev-nc.mydomain.tld
          - test-nc.mydomain.tld
    ports:
      - 8080:8080
      - 80:80
      - 443:443
      - 443:443/udp
    volumes:
      - ./traefik_static.yml:/traefik.yml:ro
      - ./traefik_dynamic/:/config/:ro
      - ./traefik-403.htm:/traefik-403.htm:ro
      - ./log:/log
      - ./acme/:/acme/
      - ./plugins-storage:/plugins-storage
./traefik_static.yml
global:
  checkNewVersion: true
  sendAnonymousUsage: true
metrics:
  prometheus: {}
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: web-secure
          scheme: https
          permanent: true
      middlewares:
        - crowdsec@file
        - denyip@file
  web-secure:
    address: ":443"
    asDefault: true
    http3:
      advertisedPort: 443
    forwardedHeaders:
      insecure: true
      trustedIPs:
        - 127.0.0.1/32
        - 172.16.0.0/12
        - fd00:beef:beef::/48
        - fd00:feed:beef::/48
    http:
      middlewares:
        - crowdsec@file
        - denyip@file
log:
  filePath: /log/traefik.log
accessLog:
  filePath: /log/traefik-access.log
  format: json
  fields:
    headers:
      defaultMode: drop
      names:
        User-Agent: keep
        Authorization: drop
        Content-Type: keep
        x-forwarded-for: keep
        x-real-ip: keep
api:
  insecure: true
providers:
  docker:
    exposedByDefault: false
    endpoint: 'tcp://dockerproxy:2375'
    network: traefik-servicenet
  file:
    directory: /config
    watch: true
certificatesResolvers:
  letsencryptresolver:
    acme:
      email: letsencrypt@mydomain.tld
      storage: /acme/le.json
      tlsChallenge: true
  letsencryptstaging:
    acme:
      email: letsencrypt@mydomain.tld
      storage: /acme/le-staging.json
      caserver: https://acme-staging-v02.api.letsencrypt.org/directory
      tlsChallenge: true
experimental:
  plugins:
    bouncer:
      moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
    denyip:
      modulename: github.com/kvncrw/denyip
      version: v1.1.0
./traefik_dynamic/catchall.yml
http:
  services:
    catchall:
      loadBalancer:
        servers:
          - url: "http://0.0.0.0/"
  # https://stackoverflow.com/questions/60321335/default-router-with-traefik
  routers:
    catchall-router:
      # PathPrefix(/) will match any request because all paths start with /
      rule: "PathPrefix(`/`)"
      service: catchall@file
      # lower number - lowest priority
      priority: -999
      middlewares:
        - deny-all-ip@file
      tls: {}
      entryPoints:
        - web-secure
        - web                            # I added this later!
./traefik_dynamic/deny-all-ip@file
http:
  middlewares:
    deny-all-ip:
      plugin:
        denyip:
          ipDenyList:
            - 0.0.0.0/0
            - ::/0

UPD: found another even more funny thing - it seems possible to access web-secure endpoint using http scheme! :confused:

http request to web-secure
{
  "ClientAddr": "159.89.49.205:38620",
  "ClientHost": "159.89.49.205",
  "ClientPort": "38620",
  "ClientUsername": "-",
  "DownstreamContentSize": 19,
  "DownstreamStatus": 404,
  "Duration": 80221,
  "GzipRatio": 0,
  "OriginContentSize": 0,
  "OriginDuration": 0,
  "OriginStatus": 0,
  "Overhead": 80221,
  "RequestAddr": "83.xxx.xxx.86:443",
  "RequestContentSize": 0,
  "RequestCount": 331052,
  "RequestHost": "83.xxx.xxx.86",
  "RequestMethod": "GET",
  "RequestPath": "/.git/config",
  "RequestPort": "443",
  "RequestProtocol": "HTTP/1.1",
  "RequestScheme": "http",
  "RetryAttempts": 0,
  "SpanId": "0000000000000000",
  "StartLocal": "2025-05-22T11:15:12.119801508+02:00",
  "StartUTC": "2025-05-22T09:15:12.119801508Z",
  "TraceId": "00000000000000000000000000000000",
  "downstream_Content-Type": "text/plain; charset=utf-8",
  "entryPointName": "web-secure",
  "level": "info",
  "msg": "",
  "request_User-Agent": "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);",
  "request_X-Real-Ip": "159.89.49.205",
  "time": "2025-05-22T11:15:12+02:00"
}

There is no real harm from this but in my eyes processing wrong request scheme is not right e.g. http->secure endpoint and https->plain http endpoint are invalid combinations and traefik should rather fail/decline connection rather process it in some unexpected way?

When you think it’s a bug, then you can report it to the developers at Traefik Github.

I solved the problem with almost 2 identical routers with and without TLS catching all traffic which doesn't hit any other router both tied to both endpoints.

cat traefik_dynamic/catchall.yml
http:
  services:
    catchall:
      loadBalancer:
        servers:
          - url: "http://0.0.0.0/"
  # https://stackoverflow.com/questions/60321335/default-router-with-traefik
  routers:
    catchall-router-https:
      # PathPrefix(/) will match any request because all paths start with /
      rule: "PathPrefix(`/`)"
      service: catchall@file
      # lower number - lowest priority
      priority: -999
      middlewares:
        - deny-all-ip@file
      tls: {}
      entryPoints:
        - web-secure
        - web

    catchall-router-http:
      # PathPrefix(/) will match any request because all paths start with /
      rule: "PathPrefix(`/`)"
      service: catchall@file
      # lower number - lowest priority
      priority: -999
      middlewares:
        - deny-all-ip@file
      entryPoints:
        - web-secure
        - web

after adding this two routers I don't see 404 for simple ip scanner requests (all are 403) - so I can apply further measures like fail2ban or crowdsec on it.