7. Using ACLs and fetching samples ---------------------------------- Haproxy is capable of extracting data from request or response streams, from client or server information, from tables, environmental information etc... The action of extracting such data is called fetching a sample. Once retrieved, these samples may be used for various purposes such as a key to a stick-table, but most common usages consist in matching them against predefined constant data called patterns. 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 (eg: 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 fir 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 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 an 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 sub) : 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 "--". 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. 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. 7.2. Using ACLs to form conditions ---------------------------------- Some actions are only performed upon a valid condition. A condition is a combination of ACLs with operators. 3 operators are supported : - AND (implicit) - OR (explicit with the "or" keyword or the "||" operator) - Negation with the exclamation mark ("!") A condition is formed as a disjunctive form: [!]acl1 [!]acl2 ... [!]acln { or [!]acl1 [!]acl2 ... [!]acln } ... Such conditions are generally used after an "if" or "unless" statement, indicating when the condition will trigger the action. For instance, to block HTTP requests to the "*" URL with methods other than "OPTIONS", as well as POST requests without content-length, and GET or HEAD requests with a content-length greater than 0, and finally every request which is not either GET/HEAD/POST/OPTIONS ! acl missing_cl hdr_cnt(Content-length) eq 0 block if HTTP_URL_STAR !METH_OPTIONS || METH_POST missing_cl block if METH_GET HTTP_CONTENT block unless METH_GET or METH_POST or METH_OPTIONS To select a different backend for requests to static contents on the "www" site and to every request on the "img", "video", "download" and "ftp" hosts : acl url_static path_beg /static /images /img /css acl url_static path_end .gif .png .jpg .css .js acl host_www hdr_beg(host) -i www acl host_static hdr_beg(host) -i img. video. download. ftp. # now use backend "static" for all static-only hosts, and for static urls # of host "www". Use backend "www" for the rest. use_backend static if host_static or host_www url_static use_backend www if host_www It is also possible to form rules using "anonymous ACLs". Those are unnamed ACL expressions that are built on the fly without needing to be declared. They must be enclosed between braces, with a space before and after each brace (because the braces must be seen as independent words). Example : The following rule : acl missing_cl hdr_cnt(Content-length) eq 0 block if METH_POST missing_cl Can also be written that way : block if METH_POST { hdr_cnt(Content-length) eq 0 } It is generally not recommended to use this construct because it's a lot easier to leave errors in the configuration when written that way. However, for very simple rules matching only one source IP address for instance, it can make more sense to use them than to declare ACLs with random names. Another example of good use is the following : With named ACLs : acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor fail if site_dead With anonymous ACLs : monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 } See section 4.2 for detailed help on the "block" and "use_backend" keywords. 7.3. Fetching samples --------------------- Historically, sample fetch methods were only used to retrieve data to match against patterns using ACLs. With the arrival of stick-tables, a new class of sample fetch methods was created, most often sharing the same syntax as their ACL counterpart. These sample fetch methods are also known as "fetches". As of now, ACLs and fetches have converged. All ACL fetch methods have been made available as fetch methods, and ACLs may use any sample fetch method as well. This section details all available sample fetch methods and their output type. Some sample fetch methods have deprecated aliases that are used to maintain compatibility with existing configurations. They are then explicitly marked as deprecated and should not be used in new setups. The ACL derivatives are also indicated when available, with their respective matching methods. These ones all have a well defined default pattern matching method, so it is never necessary (though allowed) to pass the "-m" option to indicate how the sample will be matched using ACLs. As indicated in the sample type versus matching compatibility matrix above, when using a generic sample fetch method in an ACL, the "-m" option is mandatory unless the sample type is one of boolean, integer, IPv4 or IPv6. When the same keyword exists as an ACL keyword and as a standard fetch method, the ACL engine will automatically pick the ACL-only one by default. Some of these keywords support one or multiple mandatory arguments, and one or multiple optional arguments. These arguments are strongly typed and are checked when the configuration is parsed so that there is no risk of running with an incorrect argument (eg: an unresolved backend name). Fetch function arguments are passed between parenthesis and are delimited by commas. When an argument is optional, it will be indicated below between square brackets ('[ ]'). When all arguments are optional, the parenthesis may be omitted. Thus, the syntax of a standard sample fetch method is one of the following : - name - name(arg1) - name(arg1,arg2) 7.3.1. Converters ----------------- Sample fetch methods may be combined with transformations to be applied on top of the fetched sample (also called "converters"). These combinations form what is called "sample expressions" and the result is a "sample". Initially this was only supported by "stick on" and "stick store-request" directives but this has now be extended to all places where samples may be used (acls, log-format, unique-id-format, add-header, ...). These transformations are enumerated as a series of specific keywords after the sample fetch method. These keywords may equally be appended immediately after the fetch keyword's argument, delimited by a comma. These keywords can also support some arguments (eg: a netmask) which must be passed in parenthesis. The currently available list of transformation keywords include : base64 Converts a binary input sample to a base64 string. It is used to log or transfer binary content in a way that can be reliably transferred (eg: an SSL ID can be copied in a header). hex Converts a binary input sample to an hex string containing two hex digits per input byte. It is used to log or transfer hex dumps of some binary input data in a way that can be reliably transferred (eg: an SSL ID can be copied in a header). http_date([<offset>]) Converts an integer supposed to contain a date since epoch to a string representing this date in a format suitable for use in HTTP header fields. If an offset value is specified, then it is a number of seconds that is added to the date before the conversion is operated. This is particularly useful to emit Date header fields, Expires values in responses when combined with a positive offset, or Last-Modified values when the offset is negative. ipmask(<mask>) Apply a mask to an IPv4 address, and use the result for lookups and storage. This can be used to make all hosts within a certain mask to share the same table entries and as such use the same server. The mask can be passed in dotted form (eg: 255.255.255.0) or in CIDR form (eg: 24). language(<value>[,<default>]) Returns the value with the highest q-factor from a list as extracted from the "accept-language" header using "req.fhdr". Values with no q-factor have a q-factor of 1. Values with a q-factor of 0 are dropped. Only values which belong to the list of semi-colon delimited <values> will be considered. The argument <value> syntax is "lang[;lang[;lang[;...]]]". If no value matches the given list and a default value is provided, it is returned. Note that language names may have a variant after a dash ('-'). If this variant is present in the list, it will be matched, but if it is not, only the base language is checked. The match is case-sensitive, and the output string is always one of those provided in arguments. The ordering of arguments is meaningless, only the ordering of the values in the request counts, as the first value among multiple sharing the same q-factor is used. Example : # this configuration switches to the backend matching a # given language based on the request : acl es req.fhdr(accept-language),language(es;fr;en) -m str es acl fr req.fhdr(accept-language),language(es;fr;en) -m str fr acl en req.fhdr(accept-language),language(es;fr;en) -m str en use_backend spanish if es use_backend french if fr use_backend english if en default_backend choose_your_language lower Convert a string sample to lower case. This can only be placed after a string sample fetch function or after a transformation keyword returning a string type. The result is of type string. map(<map_file>[,<default_value>]) map_<match_type>(<map_file>[,<default_value>]) map_<match_type>_<output_type>(<map_file>[,<default_value>]) Search the input value from <map_file> using the <match_type> matching method, and return the associated value converted to the type <output_type>. If the input value cannot be found in the <map_file>, the converter returns the <default_value>. If the <default_value> is not set, the converter fails and acts as if no input value could be fetched. If the <match_type> is not set, it defaults to "str". Likewise, if the <output_type> is not set, it defaults to "str". For convenience, the "map" keyword is an alias for "map_str" and maps a string to another string. It is important to avoid overlapping between the keys : IP addresses and strings are stored in trees, so the first of the finest match will be used. Other keys are stored in lists, so the first matching occurrence will be used. The following array contains the list of all map functions avalaible sorted by input type, match type and output type. input type | match method | output type str | output type int | output type ip -----------+--------------+-----------------+-----------------+--------------- str | str | map_str | map_str_int | map_str_ip -----------+--------------+-----------------+-----------------+--------------- str | beg | map_beg | map_beg_int | map_end_ip -----------+--------------+-----------------+-----------------+--------------- str | sub | map_sub | map_sub_int | map_sub_ip -----------+--------------+-----------------+-----------------+--------------- str | dir | map_dir | map_dir_int | map_dir_ip -----------+--------------+-----------------+-----------------+--------------- str | dom | map_dom | map_dom_int | map_dom_ip -----------+--------------+-----------------+-----------------+--------------- str | end | map_end | map_end_int | map_end_ip -----------+--------------+-----------------+-----------------+--------------- str | reg | map_reg | map_reg_int | map_reg_ip -----------+--------------+-----------------+-----------------+--------------- int | int | map_int | map_int_int | map_int_ip -----------+--------------+-----------------+-----------------+--------------- ip | ip | map_ip | map_ip_int | map_ip_ip -----------+--------------+-----------------+-----------------+--------------- The file contains one key + value per line. Lines which start with '#' are ignored, just like empty lines. Leading tabs and spaces are stripped. The key is then the first "word" (series of non-space/tabs characters), and the value is what follows this series of space/tab till the end of the line excluding trailing spaces/tabs. Example : # this is a comment and is ignored 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- trailing spaces ignored | | | `---------- value | | `-------------------- middle spaces ignored | `---------------------------- key `------------------------------------ leading spaces ignored upper Convert a string sample to upper case. This can only be placed after a string sample fetch function or after a transformation keyword returning a string type. The result is of type string. 7.3.2. Fetching samples from internal states -------------------------------------------- A first set of sample fetch methods applies to internal information which does not even relate to any client information. These ones are sometimes used with "monitor-fail" directives to report an internal status to external watchers. The sample fetch methods described in this section are usable anywhere. always_false : boolean Always returns the boolean "false" value. It may be used with ACLs as a temporary replacement for another one when adjusting configurations. always_true : boolean Always returns the boolean "true" value. It may be used with ACLs as a temporary replacement for another one when adjusting configurations. avg_queue([<backend>]) : integer Returns the total number of queued connections of the designated backend divided by the number of active servers. The current backend is used if no backend is specified. This is very similar to "queue" except that the size of the farm is considered, in order to give a more accurate measurement of the time it may take for a new connection to be processed. The main usage is with ACL to return a sorry page to new users when it becomes certain they will get a degraded service, or to pass to the backend servers in a header so that they decide to work in degraded mode or to disable some functions to speed up the processing a bit. Note that in the event there would not be any active server anymore, twice the number of queued connections would be considered as the measured value. This is a fair estimate, as we expect one server to get back soon anyway, but we still prefer to send new traffic to another backend if in better shape. See also the "queue", "be_conn", and "be_sess_rate" sample fetches. be_conn([<backend>]) : integer Applies to the number of currently established connections on the backend, possibly including the connection being evaluated. If no backend name is specified, the current one is used. But it is also possible to check another backend. It can be used to use a specific farm when the nominal one is full. See also the "fe_conn", "queue" and "be_sess_rate" criteria. be_sess_rate([<backend>]) : integer Returns an integer value corresponding to the sessions creation rate on the backend, in number of new sessions per second. This is used with ACLs to switch to an alternate backend when an expensive or fragile one reaches too high a session rate, or to limit abuse of service (eg. prevent sucking of an online dictionary). It can also be useful to add this element to logs using a log-format directive. Example : # Redirect to an error page if the dictionary is requested too often backend dynamic mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned connslots([<backend>]) : integer Returns an integer value corresponding to the number of connection slots still available in the backend, by totaling the maximum amount of connections on all servers and the maximum queue size. This is probably only used with ACLs. The basic idea here is to be able to measure the number of connection "slots" still available (connection + queue), so that anything beyond that (intended usage; see "use_backend" keyword) can be redirected to a different backend. 'connslots' = number of available server connection slots, + number of available server queue slots. Note that while "fe_conn" may be used, "connslots" comes in especially useful when you have a case of traffic going to one single ip, splitting into multiple backends (perhaps using ACLs to do name-based load balancing) and you want to be able to differentiate between different backends, and their available "connslots". Also, whereas "nbsrv" only measures servers that are actually *down*, this fetch is more fine-grained and looks into the number of available connection slots as well. See also "queue" and "avg_queue". OTHER CAVEATS AND NOTES: at this point in time, the code does not take care of dynamic connections. Also, if any of the server maxconn, or maxqueue is 0, then this fetch clearly does not make sense, in which case the value returned will be -1. date([<offset>]) : integer Returns the current date as the epoch (number of seconds since 01/01/1970). If an offset value is specified, then it is a number of seconds that is added to the current date before returning the value. This is particularly useful to compute relative dates, as both positive and negative offsets are allowed. It is useful combined with the http_date converter. Example : # set an expires header to now+1 hour in every response http-response set-header Expires %[date(3600),http_date] env(<name>) : string Returns a string containing the value of environment variable <name>. As a reminder, environment variables are per-process and are sampled when the process starts. This can be useful to pass some information to a next hop server, or with ACLs to take specific action when the process is started a certain way. Examples : # Pass the Via header to next hop with the local hostname in it http-request add-header Via 1.1\ %[env(HOSTNAME)] # reject cookie-less requests when the STOP environment variable is set http-request deny if !{ cook(SESSIONID) -m found } { env(STOP) -m found } fe_conn([<frontend>]) : integer Returns the number of currently established connections on the frontend, possibly including the connection being evaluated. If no frontend name is specified, the current one is used. But it is also possible to check another frontend. It can be used to return a sorry page before hard-blocking, or to use a specific backend to drain new requests when the farm is considered full. This is mostly used with ACLs but can also be used to pass some statistics to servers in HTTP headers. See also the "dst_conn", "be_conn", "fe_sess_rate" fetches. fe_sess_rate([<frontend>]) : integer Returns an integer value corresponding to the sessions creation rate on the frontend, in number of new sessions per second. This is used with ACLs to limit the incoming session rate to an acceptable range in order to prevent abuse of service at the earliest moment, for example when combined with other layer 4 ACLs in order to force the clients to wait a bit for the rate to go down below the limit. It can also be useful to add this element to logs using a log-format directive. See also the "rate-limit sessions" directive for use in frontends. Example : # This frontend limits incoming mails to 10/s with a max of 100 # concurrent connections. We accept any connection below 10/s, and # force excess clients to wait for 100 ms. Since clients are limited to # 100 max, there cannot be more than 10 incoming mails per second. frontend mail bind :25 mode tcp maxconn 100 acl too_fast fe_sess_rate ge 10 tcp-request inspect-delay 100ms tcp-request content accept if ! too_fast tcp-request content accept if WAIT_END nbproc : integer Returns an integer value corresponding to the number of processes that were started (it equals the global "nbproc" setting). This is useful for logging and debugging purposes. nbsrv([<backend>]) : integer Returns an integer value corresponding to the number of usable servers of either the current backend or the named backend. This is mostly used with ACLs but can also be useful when added to logs. This is normally used to switch to an alternate backend when the number of servers is too low to to handle some load. It is useful to report a failure when combined with "monitor fail". proc : integer Returns an integer value corresponding to the position of the process calling the function, between 1 and global.nbproc. This is useful for logging and debugging purposes. queue([<backend>]) : integer Returns the total number of queued connections of the designated backend, including all the connections in server queues. If no backend name is specified, the current one is used, but it is also possible to check another one. This is useful with ACLs or to pass statistics to backend servers. This can be used to take actions when queuing goes above a known level, generally indicating a surge of traffic or a massive slowdown on the servers. One possible action could be to reject new users but still accept old ones. See also the "avg_queue", "be_conn", and "be_sess_rate" fetches. rand([<range>]) : integer Returns a random integer value within a range of <range> possible values, starting at zero. If the range is not specified, it defaults to 2^32, which gives numbers between 0 and 4294967295. It can be useful to pass some values needed to take some routing decisions for example, or just for debugging purposes. This random must not be used for security purposes. srv_conn([<backend>/]<server>) : integer Returns an integer value corresponding to the number of currently established connections on the designated server, possibly including the connection being evaluated. If <backend> is omitted, then the server is looked up in the current backend. It can be used to use a specific farm when one server is full, or to inform the server about our view of the number of active connections with it. See also the "fe_conn", "be_conn" and "queue" fetch methods. srv_is_up([<backend>/]<server>) : boolean Returns true when the designated server is UP, and false when it is either DOWN or in maintenance mode. If <backend> is omitted, then the server is looked up in the current backend. It is mainly used to take action based on an external status reported via a health check (eg: a geographical site's availability). Another possible use which is more of a hack consists in using dummy servers as boolean variables that can be enabled or disabled from the CLI, so that rules depending on those ACLs can be tweaked in realtime. srv_sess_rate([<backend>/]<server>) : integer Returns an integer corresponding to the sessions creation rate on the designated server, in number of new sessions per second. If <backend> is omitted, then the server is looked up in the current backend. This is mostly used with ACLs but can make sense with logs too. This is used to switch to an alternate backend when an expensive or fragile one reaches too high a session rate, or to limit abuse of service (eg. prevent latent requests from overloading servers). Example : # Redirect to a separate back acl srv1_full srv_sess_rate(be1/srv1) gt 50 acl srv2_full srv_sess_rate(be1/srv2) gt 50 use_backend be2 if srv1_full or srv2_full stopping : boolean Returns TRUE if the process calling the function is currently stopping. This can be useful for logging, or for relaxing certain checks or helping close certain connections upon graceful shutdown. table_avl([<table>]) : integer Returns the total number of available entries in the current proxy's stick-table or in the designated stick-table. See also table_cnt. table_cnt([<table>]) : integer Returns the total number of entries currently in use in the current proxy's stick-table or in the designated stick-table. See also src_conn_cnt and table_avl for other entry counting methods. 7.3.3. Fetching samples at Layer 4 ---------------------------------- The layer 4 usually describes just the transport layer which in haproxy is closest to the connection, where no content is yet made available. The fetch methods described here are usable as low as the "tcp-request connection" rule sets unless they require some future information. Those generally include TCP/IP addresses and ports, as well as elements from stick-tables related to the incoming connection. For retrieving a value from a sticky counters, the counter number can be explicitly set as 0, 1, or 2 using the pre-defined "sc0_", "sc1_", or "sc2_" prefix, or it can be specified as the first integer argument when using the "sc_" prefix. An optional table may be specified with the "sc*" form, in which case the currently tracked key will be looked up into this alternate table instead of the table currently being tracked. be_id : integer Returns an integer containing the current backend's id. It can be used in frontends with responses to check which backend processed the request. dst : ip This is the destination IPv4 address of the connection on the client side, which is the address the client connected to. It can be useful when running in transparent mode. It is of type IP and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, according to RFC 4291. dst_conn : integer Returns an integer value corresponding to the number of currently established connections on the same socket including the one being evaluated. It is normally used with ACLs but can as well be used to pass the information to servers in an HTTP header or in logs. It can be used to either return a sorry page before hard-blocking, or to use a specific backend to drain new requests when the socket is considered saturated. This offers the ability to assign different limits to different listening ports or addresses. See also the "fe_conn" and "be_conn" fetches. dst_port : integer Returns an integer value corresponding to the destination TCP port of the connection on the client side, which is the port the client connected to. This might be used when running in transparent mode, when assigning dynamic ports to some clients for a whole application session, to stick all users to a same server, or to pass the destination port information to a server using an HTTP header. fe_id : integer Returns an integer containing the current frontend's id. It can be used in backends to check from which backend it was called, or to stick all users coming via a same frontend to the same server. sc_bytes_in_rate(<ctr>[,<table>]) : integer sc0_bytes_in_rate([<table>]) : integer sc1_bytes_in_rate([<table>]) : integer sc2_bytes_in_rate([<table>]) : integer Returns the average client-to-server bytes rate from the currently tracked counters, measured in amount of bytes over the period configured in the table. See also src_bytes_in_rate. sc_bytes_out_rate(<ctr>[,<table>]) : integer sc0_bytes_out_rate([<table>]) : integer sc1_bytes_out_rate([<table>]) : integer sc2_bytes_out_rate([<table>]) : integer Returns the average server-to-client bytes rate from the currently tracked counters, measured in amount of bytes over the period configured in the table. See also src_bytes_out_rate. sc_clr_gpc0(<ctr>[,<table>]) : integer sc0_clr_gpc0([<table>]) : integer sc1_clr_gpc0([<table>]) : integer sc2_clr_gpc0([<table>]) : integer Clears the first General Purpose Counter associated to the currently tracked counters, and returns its previous value. Before the first invocation, the stored value is zero, so first invocation will always return zero. This is typically used as a second ACL in an expression in order to mark a connection when a first ACL was verified : # block if 5 consecutive requests continue to come faster than 10 sess # per second, and reset the counter as soon as the traffic slows down. acl abuse sc0_http_req_rate gt 10 acl kill sc0_inc_gpc0 gt 5 acl save sc0_clr_gpc0 ge 0 tcp-request connection accept if !abuse save tcp-request connection reject if abuse kill sc_conn_cnt(<ctr>[,<table>]) : integer sc0_conn_cnt([<table>]) : integer sc1_conn_cnt([<table>]) : integer sc2_conn_cnt([<table>]) : integer Returns the cumulated number of incoming connections from currently tracked counters. See also src_conn_cnt. sc_conn_cur(<ctr>[,<table>]) : integer sc0_conn_cur([<table>]) : integer sc1_conn_cur([<table>]) : integer sc2_conn_cur([<table>]) : integer Returns the current amount of concurrent connections tracking the same tracked counters. This number is automatically incremented when tracking begins and decremented when tracking stops. See also src_conn_cur. sc_conn_rate(<ctr>[,<table>]) : integer sc0_conn_rate([<table>]) : integer sc1_conn_rate([<table>]) : integer sc2_conn_rate([<table>]) : integer Returns the average connection rate from the currently tracked counters, measured in amount of connections over the period configured in the table. See also src_conn_rate. sc_get_gpc0(<ctr>[,<table>]) : integer sc0_get_gpc0([<table>]) : integer sc1_get_gpc0([<table>]) : integer sc2_get_gpc0([<table>]) : integer Returns the value of the first General Purpose Counter associated to the currently tracked counters. See also src_get_gpc0 and sc/sc0/sc1/sc2_inc_gpc0. sc_gpc0_rate(<ctr>[,<table>]) : integer sc0_gpc0_rate([<table>]) : integer sc1_gpc0_rate([<table>]) : integer sc2_gpc0_rate([<table>]) : integer Returns the average increment rate of the first General Purpose Counter associated to the currently tracked counters. It reports the frequency which the gpc0 counter was incremented over the configured period. See also src_gpc0_rate, sc/sc0/sc1/sc2_get_gpc0, and sc/sc0/sc1/sc2_inc_gpc0. Note that the "gpc0_rate" counter must be stored in the stick-table for a value to be returned, as "gpc0" only holds the event count. sc_http_err_cnt(<ctr>[,<table>]) : integer sc0_http_err_cnt([<table>]) : integer sc1_http_err_cnt([<table>]) : integer sc2_http_err_cnt([<table>]) : integer Returns the cumulated number of HTTP errors from the currently tracked counters. This includes the both request errors and 4xx error responses. See also src_http_err_cnt. sc_http_err_rate(<ctr>[,<table>]) : integer sc0_http_err_rate([<table>]) : integer sc1_http_err_rate([<table>]) : integer sc2_http_err_rate([<table>]) : integer Returns the average rate of HTTP errors from the currently tracked counters, measured in amount of errors over the period configured in the table. This includes the both request errors and 4xx error responses. See also src_http_err_rate. sc_http_req_cnt(<ctr>[,<table>]) : integer sc0_http_req_cnt([<table>]) : integer sc1_http_req_cnt([<table>]) : integer sc2_http_req_cnt([<table>]) : integer Returns the cumulated number of HTTP requests from the currently tracked counters. This includes every started request, valid or not. See also src_http_req_cnt. sc_http_req_rate(<ctr>[,<table>]) : integer sc0_http_req_rate([<table>]) : integer sc1_http_req_rate([<table>]) : integer sc2_http_req_rate([<table>]) : integer Returns the average rate of HTTP requests from the currently tracked counters, measured in amount of requests over the period configured in the table. This includes every started request, valid or not. See also src_http_req_rate. sc_inc_gpc0(<ctr>[,<table>]) : integer sc0_inc_gpc0([<table>]) : integer sc1_inc_gpc0([<table>]) : integer sc2_inc_gpc0([<table>]) : integer Increments the first General Purpose Counter associated to the currently tracked counters, and returns its new value. Before the first invocation, the stored value is zero, so first invocation will increase it to 1 and will return 1. This is typically used as a second ACL in an expression in order to mark a connection when a first ACL was verified : acl abuse sc0_http_req_rate gt 10 acl kill sc0_inc_gpc0 gt 0 tcp-request connection reject if abuse kill sc_kbytes_in(<ctr>[,<table>]) : integer sc0_kbytes_in([<table>]) : integer sc1_kbytes_in([<table>]) : integer sc2_kbytes_in([<table>]) : integer Returns the total amount of client-to-server data from the currently tracked counters, measured in kilobytes. The test is currently performed on 32-bit integers, which limits values to 4 terabytes. See also src_kbytes_in. sc_kbytes_out(<ctr>[,<table>]) : integer sc0_kbytes_out([<table>]) : integer sc1_kbytes_out([<table>]) : integer sc2_kbytes_out([<table>]) : integer Returns the total amount of server-to-client data from the currently tracked counters, measured in kilobytes. The test is currently performed on 32-bit integers, which limits values to 4 terabytes. See also src_kbytes_out. sc_sess_cnt(<ctr>[,<table>]) : integer sc0_sess_cnt([<table>]) : integer sc1_sess_cnt([<table>]) : integer sc2_sess_cnt([<table>]) : integer Returns the cumulated number of incoming connections that were transformed into sessions, which means that they were accepted by a "tcp-request connection" rule, from the currently tracked counters. A backend may count more sessions than connections because each connection could result in many backend sessions if some HTTP keep-alive is performed over the connection with the client. See also src_sess_cnt. sc_sess_rate(<ctr>[,<table>]) : integer sc0_sess_rate([<table>]) : integer sc1_sess_rate([<table>]) : integer sc2_sess_rate([<table>]) : integer Returns the average session rate from the currently tracked counters, measured in amount of sessions over the period configured in the table. A session is a connection that got past the early "tcp-request connection" rules. A backend may count more sessions than connections because each connection could result in many backend sessions if some HTTP keep-alive is performed over the connection with the client. See also src_sess_rate. sc_tracked(<ctr>[,<table>]) : boolean sc0_tracked([<table>]) : boolean sc1_tracked([<table>]) : boolean sc2_tracked([<table>]) : boolean Returns true if the designated session counter is currently being tracked by the current session. This can be useful when deciding whether or not we want to set some values in a header passed to the server. sc_trackers(<ctr>[,<table>]) : integer sc0_trackers([<table>]) : integer sc1_trackers([<table>]) : integer sc2_trackers([<table>]) : integer Returns the current amount of concurrent connections tracking the same tracked counters. This number is automatically incremented when tracking begins and decremented when tracking stops. It differs from sc0_conn_cur in that it does not rely on any stored information but on the table's reference count (the "use" value which is returned by "show table" on the CLI). This may sometimes be more suited for layer7 tracking. It can be used to tell a server how many concurrent connections there are from a given address for example. so_id : integer Returns an integer containing the current listening socket's id. It is useful in frontends involving many "bind" lines, or to stick all users coming via a same socket to the same server. src : ip This is the source IPv4 address of the client of the session. It is of type IP and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4 addresses are mapped to their IPv6 equivalent, according to RFC 4291. Note that it is the TCP-level source address which is used, and not the address of a client behind a proxy. However if the "accept-proxy" bind directive is used, it can be the address of a client behind another PROXY-protocol compatible component for all rule sets except "tcp-request connection" which sees the real address. Example: # add an HTTP header in requests with the originating address' country http-request set-header X-Country %[src,map_ip(geoip.lst)] src_bytes_in_rate([<table>]) : integer Returns the average bytes rate from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in amount of bytes over the period configured in the table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_bytes_in_rate. src_bytes_out_rate([<table>]) : integer Returns the average bytes rate to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in amount of bytes over the period configured in the table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_bytes_out_rate. src_clr_gpc0([<table>]) : integer Clears the first General Purpose Counter associated to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, and returns its previous value. If the address is not found, an entry is created and 0 is returned. This is typically used as a second ACL in an expression in order to mark a connection when a first ACL was verified : # block if 5 consecutive requests continue to come faster than 10 sess # per second, and reset the counter as soon as the traffic slows down. acl abuse src_http_req_rate gt 10 acl kill src_inc_gpc0 gt 5 acl save src_clr_gpc0 ge 0 tcp-request connection accept if !abuse save tcp-request connection reject if abuse kill src_conn_cnt([<table>]) : integer Returns the cumulated number of connections initiated from the current incoming connection's source address in the current proxy's stick-table or in the designated stick-table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_conn_cnt. src_conn_cur([<table>]) : integer Returns the current amount of concurrent connections initiated from the current incoming connection's source address in the current proxy's stick-table or in the designated stick-table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_conn_cur. src_conn_rate([<table>]) : integer Returns the average connection rate from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in amount of connections over the period configured in the table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_conn_rate. src_get_gpc0([<table>]) : integer Returns the value of the first General Purpose Counter associated to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_get_gpc0 and src_inc_gpc0. src_gpc0_rate([<table>]) : integer Returns the average increment rate of the first General Purpose Counter associated to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table. It reports the frequency which the gpc0 counter was incremented over the configured period. See also sc/sc0/sc1/sc2_gpc0_rate, src_get_gpc0, and sc/sc0/sc1/sc2_inc_gpc0. Note that the "gpc0_rate" counter must be stored in the stick-table for a value to be returned, as "gpc0" only holds the event count. src_http_err_cnt([<table>]) : integer Returns the cumulated number of HTTP errors from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table. This includes the both request errors and 4xx error responses. See also sc/sc0/sc1/sc2_http_err_cnt. If the address is not found, zero is returned. src_http_err_rate([<table>]) : integer Returns the average rate of HTTP errors from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in amount of errors over the period configured in the table. This includes the both request errors and 4xx error responses. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_http_err_rate. src_http_req_cnt([<table>]) : integer Returns the cumulated number of HTTP requests from the incoming connection's source address in the current proxy's stick-table or in the designated stick- table. This includes every started request, valid or not. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_http_req_cnt. src_http_req_rate([<table>]) : integer Returns the average rate of HTTP requests from the incoming connection's source address in the current proxy's stick-table or in the designated stick- table, measured in amount of requests over the period configured in the table. This includes every started request, valid or not. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_http_req_rate. src_inc_gpc0([<table>]) : integer Increments the first General Purpose Counter associated to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, and returns its new value. If the address is not found, an entry is created and 1 is returned. See also sc0/sc2/sc2_inc_gpc0. This is typically used as a second ACL in an expression in order to mark a connection when a first ACL was verified : acl abuse src_http_req_rate gt 10 acl kill src_inc_gpc0 gt 0 tcp-request connection reject if abuse kill src_kbytes_in([<table>]) : integer Returns the total amount of data received from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in kilobytes. If the address is not found, zero is returned. The test is currently performed on 32-bit integers, which limits values to 4 terabytes. See also sc/sc0/sc1/sc2_kbytes_in. src_kbytes_out([<table>]) : integer Returns the total amount of data sent to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in kilobytes. If the address is not found, zero is returned. The test is currently performed on 32-bit integers, which limits values to 4 terabytes. See also sc/sc0/sc1/sc2_kbytes_out. src_port : integer Returns an integer value corresponding to the TCP source port of the connection on the client side, which is the port the client connected from. Usage of this function is very limited as modern protocols do not care much about source ports nowadays. src_sess_cnt([<table>]) : integer Returns the cumulated number of connections initiated from the incoming connection's source IPv4 address in the current proxy's stick-table or in the designated stick-table, that were transformed into sessions, which means that they were accepted by "tcp-request" rules. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_sess_cnt. src_sess_rate([<table>]) : integer Returns the average session rate from the incoming connection's source address in the current proxy's stick-table or in the designated stick-table, measured in amount of sessions over the period configured in the table. A session is a connection that went past the early "tcp-request" rules. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_sess_rate. src_updt_conn_cnt([<table>]) : integer Creates or updates the entry associated to the incoming connection's source address in the current proxy's stick-table or in the designated stick-table. This table must be configured to store the "conn_cnt" data type, otherwise the match will be ignored. The current count is incremented by one, and the expiration timer refreshed. The updated count is returned, so this match can't return zero. This was used to reject service abusers based on their source address. Note: it is recommended to use the more complete "track-sc*" actions in "tcp-request" rules instead. Example : # This frontend limits incoming SSH connections to 3 per 10 second for # each source address, and rejects excess connections until a 10 second # silence is observed. At most 20 addresses are tracked. listen ssh bind :22 mode tcp maxconn 100 stick-table type ip size 20 expire 10s store conn_cnt tcp-request content reject if { src_updt_conn_cnt gt 3 } server local 127.0.0.1:22 srv_id : integer Returns an integer containing the server's id when processing the response. While it's almost only used with ACLs, it may be used for logging or debugging. 7.3.4. Fetching samples at Layer 5 ---------------------------------- The layer 5 usually describes just the session layer which in haproxy is closest to the session once all the connection handshakes are finished, but when no content is yet made available. The fetch methods described here are usable as low as the "tcp-request content" rule sets unless they require some future information. Those generally include the results of SSL negotiations. ssl_bc : boolean Returns true when the back connection was made via an SSL/TLS transport layer and is locally deciphered. This means the outgoing connection was made other a server with the "ssl" option. ssl_bc_alg_keysize : integer Returns the symmetric cipher key size supported in bits when the outgoing connection was made over an SSL/TLS transport layer. ssl_bc_cipher : string Returns the name of the used cipher when the outgoing connection was made over an SSL/TLS transport layer. ssl_bc_protocol : string Returns the name of the used protocol when the outgoing connection was made over an SSL/TLS transport layer. ssl_bc_unique_id : binary When the outgoing connection was made over an SSL/TLS transport layer, returns the TLS unique ID as defined in RFC5929 section 3. The unique id can be encoded to base64 using the converter: "ssl_bc_unique_id,base64". ssl_bc_session_id : binary Returns the SSL ID of the back connection when the outgoing connection was made over an SSL/TLS transport layer. It is useful to log if we want to know if session was reused or not. ssl_bc_use_keysize : integer Returns the symmetric cipher key size used in bits when the outgoing connection was made over an SSL/TLS transport layer. ssl_c_ca_err : integer When the incoming connection was made over an SSL/TLS transport layer, returns the ID of the first error detected during verification of the client certificate at depth > 0, or 0 if no error was encountered during this verification process. Please refer to your SSL library's documentation to find the exhaustive list of error codes. ssl_c_ca_err_depth : integer When the incoming connection was made over an SSL/TLS transport layer, returns the depth in the CA chain of the first error detected during the verification of the client certificate. If no error is encountered, 0 is returned. ssl_c_der : binary Returns the DER formatted certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. When used for an ACL, the value(s) to match against can be passed in hexadecimal form. ssl_c_err : integer When the incoming connection was made over an SSL/TLS transport layer, returns the ID of the first error detected during verification at depth 0, or 0 if no error was encountered during this verification process. Please refer to your SSL library's documentation to find the exhaustive list of error codes. ssl_c_i_dn([<entry>[,<occ>]]) : string When the incoming connection was made over an SSL/TLS transport layer, returns the full distinguished name of the issuer of the certificate presented by the client when no <entry> is specified, or the value of the first given entry found from the beginning of the DN. If a positive/negative occurrence number is specified as the optional second argument, it returns the value of the nth given entry value from the beginning/end of the DN. For instance, "ssl_c_i_dn(OU,2)" the second organization unit, and "ssl_c_i_dn(CN)" retrieves the common name. ssl_c_key_alg : string Returns the name of the algorithm used to generate the key of the certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. ssl_c_notafter : string Returns the end date presented by the client as a formatted string YYMMDDhhmmss[Z] when the incoming connection was made over an SSL/TLS transport layer. ssl_c_notbefore : string Returns the start date presented by the client as a formatted string YYMMDDhhmmss[Z] when the incoming connection was made over an SSL/TLS transport layer. ssl_c_s_dn([<entry>[,<occ>]]) : string When the incoming connection was made over an SSL/TLS transport layer, returns the full distinguished name of the subject of the certificate presented by the client when no <entry> is specified, or the value of the first given entry found from the beginning of the DN. If a positive/negative occurrence number is specified as the optional second argument, it returns the value of the nth given entry value from the beginning/end of the DN. For instance, "ssl_c_s_dn(OU,2)" the second organization unit, and "ssl_c_s_dn(CN)" retrieves the common name. ssl_c_serial : binary Returns the serial of the certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. When used for an ACL, the value(s) to match against can be passed in hexadecimal form. ssl_c_sha1 : binary Returns the SHA-1 fingerprint of the certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. This can be used to stick a client to a server, or to pass this information to a server. Note that the output is binary, so if you want to pass that signature to the server, you need to encode it in hex or base64, such as in the example below: http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex] ssl_c_sig_alg : string Returns the name of the algorithm used to sign the certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. ssl_c_used : boolean Returns true if current SSL session uses a client certificate even if current connection uses SSL session resumption. See also "ssl_fc_has_crt". ssl_c_verify : integer Returns the verify result error ID when the incoming connection was made over an SSL/TLS transport layer, otherwise zero if no error is encountered. Please refer to your SSL library's documentation for an exhaustive list of error codes. ssl_c_version : integer Returns the version of the certificate presented by the client when the incoming connection was made over an SSL/TLS transport layer. ssl_f_der : binary Returns the DER formatted certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. When used for an ACL, the value(s) to match against can be passed in hexadecimal form. ssl_f_i_dn([<entry>[,<occ>]]) : string When the incoming connection was made over an SSL/TLS transport layer, returns the full distinguished name of the issuer of the certificate presented by the frontend when no <entry> is specified, or the value of the first given entry found from the beginning of the DN. If a positive/negative occurrence number is specified as the optional second argument, it returns the value of the nth given entry value from the beginning/end of the DN. For instance, "ssl_f_i_dn(OU,2)" the second organization unit, and "ssl_f_i_dn(CN)" retrieves the common name. ssl_f_key_alg : string Returns the name of the algorithm used to generate the key of the certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. ssl_f_notafter : string Returns the end date presented by the frontend as a formatted string YYMMDDhhmmss[Z] when the incoming connection was made over an SSL/TLS transport layer. ssl_f_notbefore : string Returns the start date presented by the frontend as a formatted string YYMMDDhhmmss[Z] when the incoming connection was made over an SSL/TLS transport layer. ssl_f_s_dn([<entry>[,<occ>]]) : string When the incoming connection was made over an SSL/TLS transport layer, returns the full distinguished name of the subject of the certificate presented by the frontend when no <entry> is specified, or the value of the first given entry found from the beginning of the DN. If a positive/negative occurrence number is specified as the optional second argument, it returns the value of the nth given entry value from the beginning/end of the DN. For instance, "ssl_f_s_dn(OU,2)" the second organization unit, and "ssl_f_s_dn(CN)" retrieves the common name. ssl_f_serial : binary Returns the serial of the certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. When used for an ACL, the value(s) to match against can be passed in hexadecimal form. ssl_f_sha1 : binary Returns the SHA-1 fingerprint of the certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. This can be used to know which certificate was chosen using SNI. ssl_f_sig_alg : string Returns the name of the algorithm used to sign the certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. ssl_f_version : integer Returns the version of the certificate presented by the frontend when the incoming connection was made over an SSL/TLS transport layer. ssl_fc : boolean Returns true when the front connection was made via an SSL/TLS transport layer and is locally deciphered. This means it has matched a socket declared with a "bind" line having the "ssl" option. Example : # This passes "X-Proto: https" to servers when client connects over SSL listen http-https bind :80 bind :443 ssl crt /etc/haproxy.pem http-request add-header X-Proto https if { ssl_fc } ssl_fc_alg_keysize : integer Returns the symmetric cipher key size supported in bits when the incoming connection was made over an SSL/TLS transport layer. ssl_fc_alpn : string This extracts the Application Layer Protocol Negotiation field from an incoming connection made via a TLS transport layer and locally deciphered by haproxy. The result is a string containing the protocol name advertised by the client. The SSL library must have been built with support for TLS extensions enabled (check haproxy -vv). Note that the TLS ALPN extension is not advertised unless the "alpn" keyword on the "bind" line specifies a protocol list. Also, nothing forces the client to pick a protocol from this list, any other one may be requested. The TLS ALPN extension is meant to replace the TLS NPN extension. See also "ssl_fc_npn". ssl_fc_cipher : string Returns the name of the used cipher when the incoming connection was made over an SSL/TLS transport layer. ssl_fc_has_crt : boolean Returns true if a client certificate is present in an incoming connection over SSL/TLS transport layer. Useful if 'verify' statement is set to 'optional'. Note: on SSL session resumption with Session ID or TLS ticket, client certificate is not present in the current connection but may be retrieved from the cache or the ticket. So prefer "ssl_c_used" if you want to check if current SSL session uses a client certificate. ssl_fc_has_sni : boolean This checks for the presence of a Server Name Indication TLS extension (SNI) in an incoming connection was made over an SSL/TLS transport layer. Returns true when the incoming connection presents a TLS SNI field. This requires that the SSL library is build with support for TLS extensions enabled (check haproxy -vv). ssl_fc_npn : string This extracts the Next Protocol Negotiation field from an incoming connection made via a TLS transport layer and locally deciphered by haproxy. The result is a string containing the protocol name advertised by the client. The SSL library must have been built with support for TLS extensions enabled (check haproxy -vv). Note that the TLS NPN extension is not advertised unless the "npn" keyword on the "bind" line specifies a protocol list. Also, nothing forces the client to pick a protocol from this list, any other one may be requested. Please note that the TLS NPN extension was replaced with ALPN. ssl_fc_protocol : string Returns the name of the used protocol when the incoming connection was made over an SSL/TLS transport layer. ssl_fc_unique_id : binary When the incoming connection was made over an SSL/TLS transport layer, returns the TLS unique ID as defined in RFC5929 section 3. The unique id can be encoded to base64 using the converter: "ssl_bc_unique_id,base64". ssl_fc_session_id : binary Returns the SSL ID of the front connection when the incoming connection was made over an SSL/TLS transport layer. It is useful to stick a given client to a server. It is important to note that some browsers refresh their session ID every few minutes. ssl_fc_sni : string This extracts the Server Name Indication TLS extension (SNI) field from an incoming connection made via an SSL/TLS transport layer and locally deciphered by haproxy. The result (when present) typically is a string matching the HTTPS host name (253 chars or less). The SSL library must have been built with support for TLS extensions enabled (check haproxy -vv). This fetch is different from "req_ssl_sni" above in that it applies to the connection being deciphered by haproxy and not to SSL contents being blindly forwarded. See also "ssl_fc_sni_end" and "ssl_fc_sni_reg" below. This requires that the SSL library is build with support for TLS extensions enabled (check haproxy -vv). ACL derivatives : ssl_fc_sni_end : suffix match ssl_fc_sni_reg : regex match ssl_fc_use_keysize : integer Returns the symmetric cipher key size used in bits when the incoming connection was made over an SSL/TLS transport layer. 7.3.5. Fetching samples from buffer contents (Layer 6) ------------------------------------------------------ Fetching samples from buffer contents is a bit different from the previous sample fetches above because the sampled data are ephemeral. These data can only be used when they're available and will be lost when they're forwarded. For this reason, samples fetched from buffer contents during a request cannot be used in a response for example. Even while the data are being fetched, they can change. Sometimes it is necessary to set some delays or combine multiple sample fetch methods to ensure that the expected data are complete and usable, for example through TCP request content inspection. Please see the "tcp-request content" keyword for more detailed information on the subject. payload(<offset>,<length>) : binary (deprecated) This is an alias for "req.payload" when used in the context of a request (eg: "stick on", "stick match"), and for "res.payload" when used in the context of a response such as in "stick store response". payload_lv(<offset1>,<length>[,<offset2>]) : binary (deprecated) This is an alias for "req.payload_lv" when used in the context of a request (eg: "stick on", "stick match"), and for "res.payload_lv" when used in the context of a response such as in "stick store response". req.len : integer req_len : integer (deprecated) Returns an integer value corresponding to the number of bytes present in the request buffer. This is mostly used in ACL. It is important to understand that this test does not return false as long as the buffer is changing. This means that a check with equality to zero will almost always immediately match at the beginning of the session, while a test for more data will wait for that data to come in and return false only when haproxy is certain that no more data will come in. This test was designed to be used with TCP request content inspection. req.payload(<offset>,<length>) : binary This extracts a binary block of <length> bytes and starting at byte <offset> in the request buffer. As a special case, if the <length> argument is zero, the the whole buffer from <offset> to the end is extracted. This can be used with ACLs in order to check for the presence of some content in a buffer at any location. ACL alternatives : payload(<offset>,<length>) : hex binary match req.payload_lv(<offset1>,<length>[,<offset2>]) : binary This extracts a binary block whose size is specified at <offset1> for <length> bytes, and which starts at <offset2> if specified or just after the length in the request buffer. The <offset2> parameter also supports relative offsets if prepended with a '+' or '-' sign. ACL alternatives : payload_lv(<offset1>,<length>[,<offset2>]) : hex binary match Example : please consult the example from the "stick store-response" keyword. req.proto_http : boolean req_proto_http : boolean (deprecated) Returns true when data in the request buffer look like HTTP and correctly parses as such. It is the same parser as the common HTTP request parser which is used so there should be no surprises. The test does not match until the request is complete, failed or timed out. This test may be used to report the protocol in TCP logs, but the biggest use is to block TCP request analysis until a complete HTTP request is present in the buffer, for example to track a header. Example: # track request counts per "base" (concatenation of Host+URL) tcp-request inspect-delay 10s tcp-request content reject if !HTTP tcp-request content track-sc0 base table req-rate req.rdp_cookie([<name>]) : string rdp_cookie([<name>]) : string (deprecated) When the request buffer looks like the RDP protocol, extracts the RDP cookie <name>, or any cookie if unspecified. The parser only checks for the first cookie, as illustrated in the RDP protocol specification. The cookie name is case insensitive. Generally the "MSTS" cookie name will be used, as it can contain the user name of the client connecting to the server if properly configured on the client. The "MSTSHASH" cookie is often used as well for session stickiness to servers. This differs from "balance rdp-cookie" in that any balancing algorithm may be used and thus the distribution of clients to backend servers is not linked to a hash of the RDP cookie. It is envisaged that using a balancing algorithm such as "balance roundrobin" or "balance leastconn" will lead to a more even distribution of clients to backend servers than the hash used by "balance rdp-cookie". ACL derivatives : req_rdp_cookie([<name>]) : exact string match Example : listen tse-farm bind 0.0.0.0:3389 # wait up to 5s for an RDP cookie in the request tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # apply RDP cookie persistence persist rdp-cookie # Persist based on the mstshash cookie # This is only useful makes sense if # balance rdp-cookie is not used stick-table type string size 204800 stick on req.rdp_cookie(mstshash) server srv1 1.1.1.1:3389 server srv1 1.1.1.2:3389 See also : "balance rdp-cookie", "persist rdp-cookie", "tcp-request" and the "req_rdp_cookie" ACL. req.rdp_cookie_cnt([name]) : integer rdp_cookie_cnt([name]) : integer (deprecated) Tries to parse the request buffer as RDP protocol, then returns an integer corresponding to the number of RDP cookies found. If an optional cookie name is passed, only cookies matching this name are considered. This is mostly used in ACL. ACL derivatives : req_rdp_cookie_cnt([<name>]) : integer match req.ssl_hello_type : integer req_ssl_hello_type : integer (deprecated) Returns an integer value containing the type of the SSL hello message found in the request buffer if the buffer contains data that parse as a complete SSL (v3 or superior) client hello message. Note that this only applies to raw contents found in the request buffer and not to contents deciphered via an SSL data layer, so this will not work with "bind" lines having the "ssl" option. This is mostly used in ACL to detect presence of an SSL hello message that is supposed to contain an SSL session ID usable for stickiness. req.ssl_sni : string req_ssl_sni : string (deprecated) Returns a string containing the value of the Server Name TLS extension sent by a client in a TLS stream passing through the request buffer if the buffer contains data that parse as a complete SSL (v3 or superior) client hello message. Note that this only applies to raw contents found in the request buffer and not to contents deciphered via an SSL data layer, so this will not work with "bind" lines having the "ssl" option. SNI normally contains the name of the host the client tries to connect to (for recent browsers). SNI is useful for allowing or denying access to certain hosts when SSL/TLS is used by the client. This test was designed to be used with TCP request content inspection. If content switching is needed, it is recommended to first wait for a complete client hello (type 1), like in the example below. See also "ssl_fc_sni". ACL derivatives : req_ssl_sni : exact string match Examples : # Wait for a client hello for at most 5 seconds tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } use_backend bk_allow if { req_ssl_sni -f allowed_sites } default_backend bk_sorry_page res.ssl_hello_type : integer rep_ssl_hello_type : integer (deprecated) Returns an integer value containing the type of the SSL hello message found in the response buffer if the buffer contains data that parses as a complete SSL (v3 or superior) hello message. Note that this only applies to raw contents found in the response buffer and not to contents deciphered via an SSL data layer, so this will not work with "server" lines having the "ssl" option. This is mostly used in ACL to detect presence of an SSL hello message that is supposed to contain an SSL session ID usable for stickiness. req.ssl_ver : integer req_ssl_ver : integer (deprecated) Returns an integer value containing the version of the SSL/TLS protocol of a stream present in the request buffer. Both SSLv2 hello messages and SSLv3 messages are supported. TLSv1 is announced as SSL version 3.1. The value is composed of the major version multiplied by 65536, added to the minor version. Note that this only applies to raw contents found in the request buffer and not to contents deciphered via an SSL data layer, so this will not work with "bind" lines having the "ssl" option. The ACL version of the test matches against a decimal notation in the form MAJOR.MINOR (eg: 3.1). This fetch is mostly used in ACL. ACL derivatives : req_ssl_ver : decimal match res.len : integer Returns an integer value corresponding to the number of bytes present in the response buffer. This is mostly used in ACL. It is important to understand that this test does not return false as long as the buffer is changing. This means that a check with equality to zero will almost always immediately match at the beginning of the session, while a test for more data will wait for that data to come in and return false only when haproxy is certain that no more data will come in. This test was designed to be used with TCP response content inspection. res.payload(<offset>,<length>) : binary This extracts a binary block of <length> bytes and starting at byte <offset> in the response buffer. As a special case, if the <length> argument is zero, the the whole buffer from <offset> to the end is extracted. This can be used with ACLs in order to check for the presence of some content in a buffer at any location. res.payload_lv(<offset1>,<length>[,<offset2>]) : binary This extracts a binary block whose size is specified at <offset1> for <length> bytes, and which starts at <offset2> if specified or just after the length in the response buffer. The <offset2> parameter also supports relative offsets if prepended with a '+' or '-' sign. Example : please consult the example from the "stick store-response" keyword. wait_end : boolean This fetch either returns true when the inspection period is over, or does not fetch. It is only used in ACLs, in conjunction with content analysis to avoid returning a wrong verdict early. It may also be used to delay some actions, such as a delayed reject for some special addresses. Since it either stops the rules evaluation or immediately returns true, it is recommended to use this acl as the last one in a rule. Please note that the default ACL "WAIT_END" is always usable without prior declaration. This test was designed to be used with TCP request content inspection. Examples : # delay every incoming request by 2 seconds tcp-request inspect-delay 2s tcp-request content accept if WAIT_END # don't immediately tell bad guys they are rejected tcp-request inspect-delay 10s acl goodguys src 10.0.0.0/24 acl badguys src 10.0.1.0/24 tcp-request content accept if goodguys tcp-request content reject if badguys WAIT_END tcp-request content reject 7.3.6. Fetching HTTP samples (Layer 7) -------------------------------------- It is possible to fetch samples from HTTP contents, requests and responses. This application layer is also called layer 7. It is only possible to fetch the data in this section when a full HTTP request or response has been parsed from its respective request or response buffer. This is always the case with all HTTP specific rules and for sections running with "mode http". When using TCP content inspection, it may be necessary to support an inspection delay in order to let the request or response come in first. These fetches may require a bit more CPU resources than the layer 4 ones, but not much since the request and response are indexed. base : string This returns the concatenation of the first Host header and the path part of the request, which starts at the first slash and ends before the question mark. It can be useful in virtual hosted environments to detect URL abuses as well as to improve shared caches efficiency. Using this with a limited size stick table also allows one to collect statistics about most commonly requested objects by host/path. With ACLs it can allow simple content switching rules involving the host and the path at the same time, such as "www.example.com/favicon.ico". See also "path" and "uri". ACL derivatives : 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 base32 : integer This returns a 32-bit hash of the value returned by the "base" fetch method above. This is useful to track per-URL activity on high traffic sites without having to store all URLs. Instead a shorter hash is stored, saving a lot of memory. The output type is an unsigned integer. base32+src : binary This returns the concatenation of the base32 fetch above and the src fetch below. The resulting type is of type binary, with a size of 8 or 20 bytes depending on the source address family. This can be used to track per-IP, per-URL counters. capture.req.hdr(<idx>) : string This extracts the content of the header captured by the "capture request header", idx is the position of the capture keyword in the configuration. The first entry is an index of 0. See also: "capture request header". capture.req.method : string This extracts the METHOD of an HTTP request. It can be used in both request and response. Unlike "method", it can be used in both request and response because it's allocated. capture.req.uri : string This extracts the request's URI, which starts at the first slash and ends before the first space in the request (without the host part). Unlike "path" and "url", it can be used in both request and response because it's allocated. capture.req.ver : string This extracts the request's HTTP version and returns either "HTTP/1.0" or "HTTP/1.1". Unlike "req.ver", it can be used in both request, response, and logs because it relies on a persistent flag. capture.res.hdr(<idx>) : string This extracts the content of the header captured by the "capture response header", idx is the position of the capture keyword in the configuration. The first entry is an index of 0. See also: "capture response header" capture.res.ver : string This extracts the response's HTTP version and returns either "HTTP/1.0" or "HTTP/1.1". Unlike "res.ver", it can be used in logs because it relies on a persistent flag. req.cook([<name>]) : string cook([<name>]) : string (deprecated) This extracts the last occurrence of the cookie name <name> on a "Cookie" header line from the request, and returns its value as string. If no name is specified, the first cookie value is returned. When used with ACLs, all matching cookies are evaluated. Spaces around the name and the value are ignored as requested by the Cookie header specification (RFC6265). The cookie name is case-sensitive. Empty cookies are valid, so an empty cookie may very well return an empty value if it is present. Use the "found" match to detect presence. Use the res.cook() variant for response cookies sent by the server. ACL derivatives : 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.cook_cnt([<name>]) : integer cook_cnt([<name>]) : integer (deprecated) Returns an integer value representing the number of occurrences of the cookie <name> in the request, or all cookies if <name> is not specified. req.cook_val([<name>]) : integer cook_val([<name>]) : integer (deprecated) This extracts the last occurrence of the cookie name <name> on a "Cookie" header line from the request, and converts its value to an integer which is returned. If no name is specified, the first cookie value is returned. When used in ACLs, all matching names are iterated over until a value matches. cookie([<name>]) : string (deprecated) This extracts the last occurrence of the cookie name <name> on a "Cookie" header line from the request, or a "Set-Cookie" header from the response, and returns its value as a string. A typical use is to get multiple clients sharing a same profile use the same server. This can be similar to what "appsession" does with the "request-learn" statement, but with support for multi-peer synchronization and state keeping across restarts. If no name is specified, the first cookie value is returned. This fetch should not be used anymore and should be replaced by req.cook() or res.cook() instead as it ambiguously uses the direction based on the context where it is used. See also : "appsession". hdr([<name>[,<occ>]]) : string This is equivalent to req.hdr() when used on requests, and to res.hdr() when used on responses. Please refer to these respective fetches for more details. In case of doubt about the fetch direction, please use the explicit ones. Note that contrary to the hdr() sample fetch method, the hdr_* ACL keywords unambiguously apply to the request headers. req.fhdr(<name>[,<occ>]) : string This extracts the last occurrence of header <name> in an HTTP request. When used from an ACL, all occurrences are iterated over until a match is found. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. It differs from req.hdr() in that any commas present in the value are returned and are not used as delimiters. This is sometimes useful with headers such as User-Agent. req.fhdr_cnt([<name>]) : integer Returns an integer value representing the number of occurrences of request header field name <name>, or the total number of header fields if <name> is not specified. Contrary to its req.hdr_cnt() cousin, this function returns the number of full line headers and does not stop on commas. req.hdr([<name>[,<occ>]]) : string This extracts the last occurrence of header <name> in an HTTP request. When used from an ACL, all occurrences are iterated over until a match is found. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. A typical use is with the X-Forwarded-For header once converted to IP, associated with an IP stick-table. The function considers any comma as a delimiter for distinct values. If full-line headers are desired instead, use req.fhdr(). Please carefully check RFC2616 to know how certain headers are supposed to be parsed. Also, some of them are case insensitive (eg: Connection). ACL derivatives : 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 req.hdr_cnt([<name>]) : integer hdr_cnt([<header>]) : integer (deprecated) Returns an integer value representing the number of occurrences of request header field name <name>, or the total number of header field values if <name> is not specified. It is important to remember that one header line may count as several headers if it has several values. The function considers any comma as a delimiter for distinct values. If full-line headers are desired instead, req.fhdr_cnt() should be used instead. With ACLs, it can be used to detect presence, absence or abuse of a specific header, as well as to block request smuggling attacks by rejecting requests which contain more than one of certain headers. See "req.hdr" for more information on header matching. req.hdr_ip([<name>[,<occ>]]) : ip hdr_ip([<name>[,<occ>]]) : ip (deprecated) This extracts the last occurrence of header <name> in an HTTP request, converts it to an IPv4 or IPv6 address and returns this address. When used with ACLs, all occurrences are checked, and if <name> is omitted, every value of every header is checked. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. A typical use is with the X-Forwarded-For and X-Client-IP headers. req.hdr_val([<name>[,<occ>]]) : integer hdr_val([<name>[,<occ>]]) : integer (deprecated) This extracts the last occurrence of header <name> in an HTTP request, and converts it to an integer value. When used with ACLs, all occurrences are checked, and if <name> is omitted, every value of every header is checked. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. A typical use is with the X-Forwarded-For header. http_auth(<userlist>) : boolean Returns a boolean indicating whether the authentication data received from the client match a username &password stored in the specified userlist. This fetch function is not really useful outside of ACLs. Currently only http basic auth is supported. http_auth_group(<userlist>) : string Returns a string corresponding to the user name found in the authentication data received from the client if both the user name and password are valid according to the specified userlist. The main purpose is to use it in ACLs where it is then checked whether the user belongs to any group within a list. This fetch function is not really useful outside of ACLs. Currently only http basic auth is supported. ACL derivatives : http_auth_group(<userlist>) : group ... Returns true when the user extracted from the request and whose password is valid according to the specified userlist belongs to at least one of the groups. http_first_req : boolean Returns true when the request being processed is the first one of the connection. This can be used to add or remove headers that may be missing from some requests when a request is not the first one, or to help grouping requests in the logs. method : integer + string Returns an integer value corresponding to the method in the HTTP request. For example, "GET" equals 1 (check sources to establish the matching). Value 9 means "other method" and may be converted to a string extracted from the stream. This should not be used directly as a sample, this is only meant to be used from ACLs, which transparently convert methods from patterns to these integer + string values. Some predefined ACL already check for most common methods. ACL derivatives : method : case insensitive method match Example : # only accept GET and HEAD requests acl valid_method method GET HEAD http-request deny if ! valid_method path : string This extracts the request's URL path, which starts at the first slash and ends before the question mark (without the host part). A typical use is with prefetch-capable caches, and with portals which need to aggregate multiple information from databases and keep them in caches. Note that with outgoing caches, it would be wiser to use "url" instead. With ACLs, it's typically used to match exact file names (eg: "/login.php"), or directory parts using the derivative forms. See also the "url" and "base" fetch methods. ACL derivatives : 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 : string req_ver : string (deprecated) Returns the version string from the HTTP request, for example "1.1". This can be useful for logs, but is mostly there for ACL. Some predefined ACL already check for versions 1.0 and 1.1. ACL derivatives : req_ver : exact string match res.comp : boolean Returns the boolean "true" value if the response has been compressed by HAProxy, otherwise returns boolean "false". This may be used to add information in the logs. res.comp_algo : string Returns a string containing the name of the algorithm used if the response was compressed by HAProxy, for example : "deflate". This may be used to add some information in the logs. res.cook([<name>]) : string scook([<name>]) : string (deprecated) This extracts the last occurrence of the cookie name <name> on a "Set-Cookie" header line from the response, and returns its value as string. If no name is specified, the first cookie value is returned. ACL derivatives : scook([<name>] : exact string match res.cook_cnt([<name>]) : integer scook_cnt([<name>]) : integer (deprecated) Returns an integer value representing the number of occurrences of the cookie <name> in the response, or all cookies if <name> is not specified. This is mostly useful when combined with ACLs to detect suspicious responses. res.cook_val([<name>]) : integer scook_val([<name>]) : integer (deprecated) This extracts the last occurrence of the cookie name <name> on a "Set-Cookie" header line from the response, and converts its value to an integer which is returned. If no name is specified, the first cookie value is returned. res.fhdr([<name>[,<occ>]]) : string This extracts the last occurrence of header <name> in an HTTP response, or of the last header if no <name> is specified. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. It differs from res.hdr() in that any commas present in the value are returned and are not used as delimiters. If this is not desired, the res.hdr() fetch should be used instead. This is sometimes useful with headers such as Date or Expires. res.fhdr_cnt([<name>]) : integer Returns an integer value representing the number of occurrences of response header field name <name>, or the total number of header fields if <name> is not specified. Contrary to its res.hdr_cnt() cousin, this function returns the number of full line headers and does not stop on commas. If this is not desired, the res.hdr_cnt() fetch should be used instead. res.hdr([<name>[,<occ>]]) : string shdr([<name>[,<occ>]]) : string (deprecated) This extracts the last occurrence of header <name> in an HTTP response, or of the last header if no <name> is specified. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. This can be useful to learn some data into a stick-table. The function considers any comma as a delimiter for distinct values. If this is not desired, the res.fhdr() fetch should be used instead. ACL derivatives : 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.hdr_cnt([<name>]) : integer shdr_cnt([<name>]) : integer (deprecated) Returns an integer value representing the number of occurrences of response header field name <name>, or the total number of header fields if <name> is not specified. The function considers any comma as a delimiter for distinct values. If this is not desired, the res.fhdr_cnt() fetch should be used instead. res.hdr_ip([<name>[,<occ>]]) : ip shdr_ip([<name>[,<occ>]]) : ip (deprecated) This extracts the last occurrence of header <name> in an HTTP response, convert it to an IPv4 or IPv6 address and returns this address. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. This can be useful to learn some data into a stick table. res.hdr_val([<name>[,<occ>]]) : integer shdr_val([<name>[,<occ>]]) : integer (deprecated) This extracts the last occurrence of header <name> in an HTTP response, and converts it to an integer value. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. This can be useful to learn some data into a stick table. res.ver : string resp_ver : string (deprecated) Returns the version string from the HTTP response, for example "1.1". This can be useful for logs, but is mostly there for ACL. ACL derivatives : resp_ver : exact string match set-cookie([<name>]) : string (deprecated) This extracts the last occurrence of the cookie name <name> on a "Set-Cookie" header line from the response and uses the corresponding value to match. This can be comparable to what "appsession" does with default options, but with support for multi-peer synchronization and state keeping across restarts. This fetch function is deprecated and has been superseded by the "res.cook" fetch. This keyword will disappear soon. See also : "appsession" status : integer Returns an integer containing the HTTP status code in the HTTP response, for example, 302. It is mostly used within ACLs and integer ranges, for example, to remove any Location header if the response is not a 3xx. url : string This extracts the request's URL as presented in the request. A typical use is with prefetch-capable caches, and with portals which need to aggregate multiple information from databases and keep them in caches. With ACLs, using "path" is preferred over using "url", because clients may send a full URL as is normally done with proxies. The only real use is to match "*" which does not match in "path", and for which there is already a predefined ACL. See also "path" and "base". ACL derivatives : 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 url_ip : ip This extracts the IP address from the request's URL when the host part is presented as an IP address. Its use is very limited. For instance, a monitoring system might use this field as an alternative for the source IP in order to test what path a given source address would follow, or to force an entry in a table for a given source address. With ACLs it can be used to restrict access to certain systems through a proxy, for example when combined with option "http_proxy". url_port : integer This extracts the port part from the request's URL. Note that if the port is not specified in the request, port 80 is assumed. With ACLs it can be used to restrict access to certain systems through a proxy, for example when combined with option "http_proxy". urlp(<name>[,<delim>]) : string url_param(<name>[,<delim>]) : string This extracts the first occurrence of the parameter <name> in the query string, which begins after either '?' or <delim>, and which ends before '&', ';' or <delim>. The parameter name is case-sensitive. The result is a string corresponding to the value of the parameter <name> as presented in the request (no URL decoding is performed). This can be used for session stickiness based on a client ID, to extract an application cookie passed as a URL parameter, or in ACLs to apply some checks. Note that the ACL version of this fetch do not iterate over multiple parameters and stop at the first one as well. ACL derivatives : 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 Example : # match http://example.com/foo?PHPSESSIONID=some_id stick on urlp(PHPSESSIONID) # match http://example.com/foo;JSESSIONID=some_id stick on urlp(JSESSIONID,;) urlp_val(<name>[,<delim>]) : integer See "urlp" above. This one extracts the URL parameter <name> in the request and converts it to an integer value. This can be used for session stickiness based on a user ID for example, or with ACLs to match a page number or price. 7.4. Pre-defined ACLs --------------------- Some predefined ACLs are hard-coded so that they do not have to be declared in every frontend which needs them. They all have their names in upper case in order to avoid confusion. Their equivalence is provided below. 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 ---------------+-----------------------------+---------------------------------