Negate RegExp or equivalent?

Hi all

So I've seen that GoLang doesn't support negative lookahead, which is a shame, as I was hoping for a rule to "catch" anything not defined as router.

i.e. I have defined "hosta.mydomain" and "hostb.mydomain" but not "hostc.mydomain"

Once I open up traefik to the internet, and forward relevant IP traffic to my traefik host IP, anything hitting the raw IP on port 443 (websecure entrypoint) is answered by traefik - which is fine, but it responds to things which are not defined - i.e. if someone accesses the IP direct, OR points a CNAME to it, traefik will answer it, and return a 404, which will invite probing :slight_smile:

Whilst I'm wiring in fail2ban to stop people repeatedly hitting it, I wanted to try something like:

  [http.routers.catcher]
    rule = "HostRegexp(`{subdomain:^(?!.*hosta|hostb).*$}`)"
    entrypoints = [ "websecure" ]
    priority = 1000
    middlewares = [ "bouncer" ]
    service = "nohost"
    [http.routers.catcher.tls]
      certResolver = "myResolver"
      [[http.routers.catcher.tls.domains]]
        sans = [ "*.mydomain" ]

...but golang argues about the ?! in the regex
I was trying Priority to see if I could traefik to answer a "matchall" subdomain rule AFTER all other routers

Seeing as golang doesn't support the negative lookup, could it be possible to have a "HostNegRegexp" - so the regexp matches but then Traefik forces a non-match?

Or is there an easier way to have traefik "ignore/reject" http traffic for anything not defined in a router on the entrypoint?

For a catchall router:

traefik.http.routers.catchall.rule: PathPrefix('/')
traefik.http.routers.catchall.priority: 1

The rule is evaluated after all others(pritority: 1) and matches any request (PathPrefix(`/`))
Attach TLS, middlewares, etc as desired.

Cool, that's working now.
I had another priority=1 that was clashing.

I've now got anything hitting the defined "main" URL externally with a 401 Unauthorized, but it's working internally.

Any defined (and allowed via DNS externally) router is answering, and anything else bounces :slight_smile:

There is also strictSNI as part of TLSOptions. I'm not sure what the response code is when used though.

What did you use for your middleware ?

I think strictSNI has to be enabled per router?

So far I've got this:
[http.routers]
[http.routers.catcher]
rule = "PathPrefix(/)"
entrypoints = [ "websecure" ]
priority = 1
middlewares = [ "bouncer" ]
service = "nohost"
[http.routers.catcher.tls]
certResolver = "myresolver"
[[http.routers.catcher.tls.domains]]
sans = [ "*.mydomain.name" ]

[http.middlewares]
[http.middlewares.bouncer]
[http.middlewares.bouncer.redirectRegex]
regex=".*"
replacement="https://www.mychosen-redirect.site"

[http.services]
[http.services.nohost.loadBalancer]
[[http.services.nohost.loadBalancer.servers]]
# Specify either:
# An invalid internal URL (visitor will get a Gateway error)
# A valid internal host, with it's own block policy
# A valid URL, if you are using external blocking
# Example here will use OMV, but be blocked externally
# as the nohost router uses the blockexternal middleware
url = "http://validinternalurl:port"

"nohost" is also used by a router which is valid externally (valid dns CNAME) but uses a separate middleware to block external IPs.

Thus if I hit the external name internally (pihole DHCP provides internal IP) I get my host. If I hit it from outside, I get Unauthorized. Fail2Ban then blocks the IP if it sees 10 x 401 unauthorized.

Any valid subdomain/router is forwarded as expected, and any invalid subdomain hitting the host, hits the rule you suggested

I've not checked what code happens if I strictSNI all the routers though, as so far this seems to work.