Traefik 2 - 2 rules, each with own ipwhitelist, only one applied to all rules

Hello Traefik World

Its my first post here, apologize for bad english

I'm very happy using Traefik, really good proxy for docker :slight_smile:

But i face a problem with rules and ipwhitelist

Configuration
Traefik 2.8.4
Docker 20.10.8 in swarm mode on Ubuntu 20.04.3 LTS
Behind a Nat router (no filtering on ports 80 and 443)

traefik.yml

version: '3.7'

services:

  traefik:
    image: traefik:latest
    # for good client IP forwarded
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
       ...

All is good at this point, any stacks deployed run well

I try to set a new stack with ipwhitelist use :

Access to http://myentry.mydomain.com/ limited to some set of ip
Access to http://myentry.mydomain.com/admin/ (and /login/) limited to different set of ip

version: '3.9'
services:
  myservice:
      ...
      labels:
       ...
        - traefik.enable=true
        - traefik.docker.network=traefik-public
        - traefik.constraint-label=traefik-public

        - traefik.http.services.myservice.loadbalancer.server.port=80

        - traefik.http.routers.myentry-root.entrypoints=http
        - traefik.http.routers.myentry-admin.entrypoints=http

        - traefik.http.routers.myentry-root.rule=Host(`myentry.mydomain.com`)
        - traefik.http.routers.myentry-root.priority=100

        - traefik.http.routers.myentry-admin.rule=Host(`myentry.mydomain.com`) && (PathPrefix(`/admin/`) || PathPrefix(`/login/`))
        - traefik.http.routers.myentry-admin.priority=200
        
        - traefik.http.middlewares.myentry-root-ipwhitelist.ipwhitelist.sourcerange=X.X.X.X
        - traefik.http.middlewares.myentry-admin-ipwhitelist.ipwhitelist.sourcerange=Y.Y.Y.Y

        - traefik.http.routers.myentry-root.middlewares=myentry-root-ipwhitelist
        - traefik.http.routers.myentry-admin.middlewares=myentry-admin-ipwhitelist

        ...

In this configuration Y.Y.Y.Y blocked anywhere, X.X.X.X allowed anywhere :thinking:

Tryed inverting priority, root priority 200 and admin 100, same result

Tryed changing 'root' rule to

        - traefik.http.routers.myentry-root.rule=Host(`myentry.mydomain.com`) && !(PathPrefix(`/admin/`) || PathPrefix(`/login/`))

(negate pathprefixes part to be the counterpart of admin rule, just to see effect)
Exact same result only X.X.X.X have ALL access !

Finally tried to change order of declarations of rules in compose file, (with last changes) just to see if that have an effect :

        - traefik.http.routers.myentry-admin.rule=Host(`myentry.mydomain.com`) && (PathPrefix(`/admin/`) || PathPrefix(`/login/`))
        - traefik.http.routers.myentry-admin.priority=200
        - traefik.http.routers.myentry-root.rule=Host(`myentry.mydomain.com`) && !(PathPrefix(`/admin/`) || PathPrefix(`/login/`))
        - traefik.http.routers.myentry-root.priority=100

Nothing change, Y.Y.Y.Y. blocked anywhere, X.X.X.X allowed anywhere :thinking:

Notice that in Traefik UI, each time, each middleware is ok and 'attached' to correct entrypoint

Seems Traefik choice a middleware only for 'Host' part of rule then apply it to all rules with same 'Host' declaration

Traefik Bug ? or i do some mistakes or misanderstand something ?

I solved my problem with add the tls field of the router definition like this

...
- traefik.http.routers.php-secure.rule=Host(`example.com`)
- traefik.http.routers.php-secure.entrypoints=websecure
- traefik.http.routers.php-secure.tls.certresolver=letsencrypt
- traefik.http.routers.php-secure.service=php
- traefik.http.routers.php-admin-secure.rule=(Host(`example.com`) && PathPrefix(`/administrator`))
- traefik.http.routers.php-admin-secure.entrypoints=websecure
- traefik.http.routers.php-admin-secure.service=php
- traefik.http.routers.php-admin-secure.middlewares=allowlist
- traefik.http.routers.php-admin-secure.tls.certresolver=letsencrypt
- traefik.http.middlewares.allowlist.ipwhitelist.sourcerange=192.168.0.1/24
- traefik.http.routers.php-secure.priority=10
- traefik.http.routers.php-admin-secure.priority=20
...

I hope this solution will help you :upside_down_face:

1 Like

Thanks
Finaly found good conf :slight_smile:
- "traefik.http.routers.myentry-root.rule=Host(myentry.mydomain.com)"
- "traefik.http.routers.myentry-admin.rule=(Host(myentry.mydomain.com) && !(Path(/)))"

    - "traefik.http.middlewares.myentry-root-ipwhitelist.ipwhitelist.sourcerange=X.X.X.X"
    - "traefik.http.routers.myentry-root.middlewares=myentry-root-ipwhitelist"

Use 3 backticks before and after code/config for better readability and preserving spaces.