7.1. ACL basics
- The use of Access Control Lists (ACL) provides a flexible solution to perform
- content switching and generally to take decisions based on content extracted
- from the request, the response or any environmental status. The principle is
- simple :
- - extract a data sample from a stream, table or the environment
- - optionally apply some format conversion to the extracted sample
- - apply one or multiple pattern matching methods on this sample
- - perform actions only when a pattern matches the sample
- The actions generally consist in blocking a request, selecting a backend, or
- adding a header.
- In order to define a test, the "acl" keyword is used. The syntax is :
- acl <aclname> <criterion> [flags] [operator] [<value>] ...
- This creates a new ACL <aclname> or completes an existing one with new tests.
- Those tests apply to the portion of request/response specified in <criterion>
- and may be adjusted with optional flags [flags]. Some criteria also support
- an operator which may be specified before the set of values. Optionally some
- conversion operators may be applied to the sample, and they will be specified
- as a comma-delimited list of keywords just after the first keyword. The values
- are of the type supported by the criterion, and are separated by spaces.
- ACL names must be formed from upper and lower case letters, digits, '-' (dash),
- '_' (underscore) , '.' (dot) and ':' (colon). ACL names are case-sensitive,
- which means that "my_acl" and "My_Acl" are two different ACLs.
- There is no enforced limit to the number of ACLs. The unused ones do not affect
- performance, they just consume a small amount of memory.
- The criterion generally is the name of a sample fetch method, or one of its ACL
- specific declinations. The default test method is implied by the output type of
- this sample fetch method. The ACL declinations can describe alternate matching
- methods of a same sample fetch method. The sample fetch methods are the only
- ones supporting a conversion.
- Sample fetch methods return data which can be of the following types :
- - boolean
- - integer (signed or unsigned)
- - IPv4 or IPv6 address
- - string
- - data block
- Converters transform any of these data into any of these. For example, some
- converters might convert a string to a lower-case string while other ones
- would turn a string to an IPv4 address, or apply a netmask to an IP address.
- The resulting sample is of the type of the last converter applied to the list,
- which defaults to the type of the sample fetch method.
- Each sample or converter returns data of a specific type, specified with its
- keyword in this documentation. When an ACL is declared using a standard sample
- fetch method, certain types automatically involved a default matching method
- which are summarized in the table below :
- +---------------------+-----------------+
- | Sample or converter | Default |
- | output type | matching method |
- +---------------------+-----------------+
- | boolean | bool |
- +---------------------+-----------------+
- | integer | int |
- +---------------------+-----------------+
- | ip | ip |
- +---------------------+-----------------+
- | string | str |
- +---------------------+-----------------+
- | binary | none, use "-m" |
- +---------------------+-----------------+
- Note that in order to match a binary samples, 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 following ACL flags are currently supported :
- -i : ignore case during matching of all subsequent patterns.
- -f : load patterns from a file.
- -m : use a specific pattern matching method
- -n : forbid the DNS resolutions
- -M : load the file pointed by -f like a map file.
- -u : force the unique id of the ACL
- -- : force end of flags. Useful when a string looks like one of the flags.
- The "-f" flag is followed by the name of a file from which all lines will be
- read as individual values. It is even possible to pass multiple "-f" arguments
- if the patterns are to be loaded from multiple files. Empty lines as well as
- lines beginning with a sharp ('#') will be ignored. All leading spaces and tabs
- will be stripped. If it is absolutely necessary to insert a valid pattern
- beginning with a sharp, just prefix it with a space so that it is not taken for
- a comment. Depending on the data type and match method, haproxy may load the
- lines into a binary tree, allowing very fast lookups. This is true for IPv4 and
- exact string matching. In this case, duplicates will automatically be removed.
- The "-M" flag allows an ACL to use a map file. If this flag is set, the file is
- parsed as two column file. The first column contains the patterns used by the
- ACL, and the second column contain the samples. The sample can be used later by
- a map. This can be useful in some rare cases where an ACL would just be used to
- check for the existence of a pattern in a map before a mapping is applied.
- The "-u" flag forces the unique id of the ACL. This unique id is used with the
- socket interface to identify ACL and dynamically change its values. Note that a
- file is always identified by its name even if an id is set.
- Also, note that the "-i" flag applies to subsequent entries and not to entries
- loaded from files preceding it. For instance :
- acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test
- In this example, each line of "exact-ua.lst" will be exactly matched against
- the "user-agent" header of the request. Then each line of "generic-ua" will be
- case-insensitively matched. Then the word "test" will be insensitively matched
- as well.
- The "-m" flag is used to select a specific pattern matching method on the input
- sample. All ACL-specific criteria imply a pattern matching method and generally
- do not need this flag. However, this flag is useful with generic sample fetch
- methods to describe how they're going to be 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 pattern 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.
- The "-n" flag forbids the dns resolutions. It is used with the load of ip files.
- By default, if the parser cannot parse ip address it considers that the parsed
- string is maybe a domain name and try dns resolution. The flag "-n" disable this
- resolution. It is useful for detecting malformed ip lists. Note that if the DNS
- server is not reachable, the haproxy configuration parsing may last many minutes
- waiting for the timeout. During this time no error messages are displayed. The
- flag "-n" disable this behavior. Note also that during the runtime, this
- function is disabled for the dynamic acl modifications.
- There are some restrictions however. Not all methods can be used with all
- sample fetch methods. Also, if "-m" is used in conjunction with "-f", it must
- be placed first. The pattern matching method must be one of the following :
- - "found" : only check if the requested sample could be found in the stream,
- but do not compare it against any pattern. It is recommended not
- to pass any pattern to avoid confusion. This matching method is
- particularly useful to detect presence of certain contents such
- as headers, cookies, etc... even if they are empty and without
- comparing them to anything nor counting them.
- - "bool
" : check the value as a boolean. It can only be applied to fetches
- This keyword is available in sections :
- Converters
- Fetching samples from internal states
- which return a boolean or integer value, and takes no pattern.
- Value zero or false does not match, all other values do match.
- - "int" : match the value as an integer. It can be used with integer and
- boolean samples. Boolean false is integer 0, true is integer 1.
- - "ip" : match the value as an IPv4 or IPv6 address. It is compatible
- with IP address samples only, so it is implied and never needed.
- - "bin" : match the contents against a hexadecimal string representing a
- binary sequence. This may be used with binary or string samples.
- - "len" : match the sample's length as an integer. This may be used with
- binary or string samples.
- - "str" : exact match : match the contents against a string. This may be
- used with binary or string samples.
- - "sub" : substring match : check that the contents contain at least one of
- the provided string patterns. This may be used with binary or
- string samples.
- - "reg" : regex match : match the contents against a list of regular
- expressions. This may be used with binary or string samples.
- - "beg" : prefix match : check that the contents begin like the provided
- string patterns. This may be used with binary or string samples.
- - "end" : suffix match : check that the contents end like the provided
- string patterns. This may be used with binary or string samples.
- - "dir" : subdir match : check that a slash-delimited portion of the
- contents exactly matches one of the provided string patterns.
- This may be used with binary or string samples.
- - "dom" : domain match : check that a dot-delimited portion of the contents
- exactly match one of the provided string patterns. This may be
- used with binary or string samples.
- For example, to quickly detect the presence of cookie "JSESSIONID" in an HTTP
- request, it is possible to do :
- acl jsess_present cook(JSESSIONID) -m found
- In order to apply a regular expression on the 500 first bytes of data in the
- buffer, one would use the following acl :
- acl script_tag payload(0,500) -m reg -i <script>
- On systems where the regex library is much slower when using "-i", it is
- possible to convert the sample to lowercase before matching, like this :
- acl script_tag payload(0,500),lower -m reg <script>
- All ACL-specific criteria imply a default matching method. Most often, these
- criteria are composed by concatenating the name of the original sample fetch
- method and the matching method. For example, "hdr_beg" applies the "beg" match
- to samples retrieved using the "hdr" fetch method. Since all ACL-specific
- criteria rely on a sample fetch method, it is always possible instead to use
- the original sample fetch method and the explicit matching method using "-m".
- If an alternate match is specified using "-m" on an ACL-specific criterion,
- the matching method is simply applied to the underlying sample fetch method.
- For example, all ACLs below are exact 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 summarizes the compatibility matrix between sample or converter
- types and the pattern types to fetch against. It indicates for each compatible
- combination the name of the matching method to be used, surrounded with angle
- brackets ">" and "<" when the method is the default one and will work by
- default without "-m".
- +-------------------------------------------------+
- | Input sample type |
- +----------------------+---------+---------+---------+---------+---------+
- | 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 |
- +----------------------+---------+---------+---------+---------+---------+
7.1.1. Matching booleans
- In order to match a boolean, no value is needed and all values are ignored.
- Boolean matching is used by default for all fetch methods of type "boolean".
- When boolean matching is used, the fetched value is returned as-is, which means
- that a boolean "true" will always match and a boolean "false" will never match.
- Boolean matching may also be enforced using "-m bool" on fetch methods which
- return an integer value. Then, integer value 0 is converted to the boolean
- "false" and all other values are converted to "true".
7.1.2. Matching integers
- Integer matching applies by default to integer fetch methods. It can also be
- enforced on boolean fetches using "-m int". In this case, "false" is converted
- to the integer 0, and "true" is converted to the integer 1.
- Integer matching also supports integer ranges and operators. Note that integer
- matching only applies to positive values. A range is a value expressed with a
- lower and an upper bound separated with a colon, both of which may be omitted.
- For instance, "1024:65535" is a valid range to represent a range of
- unprivileged ports, and "1024:" would also work. "0:1023" is a valid
- representation of privileged ports, and ":1023" would also work.
- As a special case, some ACL functions support decimal numbers which are in fact
- two integers separated by a dot. This is used with some version checks for
- instance. All integer properties apply to those decimal numbers, including
- ranges and operators.
- For an easier usage, comparison operators are also supported. Note that using
- operators with ranges does not make much sense and is strongly discouraged.
- Similarly, it does not make much sense to perform order comparisons with a set
- of values.
- Available operators for integer matching are :
- eq : true if the tested value equals at least one value
- ge : true if the tested value is greater than or equal to at least one value
- gt : true if the tested value is greater than at least one value
- le : true if the tested value is less than or equal to at least one value
- lt : true if the tested value is less than at least one value
- For instance, the following ACL matches any negative Content-Length header :
- acl negative-length hdr_val(content-length) lt 0
- This one matches SSL versions between 3.0 and 3.1 (inclusive) :
- acl sslv3 req_ssl_ver 3:3.1
7.1.3. Matching strings
- String matching applies to string or binary fetch methods, and exists in 6
- different forms :
- - exact match (-m str) : the extracted string must exactly match the
- patterns;
- - substring match (-m sub) : the patterns are looked up inside the
- extracted string, and the ACL matches if any of them is found inside;
- - prefix match (-m beg) : the patterns are compared with the beginning of
- the extracted string, and the ACL matches if any of them matches.
- - suffix match (-m end) : the patterns are compared with the end of the
- extracted string, and the ACL matches if any of them matches.
- - subdir match (-m dir) : the patterns are looked up inside the extracted
- string, delimited with slashes ("/"), and the ACL matches if any of them
- matches.
- - domain match (-m dom) : the patterns are looked up inside the extracted
- string, delimited with dots ("."), and the ACL matches if any of them
- matches.
- String matching applies to verbatim strings as they are passed, with the
- exception of the backslash ("\") which makes it possible to escape some
- characters such as the space. If the "-i" flag is passed before the first
- string, then the matching will be performed ignoring the case. In order
- to match the string "-i", either set it second, or pass the "--" flag
- before the first string. Same applies of course to match the string "--".
- Do not use string matches for binary fetches which might contain null bytes
- (0x00), as the comparison stops at the occurrence of the first null byte.
- Instead, convert the binary fetch to a hex string with the hex converter first.
Example:
# matches if the string <tag> is present in the binary sample
acl tag_found req.payload(0,0),hex -m sub 3C7461673E
7.1.4. Matching regular expressions (regexes)
- Just like with string matching, regex matching applies to verbatim strings as
- they are passed, with the exception of the backslash ("\") which makes it
- possible to escape some characters such as the space. If the "-i" flag is
- passed before the first regex, then the matching will be performed ignoring
- the case. In order to match the string "-i", either set it second, or pass
- the "--" flag before the first string. Same principle applies of course to
- match the string "--".
7.1.5. Matching arbitrary data blocks
- It is possible to match some extracted samples against a binary block which may
- not safely be represented as a string. For this, the patterns must be passed as
- a series of hexadecimal digits in an even number, when the match method is set
- to binary. Each sequence of two digits will represent a byte. The hexadecimal
- digits may be used upper or lower case.
Example :
# match "Hello\n" in the input stream (\x48 \x65 \x6c \x6c \x6f \x0a)
acl hello payload(0,6) -m bin 48656c6c6f0a
7.1.6. Matching IPv4 and IPv6 addresses
- IPv4 addresses values can be specified either as plain addresses or with a
- netmask appended, in which case the IPv4 address matches whenever it is
- within the network. Plain addresses may also be replaced with a resolvable
- host name, but this practice is generally discouraged as it makes it more
- difficult to read and debug configurations. If hostnames are used, you should
- at least 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.
- The dotted IPv4 address notation is supported in both regular as well as the
- abbreviated form with all-0-octets omitted:
- +------------------+------------------+------------------+
- | Example 1 | Example 2 | Example 3 |
- +------------------+------------------+------------------+
- | 192.168.0.1 | 10.0.0.12 | 127.0.0.1 |
- | 192.168.1 | 10.12 | 127.1 |
- | 192.168.0.1/22 | 10.0.0.12/8 | 127.0.0.1/8 |
- | 192.168.1/22 | 10.12/8 | 127.1/8 |
- +------------------+------------------+------------------+
- Notice that this is different from RFC 4632 CIDR address notation in which
- 192.168.42/24 would be equivalent to 192.168.42.0/24.
- IPv6 may be entered in their usual form, with or without a netmask appended.
- Only bit counts are accepted for IPv6 netmasks. In order to avoid any risk of
- trouble with randomly resolved IP addresses, host names are never allowed in
- IPv6 patterns.
- HAProxy is also able to match IPv4 addresses with IPv6 addresses in the
- following situations :
- - tested address is IPv4, pattern address is IPv4, the match applies
- in IPv4 using the supplied mask if any.
- - tested address is IPv6, pattern address is IPv6, the match applies
- in IPv6 using the supplied mask if any.
- - tested address is IPv6, pattern address is IPv4, the match applies in IPv4
- using the pattern's mask if the IPv6 address matches with 2002:IPV4::,
- ::IPV4 or ::ffff:IPV4, otherwise it fails.
- - tested address is IPv4, pattern address is IPv6, the IPv4 address is first
- converted to IPv6 by prefixing ::ffff: in front of it, then the match is
- applied in IPv6 using the supplied IPv6 mask.