- HAPEE 1.7r1 User Guide
- Getting Started
- Traffic Management
- Running HAProxy
- Stopping and Restarting HAProxy
- Performing Health Checks
- Generating Alerts for Events
- Capturing Traffic Data
- Configuring HAPEE for Transport Layer Security (TLS)
- Fetching Data Samples
- Setting Up Access Control Lists (ACLs)
- Writing Conditions
- Rewriting HTTP Protocol
- Redirecting HTTP Traffic
- Compressing HTTP Traffic
- Configuring the lb-update module
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
ACLs are defined using the keyword acl. The syntax is:
acl <aclname> <criterion>[,<converter>] [flags] [operator] [<pattern>] …
ACLs require the following parameters:
Name of the ACL to describe it as much as possible.
|<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>.|
Data provided by <criterion> is compared to a<pattern> list.
An ACL can return two values:
|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>|
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
The criterion is generally the name of a sample fetch method, or one of the Sample fetch ACL derivatives declinations.
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:
- integer (signed or unsigned)
- IPv4 or IPv6 address
- binary data block
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.
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: exact string 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
ACLs support the following flags:
- -i: ignores case during matching of all subsequent patterns
- -f </path/tp/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.
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
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.
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.
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.
The matching <methods> must be one of the following:
|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.|
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.
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|
|binary||none, use “-m”|
The ACL engine can match these types against patterns of the following types:
- 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 to use for each compatible combination.
The method in bold is the default and works without any -m flag.
|none (presence only)||found||found||found||found||found|
|none (boolean value)||bool||bool||bool|
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.
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.
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.
For easier use, comparison operators are also supported.
Available operators for integer matching are:
- 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
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.
By default, string matching applies to string or binary fetch methods or converters , and exists in 6 formats.
They use the -m flag:
|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 “–”.
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 “–”.
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.
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.|
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|
|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|
|WAIT_END||wait_end||Wait for end of content analysis|
- 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 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/