7. Using ACLs and pattern extraction ------------------------------------ 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 : - define test criteria with sets of values - perform actions only if a set of tests is valid The actions generally consist in blocking the request, or selecting a backend. 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. 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 following ACL flags are currently supported : -i : ignore case during matching of all subsequent patterns. -f : load patterns from a file. -- : force end of flags. Useful when a string looks like one of the flags. The "-f" flag is special as it loads all of the lines it finds in the file specified in argument and loads all of them before continuing. 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 needed 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. Also, note that the "-i" flag applies to subsequent entries and not to entries loaded from files preceeding 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 too. Note that right now it is difficult for the ACL parsers to report errors, so if a file is unreadable or unparsable, the most you'll get is a parse error in the ACL. Thus, file-based ACLs should only be produced by reliable processes. Supported types of values are : - integers or integer ranges - strings - regular expressions - IP addresses and networks 7.1. Matching integers ---------------------- Matching integers is special in that ranges and operators are permitted. 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.2. Matching strings --------------------- 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.3. 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.4. Matching IPv4 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. 7.5. Available matching criteria -------------------------------- 7.5.1. Matching at Layer 4 and below ------------------------------------ A first set of criteria applies to information which does not require any analysis of the request or response contents. Those generally include TCP/IP addresses and ports, as well as internal values independant on the stream. always_false This one never matches. All values and flags are ignored. It may be used as a temporary replacement for another one when adjusting configurations. always_true This one always matches. All values and flags are ignored. It may be used as a temporary replacement for another one when adjusting configurations. avg_queue <integer> avg_queue(backend) <integer> Returns the total number of queued connections of the designated backend divided by the number of active servers. 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 to return a sorry page to new users when it becomes certain they will get a degraded service. Note that in the event there would not be any active server anymore, we would consider twice the number of queued connections 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" criteria. be_conn <integer> 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 <integer> be_sess_rate(backend) <integer> Returns true when the sessions creation rate on the backend matches the specified values or ranges, in number of new sessions per second. 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 sucking of an online dictionary). 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 <integer> connslots(backend) <integer> 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 acl 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 acl clearly does not make sense, in which case the value returned will be -1. dst <ip_address> Applies to the local IPv4 address the client connected to. It can be used to switch to a different backend for some alternative addresses. dst_conn <integer> Applies to the number of currently established connections on the same socket including the one being evaluated. 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" criteria. dst_port <integer> Applies to the local port the client connected to. It can be used to switch to a different backend for some alternative ports. fe_conn <integer> fe_conn(frontend) <integer> Applies to 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 either return a sorry page before hard-blocking, or to use a specific backend to drain new requests when the farm is considered saturated. See also the "dst_conn", "be_conn" and "fe_sess_rate" criteria. fe_id <integer> Applies to the frontend's id. Can be used in backends to check from which frontend it was called. fe_sess_rate <integer> fe_sess_rate(frontend) <integer> Returns true when the session creation rate on the current or the named frontend matches the specified values or ranges, expressed in new sessions per second. This is used to limit the connection rate to acceptable ranges in order to prevent abuse of service at the earliest moment. This can be combined with layer 4 ACLs in order to force the clients to wait a bit for the rate to go down below the limit. 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 nbsrv <integer> nbsrv(backend) <integer> Returns true when the number of usable servers of either the current backend or the named backend matches the values or ranges specified. This is 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". queue <integer> 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 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" criteria. so_id <integer> Applies to the socket's id. Useful in frontends with many bind keywords. src <ip_address> Applies to the client's IPv4 address. It is usually used to limit access to certain resources such as statistics. Note that it is the TCP-level source address which is used, and not the address of a client behind a proxy. src_port <integer> Applies to the client's TCP source port. This has a very limited usage. srv_is_up(<server>) srv_is_up(<backend>/<server>) 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. The function takes no arguments since it is used as a boolean. 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. 7.5.2. Matching contents at Layer 4 ----------------------------------- A second set of criteria depends on data found in buffers, but which can change during analysis. This requires that some data has been buffered, for instance through TCP request content inspection. Please see the "tcp-request" keyword for more detailed information on the subject. req_len <integer> Returns true when the length of the data in the request buffer matches the specified range. 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_proto_http 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. This test can be used for instance to direct HTTP traffic to a given port and HTTPS traffic to another one using TCP request content inspection rules. req_rdp_cookie <string> req_rdp_cookie(name) <string> Returns true when data in the request buffer look like the RDP protocol, and a cookie is present and equal to <string>. By default, any cookie name is checked, but a specific cookie name can be specified in parenthesis. The parser only checks for the first cookie, as illustrated in the RDP protocol specification. The cookie name is case insensitive. This ACL can be useful with the "MSTS" cookie, as it can contain the user name of the client connecting to the server if properly configured on the client. This can be used to restrict access to certain servers to certain users. req_rdp_cookie_cnt <integer> req_rdp_cookie_cnt(name) <integer> Returns true when the data in the request buffer look like the RDP protocol and the number of RDP cookies matches the specified range (typically zero or one). Optionally a specific cookie name can be checked. This is a simple way of detecting the RDP protocol, as clients generally send the MSTS or MSTSHASH cookies. req_ssl_ver <decimal> Returns true when data in the request buffer look like SSL, with a protocol version matching the specified range. Both SSLv2 hello messages and SSLv3 messages are supported. The test tries to be strict enough to avoid being easily fooled. In particular, it waits for as many bytes as announced in the message header if this header looks valid (bound to the buffer size). Note that TLSv1 is announced as SSL version 3.1. This test was designed to be used with TCP request content inspection. wait_end Waits for the end of the analysis period to return true. This may be used 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.5.3. Matching at Layer 7 -------------------------- A third set of criteria applies to information which can be found at the application layer (layer 7). Those require that a full HTTP request has been read, and are only evaluated then. They may require slightly more CPU resources than the layer 4 ones, but not much since the request and response are indexed. hdr <string> hdr(header) <string> Note: all the "hdr*" matching criteria either apply to all headers, or to a particular header whose name is passed between parenthesis and without any space. The header name is not case-sensitive. The header matching complies with RFC2616, and treats as separate headers all values delimited by commas. Use the shdr() variant for response headers sent by the server. The "hdr" criteria returns true if any of the headers matching the criteria match any of the strings. This can be used to check exact for values. For instance, checking that "connection: close" is set : hdr(Connection) -i close hdr_beg <string> hdr_beg(header) <string> Returns true when one of the headers begins with one of the strings. See "hdr" for more information on header matching. Use the shdr_beg() variant for response headers sent by the server. hdr_cnt <integer> hdr_cnt(header) <integer> Returns true when the number of occurrence of the specified header matches the values or ranges specified. It is important to remember that one header line may count as several headers if it has several values. This is 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 "hdr" for more information on header matching. Use the shdr_cnt() variant for response headers sent by the server. hdr_dir <string> hdr_dir(header) <string> Returns true when one of the headers contains one of the strings either isolated or delimited by slashes. This is used to perform filename or directory name matching, and may be used with Referer. See "hdr" for more information on header matching. Use the shdr_dir() variant for response headers sent by the server. hdr_dom <string> hdr_dom(header) <string> Returns true when one of the headers contains one of the strings either isolated or delimited by dots. This is used to perform domain name matching, and may be used with the Host header. See "hdr" for more information on header matching. Use the shdr_dom() variant for response headers sent by the server. hdr_end <string> hdr_end(header) <string> Returns true when one of the headers ends with one of the strings. See "hdr" for more information on header matching. Use the shdr_end() variant for response headers sent by the server. hdr_ip <ip_address> hdr_ip(header) <ip_address> Returns true when one of the headers' values contains an IP address matching <ip_address>. This is mainly used with headers such as X-Forwarded-For or X-Client-IP. See "hdr" for more information on header matching. Use the shdr_ip() variant for response headers sent by the server. hdr_reg <regex> hdr_reg(header) <regex> Returns true when one of the headers matches of the regular expressions. It can be used at any time, but it is important to remember that regex matching is slower than other methods. See also other "hdr_" criteria, as well as "hdr" for more information on header matching. Use the shdr_reg() variant for response headers sent by the server. hdr_sub <string> hdr_sub(header) <string> Returns true when one of the headers contains one of the strings. See "hdr" for more information on header matching. Use the shdr_sub() variant for response headers sent by the server. hdr_val <integer> hdr_val(header) <integer> Returns true when one of the headers starts with a number which matches the values or ranges specified. This may be used to limit content-length to acceptable values for example. See "hdr" for more information on header matching. Use the shdr_val() variant for response headers sent by the server. http_auth(userlist) http_auth_group(userlist) <group> [<group>]* Returns true when authentication data received from the client matches username &password stored on the userlist. It is also possible to use http_auth_group to check if the user is assigned to at least one of specified groups. Currently only http basic auth is supported. http_req_first 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 even to perform some specific ACL checks only on the first request. method <string> Applies to the method in the HTTP request, eg: "GET". Some predefined ACL already check for most common methods. path <string> Returns true when the path part of the request, which starts at the first slash and ends before the question mark, equals one of the strings. It may be used to match known files, such as /favicon.ico. path_beg <string> Returns true when the path begins with one of the strings. This can be used to send certain directory names to alternative backends. path_dir <string> Returns true when one of the strings is found isolated or delimited with slashes in the path. This is used to perform filename or directory name matching without the risk of wrong match due to colliding prefixes. See also "url_dir" and "path_sub". path_dom <string> Returns true when one of the strings is found isolated or delimited with dots in the path. This may be used to perform domain name matching in proxy requests. See also "path_sub" and "url_dom". path_end <string> Returns true when the path ends with one of the strings. This may be used to control file name extension. path_reg <regex> Returns true when the path matches one of the regular expressions. It can be used any time, but it is important to remember that regex matching is slower than other methods. See also "url_reg" and all "path_" criteria. path_sub <string> Returns true when the path contains one of the strings. It can be used to detect particular patterns in paths, such as "../" for example. See also "path_dir". req_ver <string> Applies to the version string in the HTTP request, eg: "1.0". Some predefined ACL already check for versions 1.0 and 1.1. status <integer> Applies to the HTTP status code in the HTTP response, eg: "302". It can be used to act on responses depending on status ranges, for instance, remove any Location header if the response is not a 3xx. url <string> Applies to the whole URL passed in the request. The only real use is to match "*", for which there already is a predefined ACL. url_beg <string> Returns true when the URL begins with one of the strings. This can be used to check whether a URL begins with a slash or with a protocol scheme. url_dir <string> Returns true when one of the strings is found isolated or delimited with slashes in the URL. This is used to perform filename or directory name matching without the risk of wrong match due to colliding prefixes. See also "path_dir" and "url_sub". url_dom <string> Returns true when one of the strings is found isolated or delimited with dots in the URL. This is used to perform domain name matching without the risk of wrong match due to colliding prefixes. See also "url_sub". url_end <string> Returns true when the URL ends with one of the strings. It has very limited use. "path_end" should be used instead for filename matching. url_ip <ip_address> Applies to the IP address specified in the absolute URI in an HTTP request. It can be used to prevent access to certain resources such as local network. It is useful with option "http_proxy". url_port <integer> Applies to the port specified in the absolute URI in an HTTP request. It can be used to prevent access to certain resources. It is useful with option "http_proxy". Note that if the port is not specified in the request, port 80 is assumed. url_reg <regex> Returns true when the URL matches one of the regular expressions. It can be used any time, but it is important to remember that regex matching is slower than other methods. See also "path_reg" and all "url_" criteria. url_sub <string> Returns true when the URL contains one of the strings. It can be used to detect particular patterns in query strings for example. See also "path_sub". 7.6. 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 ---------------+-----------------------------+--------------------------------- 7.7. 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 independant 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.8. Pattern extraction ----------------------- The stickiness features relies on pattern extraction in the request and response. Sometimes the data needs to be converted first before being stored, for instance converted from ASCII to IP or upper case to lower case. All these operations of data extraction and conversion are defined as "pattern extraction rules". A pattern rule always has the same format. It begins with a single pattern fetch word, potentially followed by a list of arguments within parenthesis then an optional list of transformations. As much as possible, the pattern fetch functions use the same name as their equivalent used in ACLs. The list of currently supported pattern fetch functions is the following : src This is the source IPv4 address of the client of the session. It is of type IP and only works with such tables. dst This is the destination IPv4 address of the session on the client side, which is the address the client connected to. It can be useful when running in transparent mode. It is of typie IP and only works with such tables. dst_port This is the destination TCP port of the session on the client side, which is the port the client connected to. This might be used when running in transparent mode or when assigning dynamic ports to some clients for a whole application session. It is of type integer and only works with such tables. hdr(name) This extracts the last occurrence of header <name> in an HTTP request and converts it to an IP address. This IP address is then used to match the table. A typical use is with the x-forwarded-for header. The currently available list of transformations include : lower Convert a string pattern to lower case. This can only be placed after a string pattern fetch function or after a conversion function returning a string type. The result is of type string. upper Convert a string pattern to upper case. This can only be placed after a string pattern fetch function or after a conversion function returning a string type. The result is of type string. 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).