Jay Taylor's notes

back to listing index

How do I match a wildcard host in ACL lists in HAproxy? - Server Fault

[web search]
Original source (serverfault.com)
Tags: configuration haproxy howto serverfault.com
Clipped on: 2024-07-29

The 2024 Developer Survey results are live! See the results
    1. Home
    2. Questions
    3. Tags
    4. Saves
    5. Users
    6. Jobs
    7. Companies
    8. Unanswered
  1. Teams

    Now available on Stack Overflow for Teams! AI features where you work: search, IDE, and chat.

    Learn more Explore Teams
  2. Looking for

Asked 12 years, 2 months ago
Modified 3 months ago
Viewed 71k times
20

I have the following lines in my haproxy.conf:

acl valid_domains hdr(Host) -i mysite.com images.mysite.com docs.mysite.com admin.mysite.com
redirect location http://mysite.com/invalid_domain if !valid_domains

How do I match any subdomain?

I tried:

acl valid_domains hdr(Host) -i *.mysite.com

and:

acl valid_domains hdr(Host) -i [a-z]+.mysite.com

... But neither worked.

Thanks

asked May 14, 2012 at 16:06
Tom
74133 gold badges1212 silver badges2424 bronze badges

4 Answers

Sorted by:
19

I feel that hdr_sub is better for your needs. I was using hdr_end for a while but it runs into the following problem:

requests with port 80 usually get the port stripped so the host header looks like "example.com", but if you were requesting on a port explicitly, like example.com:8080, the header will have the port, and hdr_end will fail the check for "example.com".

hdr_sub will do a substring match, which seems like a better fit for you (and me).

Either solution still has a nasty thing I don't like. Order dependent evaluation of the results.

e.g (my conditions look like this on the frontend)

acl is_dbadmin hdr_sub(host) -i dbadmin.example.com

Requesting on port 8080 would be like this:

Jul  9 02:48:40 localhost haproxy[8]: 192.168.1.1:55870 [09/Jul/2015:02:48:40.865] http-in example/s1 1/0/0/20/110 200 330722 - - ---- 0/0/0/0/0 0/0 {**example.com:8080**||http://example.com:} {Apache/2.4.10 (Debia||||} "GET /wp-includes/js/zxcvbn.min.js HTTP/1.1"

where as port 80 could likely be like this

Jul  9 02:48:40 localhost haproxy[8]: 192.168.1.1:55870 [09/Jul/2015:02:48:40.865] http-in example/s1 1/0/0/20/110 200 330722 - - ---- 0/0/0/0/0 0/0 {example.com||***http://example.com***:} {Apache/2.4.10 (Debia||||} "GET /wp-includes/js/zxcvbn.min.js HTTP/1.1"
answered Jul 9, 2015 at 2:52
Rj Wilson
19111 silver badge22 bronze badges
19

There are cases where you need to be explicit about this, such as handling redirects for wildcard SSL with multiple levels of subdomains.

Matching end (hdr_end or -m end) or substring (hdr_sub or -m sub) can have unintended side-effects of matching more than you expect. In many cases this may not really matter, since you don't have traffic for those domains coming to the server, but it doesn't mean it's the technically correct solution.

Using a regular expression is the best way I've found to do explicit matching. For example, if you want to only match *.example.org without matching sub.domain.example.org:

acl valid_domains hdr(host) -m reg -i ^[^.]+.example.org$

If you also want to handle (any) non-standard ports, this can be extended slightly:

acl valid_domains hdr(host) -m reg -i ^[^.]+.example.org(:[0-9]+)?$

The above will match:

  • test1.example.org
  • test2.example.org:8080

and will not match:

  • example.org
  • two.subs.example.org
  • myexample.org
  • test.myexample.org
  • test.example.org.other.com
answered Apr 25, 2018 at 21:37
gregmac
1,61944 gold badges2020 silver badges2727 bronze badges
14

hdr_end is what you're looking for. Try this:

acl valid_domains hdr_end(host) -i mysite.com 
redirect location http://mysite.com/invalid_domain if !valid_domains
answered Aug 12, 2012 at 8:02
quanta
52k1919 gold badges162162 silver badges218218 bronze badges
  • 1
    what if you have two domains. One called mysite.com and one called notmysite.com? The both end with mysite.com. So the match is not specific enought, right?
    – Saab
    Commented Jun 1, 2015 at 18:48
  • 3
    @Saab in that case I would write acl valid_domains hdr(host) -i mysite.com + acl valid_domains hdr_end(host) -i .mysite.com, or just use acl valid_domains hdr_dom(host) -i mysite.com
    – howanghk
    Commented Aug 27, 2015 at 17:55
  • Amazingly this doesn't work if there is a trailing port number, like :90, even howanghk 's answer doesn't work, have to use something like @gregmac 's answer with the regex if using a port other than (80/noport).
    – blissweb
    Commented Dec 22, 2021 at 8:32
0

I'd offer yet another solution

acl valid_domains hdr_dom(host) -i mysite.com
acl valid_domains hdr_dom(host) -i -m end .mysite.com

Rules in one acl are combined with or. First one accepts just the top domain, second will accept subdomains. Should not be concerned with port thanks to hdr_dom

I know it's an old question, but I still came here looking. See the docs for full detail.

answered Apr 29 at 16:16
Robert Cutajar
11366 bronze badges

Your Answer

Community wiki

Not the answer you're looking for? Browse other questions tagged or ask your own question.

Hot Network Questions