The purpose in using Access Control Lists (ACL) is to provide a flexible solution to make decisions based on content extracted from the request, the response, or any environmental status.

Its principle is the following:

  • Extract a data sample from a stream, table, or the environment

  • Apply optionally some format conversion to the extracted sample

  • Apply one or multiple pattern matching methods on this sample

ACL Syntax

ACLs are defined using the keyword acl. The syntax is:

acl <aclname> <criterion>[,<converter>] [flags] [operator] [<pattern>] ...

ACLs require the following parameters:

Parameter

Description

<aclname>

Name of the ACL to describe it as much as possible.

It must have upper and lower case letters, digits, - (dash), _ (underscore) , . (dot) and : (colon).

It is case sensitive; hence my_acl and My_Acl are two different ACLs.

<criterion>

Based on sample fetches, it describes the portion of the request or response where this ACL applies.

[<converter>]

One or several <converter> can be specified, separated by a comma ,. They can be used to manipulate the data provided by the <criterion>

[flags] (optional)

Completes the <criterion> to make it more accurate on where and how to apply the ACL.

[operator] (optional)

It is possible to apply an <operator> when matching the data provided by the <criterion> against <pattern>.

[<pattern>] (optional)

Data provided by <criterion> is compared to a<pattern> list.

It is as the same type as the data provided by the <criterion> or the result of the latest <converter>.

Matching results will define the result of the whole ACL.

An ACL can return two values:

Value

Description

TRUE

when the data from <criterion> matches at least one of the <pattern>

FALSE

when the data from <criterion> does not match any of the <pattern>

ACL Rules

For ACLs sharing the same name, the following rules apply:

  • It is possible to use the same <aclname> for many ACLs, even if they do not have the same matching criterion

  • A logical OR applies between all of them

ACL Criterion

The criterion is generally the name of a sample fetch method, or one of the Sample fetch ACL derivatives declinations.

Note

The sample fetch methods are the only ones that support a conversion.

The ACL declinations can describe alternate matching methods for a same sample fetch method.

As a reminder, sample fetch methods can return the following data types:

  • boolean

  • integer (signed or unsigned)

  • IPv4 or IPv6 address

  • string

  • binary data block

Criterion converters

Converters transform any supported data type any other data type.

The resulting sample's type is the same as the type of the last converter applied to the list, which defaults to the type of the sample fetch method.

Sample fetch ACL derivatives

All ACL-specific criteria imply a default matching method. Most often, these criteria are built by concatenating the name of the original sample fetch method and the matching method.

For example, hdr_beg applies the beg match to the sample retrieved using the hdr fetch.

Since all ACL-specific criteria rely on a sample fetch method, you can use the original sample fetch method and the explicit matching method with -m.

If an alternate match is specified using -m on an ACL-specific criterion, the matching method is applied to the underlying sample fetch method.

For example, all ACLs below are exactly equivalent:

acl short_form  hdr_beg(host)        www.
acl alternate1  hdr_beg(host) -m beg www.
acl alternate2  hdr_dom(host) -m beg www.
acl alternate3  hdr(host)     -m beg www.

The table below presents ACL derivatives from their respective sample fetch:

Sample fetch

Derivative ACLs

req.rdp_cookie([<name>])

req_rdp_cookie([<name>])

exact string match

req.rdp_cookie_cnt([name])

req_rdp_cookie_cnt([<name>])

integer match

req.ssl_sni

req_ssl_sni

exact string match

req.ssl_ver

req_ssl_ver

decimal match

base

base

exact string match

base_beg

prefix match

base_dir

subdir match

base_dom

domain match

base_end

suffix match

base_len

length match

base_reg

regex match

base_sub

substring match

req.cook([<name>])

cook([<name>])

exact string match

cook_beg([<name>])

prefix match

cook_dir([<name>])

subdir match

cook_dom([<name>])

domain match

cook_end([<name>])

suffix match

cook_len([<name>])

length match

cook_reg([<name>])

regex match

cook_sub([<name>])

substring match

req.hdr([<name>[,<occ>]])

hdr([<name>[,<occ>]])

exact string match

hdr_beg([<name>[,<occ>]])

prefix match

hdr_dir([<name>[,<occ>]])

subdir match

hdr_dom([<name>[,<occ>]])

domain match

hdr_end([<name>[,<occ>]])

