HAProxy Enterprise Documentation 2.5r1

Syntax

First, let's examine an ACL on its own, without referencing it anywhere. The following ACL, which begins with the acl keyword, returns true if the requested URL path begins with /images/:

frontend www
   bind :80
   acl image_url path -i -m beg /images/
  • The -i flag performs a case-insensitive match of the requested URL path.

  • The -m beg flag sets the match type to begins with.

You can also use a shorthand syntax, path_beg, instead of path:

frontend www
   bind :80
   acl image_url path_beg -i /images/

Specify multiple values to match against by separating them with spaces:

frontend www
   bind :80
   acl image_url path_beg -i /images/ /photos/

It's possible to specify an ACL on multiple lines, in which case it behaves as the previous example, where the values were separated by spaces:

frontend www
   bind :80
   acl image_url path_beg -i /images/
   acl image_url path_beg -i /photos/

The functions path and path_beg are called fetch methods or fetches for short. Most fetches do not have a shorthand syntax like path_beg, but check the Reference Manual to learn about those that do.

When HAProxy Enterprise evaluates an ACL, it always returns true or false. You can then use the ACL on any line that allows a conditional if or unless statement. For instance, to select a specific backend if the URL path begins with /images/, place the name of the ACL after an if statement at the end of a use_backend line in a frontend section:

frontend www
   bind :80
   acl image_url path_beg -i /images/
   use_backend static_assets if image_url

backend static_assets
   server s1 192.168.50.20:80

Now, requests that begin with /images/ are routed to the backend pool of servers named static_assets.

You can reference multiple ACLs in a condition. In this case, a logical AND operator is implied:

frontend www
   bind :80
   acl api_url path_beg /api/
   acl is_post method POST

   # The path begins with /api/ and the method is POST
   use_backend api_servers if api_url is_post

backend api_servers
     server s1 192.168.50.20:80

You can also specify a logical OR operator by using ||:

frontend www
   bind :80
   acl api_url path_beg /api/
   acl is_post method POST

   # The path begins with /api/ or the method is POST
   use_backend api_servers if api_url || is_post

backend api_servers
   server s1 192.168.50.20:80
  • To negate a condition, the unless operator can be used:

frontend www
   bind :80
   acl api_url path_beg /api/

   # Use webservers only if the path does not begin with /api/
   use_backend webservers unless api_url

backend webservers
   server s1 192.168.50.20:80

An ACL is split into four parts:

  • a name for the ACL, which you choose

  • a fetch to collect information from the client's session

  • optional flags

  • a value to match against

In the example below, we mark these parts:

frontend www
   bind :80
   #   name       fetch  flags       value
   acl image_url  path   -i -m beg   /images/

Fetches

An ACL compares a value with a result from a fetch method. See Fetches to learn more about fetch methods.

The fetch part of an ACL returns a value of a certain data type. For example, the path fetch returns a string, which you match against an expected string value. In the previous example, we attempted to match the path fetch against the string /images/.

The data types are:

  • Boolean

  • Integer (signed or unsigned)

  • IPv4 or IPv6 address

  • String

  • Binary data block

Here are examples of ACLs that use fetches of various data types:

frontend www
   bind :80

   # Boolean. Did the connection arrive over SSL?
   # Note that boolean expressions do not include an explicit value to match against.
   acl ssl_was_used ssl_fc

   # Integer. Is the destination port 8080?
   acl is_8080 dst_port 8080

   # IP address. Is the destination IP address localhost (i.e. 127.0.0.1)?
   acl localhost dst 127.0.0.1

   # Binary. Does the request body contain the substring 'PING'?
   # For binary fetches, you must set a match type.
   acl contains_ping req.body -m sub PING

ACL Flags

ACLs support the following flags:

Flag

Description

-i

Ignores case during matching of all subsequent patterns.

-f </path/to/file>

Loads patterns from </path/to/file>.

-m <method>

Uses a specific pattern matching method.

-n

Forbids DNS resolution.

-M

Loads the file pointed by -f like a map file.

-u

Forces the ACL unique id.

--

Forces end of flags; it is useful when a pattern looks like one of the flags.

-f Flag

The -f flag loads a file that contains values to match against. It must be followed by the name of a file from which HAProxy Enterprise reads all lines as individual patterns. It's possible to pass multiple -f arguments if the patterns come from multiple files.

Example file patterns.txt:

/images/
/photos/

HAProxy Enterprise configuration:

frontend www
   bind :80
   acl images_url path -i -m beg -f /etc/hapee-2.5/patterns.txt

