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

Tom
  • 751

4 Answers4

21

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
gregmac
  • 1,689
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"
Dan Soap
  • 145
Rj Wilson
  • 191
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
quanta
  • 52,423
1

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.