Setting up ACLs for multiple sites / regrep

Hi all, I’m pretty new to HAproxy, but it’s fantastic so far. I’m hosting multiple intranet sites with it to test some stuff. For ease of description I’m going to limit this to one page here. Here is my issue:

frontend public
        bind 192.168.2.2:80 v4v6
        option forwardfor except 127.0.0.1
        default_backend pihole

        acl isaak hdr(host) -i isaak.com
        acl isaak1 hdr(host) -i www.isaak.com
        use_backend isaak1 if isaak or isaak1

backend pihole
        reqrep ^([^\ :]*)\ (.*) \1\ /admin\2
        server pihole  127.0.0.1:8081

backend isaak1
        reqrep ^([^\ :]*)\ (.*) \1\ /isaak\2
        server isaak 192.168.2.2:8082


Obviously this config is not only super redundant but also there is a problem. This server, as you can see, also hosts my pi-hole. I’m using local DNS records to forward isaak.com to lighttpd running on port 8082.

My questions:

  • Whenever I click a link (let’s say files/) on isaak.com the regrep forwards this to isaak.com/isaak/files, how do I fix the regrep? I’ve been googling for hours but I’m not sure what to search for.
  • Can I somehow use wildcards in the acls to make this less redundant?

Thanks in advance!

The regexp here looks overly complicated, but it’s hard to tell what you want. Try them online here https://regex101.com/ or any similar site, using either perl or python regex to test, they are typically close enough.

Refer to docs at HAProxy version 2.4.0 - Configuration Manual (if 2.4 is your version!), and Managing Traffic | LB Layer7 | Rewriting HTTP Requests, Methods, or Headers | HAProxy ALOHA 13.0 which is technically the commercial product but is not surprisingly very similar.

There are many excellent blog posts over at haproxy.com including:

I guess you want to rewrite:

http://isaak.com/files/foo

to

http://192.168.2.2:8082/foo

If so, this might be a better approach, using word substitution:

    acl static_files      if path_beg /files/
    http-request set-path    /%[path,word(2,/,0)]    if static_files

word(<index>,<delimiters>[,<count>])
Extracts the nth word counting from the beginning (positive index) or from the end (negative index) considering given delimiters from an input string. Indexes start at 1 or -1 and delimiters are a string formatted list of chars. Delimiters at the beginning or end of the input string are ignored. Optionally you can specify of words to extract (default: 1). Value of 0 indicates extraction of all remaining words.

comments

  • you can simplify the ACL like this:
        acl isaak hdr(host) -i isaak.com
        acl isaak hdr(host) -i www.isaak.com
        use_backend isaak if isaak
  • reqrep is deprecated since quite a few versions, the current alternative might be:
    http-request replace-path /files/(.+) \1 
  • generally one tries to avoid regexp for high performance sites (it can be abused as a denial-of-service vector) but I expect in your case this isn’t important.