suffix match

hdr_len([<name>[,<occ>]])

length match

hdr_reg([<name>[,<occ>]])

regex match

hdr_sub([<name>[,<occ>]])

substring match

http_auth_group(<userlist>)

http_auth_group(<userlist>) group ...

Returns true when the user extracted from the request and whose password isvalid according to the specified userlist belongs to at least one of the groups.

method

method

case insensitive method match

path

path

exact string match

path_beg

prefix match

path_dir

subdir match

path_dom

domain match

path_end

suffix match

path_len

length match

path_reg

regex match

path_sub

substring match

req.ver

req_ver

exact string match

res.cook([<name>])

scook([<name>]

exact string match

res.hdr([<name>[,<occ>]])

shdr([<name>[,<occ>]])

exact string match

shdr_beg([<name>[,<occ>]])

prefix match

shdr_dir([<name>[,<occ>]])

subdir match

shdr_dom([<name>[,<occ>]])

domain match

shdr_end([<name>[,<occ>]])

suffix match

shdr_len([<name>[,<occ>]])

length match

shdr_reg([<name>[,<occ>]])

regex match

shdr_sub([<name>[,<occ>]])

substring match

res.ver

resp_ver

exact string match

url

url

exact string match

url_beg

prefix match

url_dir

subdir match

url_dom

domain match

url_end

suffix match

url_len

length match

url_reg

regex match

url_sub

substring match

urlp(<name>[,<delim>])

urlp(<name>[,<delim>])

exact string match

urlp_beg(<name>[,<delim>])

prefix match

urlp_dir(<name>[,<delim>])

subdir match

urlp_dom(<name>[,<delim>])

domain match

urlp_end(<name>[,<delim>])

suffix match

urlp_len(<name>[,<delim>])

length match

urlp_reg(<name>[,<delim>])

regex match

urlp_sub(<name>[,<delim>])

substring match

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. Useful when a pattern looks like one of the flags.

acl -f flag

Note

If you use -m in conjunction with -f, you must place it first.

The -f flag must be followed by the name of a file from which all lines will be read as individual pattern. It is possible to pass multiple -f arguments if the patterns must be loaded from multiple files.

The following actions happen when HAProxy loads an ACL pattern list from a file:

  • Empty lines are ignored

  • Lines starting with a sharp (#) are ignored

  • All leading spaces and tabs are stripped

Note

If it is absolutely necessary to insert a valid pattern that begins with a sharp character, you can prefix it with a space character so it is not read as a comment.

acl -M flag

The -M flag allows an ACL to use a map file. With this flag set, the file is parsed as a two column file:

The first column contains the patterns used by the ACL, and the second column contain the samples. The samples can be used later by a map. This can be useful in some cases where an ACL would be used to check for a pattern in a map before it applies mapping.

acl -u flag

The -u flag forces the unique ID of the ACL.

This unique ID is used with the stats socket interface to identify an ACL and dynamically change its values.

Note

An ACL that uses a file is always identified by its file name even if an ID is set.

acl -m flag

Note

If you use -m in conjunction with -f, you must place it first.

The -m flag is used to select a specific matching method on the input sample.

All ACL-specific criteria imply a matching method and generally do not need this flag. However, this flag is useful with generic sample fetch methods to describe how they get matched against the patterns.

This is required for sample fetches which return data type for which there is no obvious matching method (e.g. string or binary).

When -m is specified and followed by a matching method name, this method is used instead of the default one for the criterion. This makes it possible to match contents in ways that were not initially planned, or with sample fetch methods which return a string. The matching method also affects the way the patterns are parsed.

Note

There are some restrictions. Not all methods can be used with all sample fetch methods.

The matching <methods> must be one of the following:

Code

Description

found

Only checks if the requested sample could be found in the stream, but does not compare it against any pattern. It is recommended not to pass any pattern to avoid confusion. This matching method is useful to detect the presence of certain contents such as headers, cookies, etc. even if they are empty, without comparing or counting them.

bool

Checks the sample as a boolean. This method only applies to fetches which return a boolean or integer value, and takes no pattern.

Value zero or false does not match, all other values match.

int

Matches the sample as an integer. 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 sample only.

bin

Matches the sample against an hexadecimal string representing a binary sequence. Can apply to binary or string samples.

len

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

str

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

sub

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

reg

Regex match: matches the sample against a list of regular expressions. This may be used with binary or string samples.

beg

Prefix match: checks that the sample begins like any of the provided pattern. Can apply to binary or string samples.

end

Suffix match: checks that the sample finishes like any of the provided pattern. 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. 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 pattern. Can apply to binary or string samples.

acl -n flag

The -n flag forbids DNS resolutions. It is used when loading IPs 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 configuration parsing can take several minutes waiting for DNS timeouts. During this time, it does not display error messages.

Data types and matching between samples and patterns

The default test method is implied by the output data type of this sample fetch method.

Each sample fetch or converter returns a specific data type, specified with its keyword.

When an ACL is declared using a standard sample fetch method, certain types automatically default to a matching method which are summarized in the table below:

Sample or converter output type

Default matching method

boolean

bool

integer

int

ip

ip

string

str

binary

none, use -m

Note

In order to match a binary sample, it is mandatory to specify a matching method. See below.

The ACL engine can match these types against patterns of the following types:

  • boolean

  • integer or integer range

  • IP address / network

  • string (exact, substring, suffix, prefix, subdir, domain)

  • regular expression

  • hex block

The table below summarizes the compatibility matrix between pattern and samples or converter . It indicates the name of the matching method to use for each compatible combination.

The method in bold is the default and works without any -m flag.

pattern type

boolean

integer

ip

string

binary

none (presence only)

found

found

found

found

found

none (boolean value)

bool

bool

bool

integer (value)

int

int

int

int

integer (length)

len

len

len

len

len

IP address

ip

ip

ip

exact string

str

str

str

str

str

prefix

beg

beg

beg

beg

beg

suffix

end

end

end

end

end

substring

sub

sub

sub

sub

sub

subdir

dir

dir

dir

dir

dir

domain

dom

dom

dom

dom

dom

regex

reg

reg

reg

reg

reg

hex block

bin

bin

Matching booleans

Boolean matching applies by default to boolean fetch methods or converters.

In order to match a Boolean, no pattern is required and all patterns are ignored. When using Boolean matching, the criterion returns the sample as is (hence the fetch), which means that a Boolean true will always match and a Boolean false will never match.

You can enforce Boolean matching by using the flag -m bool on fetch method returning an integer type. In such cases, 0 is converted to a Boolean false and all other values are converted to Boolean true.

Matching integers

Note

Integer matching only applies to positive values.

Integer matching applies by default to integer fetch methods or converters.

You can also enforce it on boolean fetches using the flag -m int. In such cases, false is converted to the integer 0, and true is converted to the integer 1.

Integer matching also supports integer ranges and operators.

Note

Using operators with ranges is not recommended.

Integer ranges

A range is a value expressed with a lower and an upper bound separated by a colon, which can both be omitted.

When one of the bound is omitted, it means than the range has either no start or no end. Basically, it means you want to match anything higher than or anything lower than the specified lower or upper bound specified.

  • 1024:65535 or 1024: is a valid range to represent a range of unprivileged ports.

  • 0:1023 or:1023 is a valid representation of privileged ports.

Integer operators

For easier use, comparison operators are also supported.

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

Decimal numbers

As a special case, some ACL functions support decimal numbers, which are two integers separated by a period. For example, this is used with version checks.

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

Matching strings

By default, string matching applies to string or binary fetch methods or converters, and exists in 6 formats.

They use the -m flag:

Parameter

Description

exact match -m str

The sample string must match exactly any of the patterns

substring match -m sub

The patterns are looked up inside the sample string, and the ACL makes a match if any is found.

prefix match -m beg

The patterns are compared with the beginning of the sample string, and the ACL makes a match if any is found.

suffix match -m end

The patterns are compared with the end of the sample string, and the ACL makes a match if any is found.

subdir match -m sub

The patterns are looked up inside the sample string, delimited with slashes (/), and the ACL makes a match if any is found.

domain match -m dom

The patterns are looked up inside the sample string, delimited with periods (.), and the ACL makes a match if any is found.

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

When the flag -i is passed before the first string, then the matching performed 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 -.

Matching regular expressions

Regex matching applies to verbatim samples as they are passed, with the exception of the backslash (\). This enables you to avoid characters such as the space.

When the flag -i is passed before the first regex, then the matching performed 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 -.

Matching arbitrary data blocks

It is possible to match samples against a binary block which may not be safely represented as a string. For this, the patterns must be passed as a series of hexadecimal digits in an even number.

This works when the match method is set to binary. Each sequence of two digits represents a byte. The hexadecimal digits can either be in upper or lower case.

Matching IPv4 and IPv6 addresses

You can specify a pattern of IPv4 addresses either as plain addresses or with an appended netmask, in which case the IPv4 address matches whenever it is within the network.

You can also replace plain addresses with a resolvable host name using DNS, but this practice is generally not recommended as it makes it more difficult to read and debug configurations.

If you use host names, ensure that they are present in /etc/hosts so that the configuration does not depend on any random DNS match at the moment the configuration is parsed.

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

To avoid any risk of problems with randomly resolved IP addresses, host names are never allowed for IPv6 patterns.

HAProxy can also match IPv4 addresses with IPv6 addresses in the following situations:

Sample address family

Pattern address family

Match

IPv4

IPv4

IPv4 using the supplied mask.

IPv6

IPv6

IPv6 using the supplied mask.

IPv6

IPv4

IPv4 using the pattern's mask if the IPv6 address matches with 2002:IPV4::, ::IPV4 or ::ffff:IPV4; otherwise it fails.

IPv4

IPv6

IPv4 is first converted to IPv6 by prefixing it with ::ffff: Then the match is applied in IPv6 using the supplied IPv6 mask.

Predefined ACLs

Certain predefined ACLs are hard-coded in HAProxy, so they don't need to be declared in every section that requires them. Their names are in upper case to avoid confusion.

Below is the list of predefined ACLs with their equivalence:

ACL name

Equivalent to

Usage

FALSE

always_false

Never match

HTTP

req_proto_http

Match if protocol is valid HTTP

HTTP_1.0

req_ver 1.0

Match HTTP version 1.0

HTTP_1.1

req_ver 1.1

Match HTTP version 1.1

HTTP_CONTENT

hdr_val(content-length) gt 0

Match an existing content-length

HTTP_URL_ABS

url_reg ^[^/:]*://

Match absolute URL with scheme

HTTP_URL_SLASH

url_beg /

Match URL beginning with /

HTTP_URL_STAR

url *

Match URL equal to *

LOCALHOST

src 127.0.0.1/8

Match connection from local host

METH_CONNECT

method CONNECT

Match HTTP CONNECT method

METH_GET

method GET HEAD

Match HTTP GET or HEAD method

METH_HEAD

method HEAD

Match HTTP HEAD method

METH_OPTIONS

method OPTIONS

Match HTTP OPTIONS method

METH_POST

method POST

Match HTTP POST method

METH_TRACE

method TRACE

Match HTTP TRACE method

RDP_COOKIE

req_rdp_cookie_cnt gt 0

Match presence of an RDP cookie

REQ_CONTENT

req_len gt 0

Match data in the request buffer

TRUE

always_true

Always match

WAIT_END

wait_end

Wait for end of content analysis

ACL Examples

To detect quickly the presence of a cookie JSESSIONID in an HTTP request:

acl jsess_present req.cook(JSESSIONID) -m found

Apply a regular expression over the first 500 bytes of data in the request buffer:

acl script_tag req.payload(0,500) -m reg -i <script>

Apply both case-sensitive and non-case-sensitve matches, using the 'i flag:

acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test

The following happens:

  • each line of exact-ua.lst is matched exactly against the user-agent header of the request.

  • each line of generic-ua.lst is matched without case-sensitivity.

  • the word test is also matched without case-sensitivity.

Match any negative Content-Length header:

acl negative-length hdr_val(content-length) lt 0

Match any SSL version between 3.0 and 3.1 (inclusive):

acl sslv3 req_ssl_ver 3:3.1

Look for the string -i in the User-Agent header:

acl hdr_sub -- -i

Match the string Hello at the beginning of the input stream (Hexa values: x48 x65 x6c x6c x6f x0a):

acl hello payload(0,6) -m bin 48656c6c6f0a

Convert the X-Forwarded-For header into IP addresses and match for private IPs:

acl req.fhdr(X-Forwarded-For) -m ip 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16

Match static content either in the Host header or in the URL path:

acl static hdr_dom(Host) -i static.domain.com assets.domain.com
acl static path_beg -i /static/ /images/ /css/