Things to know

  • Empty lines are ignored.

  • Lines starting with a sharp (#) are ignored.

  • All leading spaces and tabs are stripped.

  • If you use -f in conjunction with -m, the -m must come first.

-M flag

The -M flag allows an ACL to load a map file. A map file contains two columns. The first column is a key and the second is an associated value. An ACL line reads only the first column; but you can use the second column later, such as by the map converter on an http-request line.

Example file redirects.map:

www.test.com   www.test.com
docs.test.com  www.test.com/docs
blog.test.com  www.test.com/blog

The ACL only considers the first column, in the same way as the -f flag with a single-column file. However, the http-request redirect line that follows finds the matching Host header from the key column, and fills in the redirect URL from the value column:

frontend www
   bind :80

   # Does the Host header match a key in the map file?
   acl requires_redirect req.hdr(Host) -i -M -f /etc/hapee-2.5/redirects.map

   # Use the correct redirect URL based on the Host header
   http-request redirect prefix https://%[req.hdr(Host),lower,map(/etc/hapee-2.5/redirects.map)] code 301 if requires_redirect

-u Flag

The -u flag lets you set the unique ID for the ACL. Then, when you use the Runtime API command show acl, it displays a unique ID next to the ACL you've defined:

$ echo "show acl" | \
   sudo socat stdio unix-connect:/var/run/hapee-2.5/hapee-lb.sock
# id (file) description
0 () acl 'ssl_fc' file '/etc/hapee-2.5/hapee-lb.cfg' line 45
1 () acl 'dst_port' file '/etc/hapee-2.5/hapee-lb.cfg' line 48
2 () acl 'dst' file '/etc/hapee-2.5/hapee-lb.cfg' line 51
3 () acl 'req.body' file '/etc/hapee-2.5/hapee-lb.cfg' line 55
4 () acl 'path' file '/etc/hapee-2.5/hapee-lb.cfg' line 6

You can use other Runtime API commands, such as get acl, to test a particular value against an ACL, which you reference by its unique ID:

$ echo "get acl #4 /images/" | \
   sudo socat stdio unix-connect:/var/run/hapee-2.5/hapee-lb.sock
type=str, case=sensitive, match=yes, idx=tree, pattern="/images/"
$ echo "get acl #4 /test/" | \
   sudo socat stdio unix-connect:/var/run/hapee-2.5/hapee-lb.sock
type=str, case=sensitive, match=no

By default, HAProxy Enterprise controls the unique ID for each ACL. However, you can use the -u flag to set it yourself:

frontend www
   bind :80
   acl image_url path_beg -i -u 50 /images/

-m Flag

The -m flag sets a specific match type to use when comparing against the input sample.

All fetches imply a matching type and generally do not need this flag. However, it is useful with generic fetches to make the match type explicit or to override the default match type.

Things to know

  • If you use -f in conjunction with -m, the -m must come first.

  • Not all match types can work with all sample fetch methods.

The match type must be one of the following:

Code

Description

found

Only checks for the existence of the requested sample in the stream. For example, use this to check whether a URL parameter exists, without concern for its value.

bool

Matches the sample as a Boolean. This method only applies to fetches that return a boolean or integer value. Value zero or false does not match, all other values match.

int

Matches the sample as an integer. It can apply to integer and boolean samples. Boolean false is integer 0, true is integer 1.

ip

Matches the sample as an IPv4 or IPv6 address. It is compatible with IP address samples only.

bin

Matches the sample against a hexadecimal string representing a binary sequence. It can apply to binary or string samples.

len

Matches the sample's length as an integer. It can apply to binary or string samples.

str

Exact string match. It can apply to binary or string samples.

sub

Substring match: checks that the sample contains at least one of the provided string patterns. It can apply to binary or string samples.

reg

Regex match: matches the sample against a list of regular expressions. This can work with binary or string samples.

beg

Prefix match: checks that the sample begins like any of the provided patterns. It can apply to binary or string samples.

end

Suffix match: checks that the sample finishes like any of the provided patterns. It can apply to binary or string samples.

dir

Subdir match: checks that a slash-delimited portion of the sample exactly matches one of the provided patterns. It can apply to binary or string samples.

dom

Domain match: checks that a dot-delimited portion of the sample exactly matches one of the provided patterns. It can apply to binary or string samples.

-n Flag

The -n flag forbids DNS resolutions when loading IP addresses from a file.

By default, when the parser can not parse an IP address, it considers that the parsed string is a domain name and tries to resolve it using DNS. If the DNS server is not reachable, the HAProxy Enterprise configuration parsing can take several minutes to wait for DNS timeouts. During this time, it does not display error messages. Therefore, this flag avoids this scenario entirely.

Example

An IP address file, safelist.txt, contains a gibberish domain name:

192.168.0.10
ssdfasdfasddfasdfa.com

HAProxy Enterprise configuration:

frontend www
   bind :80
   acl safe_ip src -n -f /etc/hapee-2.5/safelist.txt
   tcp-request content reject unless safe_ip

When reloading HAProxy, the following error displays:

error detected while parsing ACL 'safe_ip' : 'ssdfasdfasddfasdfa.com' is not a valid IPv4 or IPv6 address at line 2

Special matching

Some expressions go beyond the simple matching rules described so far. For example, you can try to match a range of integers or a range of IP addresses.

Match integer ranges

Express a range of integers as a lower and an upper bound separated by a colon:

frontend www
   bind :80

   # Is the response status from the server between 500 and 511?
   acl response_5xx status 500:511

When one of the bounds is missing, it indicates that the range has either no start or no end. It means you want to match anything higher than or anything lower than the specified lower or upper bound.

frontend www
   bind *:80

   # Is port 1024 or higher?
   acl high_port dst_port 1024:

   # Is port 1023 or lower?
   acl low_port dst_port :1023

Match integer operators

Use operators to compare two integers.

frontend www
   bind :80

   # Is the HTTP response body greater than 10000 bytes?
   acl 10kb_response res.body_len gt 10000

Available operators for integer matching are:

Operator

Description

eq

true if the sample equals at least one pattern.

ge

true if the sample is greater than or equal to at least one pattern.

gt

true if the sample is greater than at least one pattern.

le

true if the sample is less than or equal to at least one pattern.

lt

true if the sample is less than at least one pattern.

Match decimal numbers

As a special case, some ACL functions support decimal numbers, which are two integers separated by a period. In the example below, the two ACLS, tlsv1 and ssl3_or_tls1 call the req.ssl_ver fetch method, which returns a decimal number that indicates the version of SSL/TLS used. We then compare that value with a literal value 3.1 and the range 3:3.1:

frontend www
   bind :80

   # Match TLV v1.0
   acl tlsv1 req.ssl_ver 3.1

   # Match SSL 3.0 or TLS 1.0
   acl ssl3_or_tls1 req.ssl_ver 3:3.1

All integer properties apply to decimal numbers, including ranges and operators.

Match strings

String matching applies to string or binary fetch methods or converters. It and can be categorized into six match types. Use the -m flag to indicate the match type:

Parameter

Description

Exact match -m str

Matches the string exactly.

Substring match -m sub

Matches a portion of the string.

Prefix match -m beg

Matches the beginning of the string.

Suffix match -m end

Matches the end of the string.

Subdir match -m dir

Matches part of a URL or file path, delimited with slashes (/).

Domain match -m dom

Matches part of a domain, delimited with periods (.).

Things to know

  • String matching applies to verbatim strings as they pass, with the exception of the backslash (\). This enables you to avoid characters such as the space.

  • When the flag -i passes before the first string, the matching is not case-sensitive.

  • To match the pattern -i, you can either set it after, or pass the specific flag -- before the first pattern. The same applies to match the pattern -.

Match regular expressions

Use the -m reg match type to compare a fetch method's value with a regular expression. You can escape backslashes by prefixing them with another backslash \\.

frontend www
   bind :80

   # Path contains cat, caat, caaat, etc.
   acl contains_cat path -m reg ca+t

Things to know

  • When the flag -i is passed before the first regex, the matching is not case-sensitive.

  • To match the literal -i, you can either set it after, or pass the specific flag -- before the first pattern. The same applies to match the pattern -.

Match arbitrary data blocks

It is possible to match samples against a binary block when you cannot safely represent it as a string. To do this, the patterns must be passed as a series of hexadecimal digits in an even number. Set the match type to bin. Each sequence of two digits represents a byte. The hexadecimal digits can be in either upper or lowercase.

# Match the string Hello at the beginning of the input stream
# (Hexadecimal values: x48 x65 x6c x6c x6f x0a)
acl hello payload(0,6) -m bin 48656c6c6f0a

Match IPv4 and IPv6 addresses

You can match against IPv4 addresses with or without an appended netmask. When you use a netmask, the IPv4 address matches whenever it is within the network.

You can enter IPv6 addresses in their usual form with or without an appended netmask. Only bit counts are accepted for IPv6 netmasks.

frontend www
   bind :80

   # Is the client's IP address localhost?
   acl is_localhost src 127.0.0.1

   # Is the client's IP address in the IPv4 range?
   acl allowed_ipv4 src 192.168.0.0/16

   # Is the client's IP address in the given IPv6 range?
   acl allowed_ipv6 src 2001:db8::/48

Next up

ACL Examples