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 |
---|---|
| Ignores case during matching of all subsequent patterns. |
| Loads patterns from |
| Uses a specific pattern matching method. |
| Forbids DNS resolution. |
| Loads the file pointed by |
| 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.0/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.0/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.0/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.0/hapee-lb.sock
# id (file) description
0 () acl 'ssl_fc' file '/etc/hapee-2.0/hapee-lb.cfg' line 45
1 () acl 'dst_port' file '/etc/hapee-2.0/hapee-lb.cfg' line 48
2 () acl 'dst' file '/etc/hapee-2.0/hapee-lb.cfg' line 51
3 () acl 'req.body' file '/etc/hapee-2.0/hapee-lb.cfg' line 55
4 () acl 'path' file '/etc/hapee-2.0/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.0/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.0/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 |
---|---|
| 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. |
| 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. |
| Matches the sample as an integer. It can apply to integer and boolean samples. Boolean false is integer 0, true is integer 1. |
| Matches the sample as an IPv4 or IPv6 address. It is compatible with IP address samples only. |
| Matches the sample against a hexadecimal string representing a binary sequence. It can apply to binary or string samples. |
| Matches the sample's length as an integer. It can apply to binary or string samples. |
| Exact string match. It can apply to binary or string samples. |
| Substring match: checks that the sample contains at least one of the provided string patterns. It can apply to binary or string samples. |
| Regex match: matches the sample against a list of regular expressions. This can work with binary or string samples. |
| Prefix match: checks that the sample begins like any of the provided patterns. It can apply to binary or string samples. |
| Suffix match: checks that the sample finishes like any of the provided patterns. It can apply to binary or string samples. |
| 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. |
| 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.0/safelist.txttcp-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 |
---|---|
|
|
|
|
|
|
|
|
|
|
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 | Matches the string exactly. |
Substring match | Matches a portion of the string. |
Prefix match | Matches the beginning of the string. |
Suffix match | Matches the end of the string. |
Subdir match | Matches part of a URL or file path, delimited with slashes ( |
Domain match | 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