7.1. Matching integers
7.2. Matching strings
7.3. Matching regular expressions (regexes)
-7.4. Matching IPv4 addresses
+7.4. Matching IPv4 and IPv6 addresses
7.5. Available matching criteria
7.5.1. Matching at Layer 4 and below
7.5.2. Matching contents at Layer 4
The currently supported settings are the following ones.
-addr <ipv4>
+addr <ipv4|ipv6>
Using the "addr" parameter, it becomes possible to use a different IP address
to send health-checks. On some servers, it may be desirable to dedicate an IP
address to specific component able to perform complex tests which are more
match the string "--".
-7.4. Matching IPv4 addresses
+7.4. Matching IPv4 and IPv6 addresses
----------------------------
IPv4 addresses values can be specified either as plain addresses or with a
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.5. Available matching criteria
--------------------------------
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.
+ Applies to the local IPv4 or IPv6 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
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.
+ Applies to the client's IPv4 or IPv6 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_bytes_in_rate <integer>
src_bytes_in_rate(<table>) <integer>
response headers sent by the server.
hdr_ip <ip_address>
-hdr_ip(<header>[,<occ>]) <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
+hdr_ip(<header>[,<occ>]) <address>
+ Returns true when one of the headers' values contains an IPv4 or IPv6 address
+ matching <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_len <integer>
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_ip <address>
+ Applies to the IPv4 or IPv6 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_len <integer>
Returns true when the url length matches the values or ranges specified. This
Returns true when the URL parameter "<name>" ends with one of the strings.
urlp_ip(<name>) <ip_address>
- Returns true when the URL parameter "<name>" contains an IPv4 address which
- matches one of the specified IP addresses.
+ Returns true when the URL parameter "<name>" contains an IPv4 or IPv6 address
+ which matches one of the specified addresses.
urlp_len(<name>) <integer>
Returns true when the URL parameter "<name>" has a length matching the values
int acl_match_ip(struct sample *smp, struct acl_pattern *pattern)
{
- struct in_addr *s;
+ unsigned int v4; /* in network byte order */
+ struct in6_addr *v6;
+ int bits, pos;
+ struct in6_addr tmp6;
+
+ if (pattern->type == SMP_T_IPV4) {
+ if (smp->type == SMP_T_IPV4) {
+ v4 = smp->data.ipv4.s_addr;
+ }
+ else if (smp->type == SMP_T_IPV6) {
+ /* v4 match on a V6 sample. We want to check at least for
+ * the following forms :
+ * - ::ffff:ip:v4 (ipv4 mapped)
+ * - ::0000:ip:v4 (old ipv4 mapped)
+ * - 2002:ip:v4:: (6to4)
+ */
+ if (*(uint32_t*)&smp->data.ipv6.s6_addr[0] == 0 &&
+ *(uint32_t*)&smp->data.ipv6.s6_addr[4] == 0 &&
+ (*(uint32_t*)&smp->data.ipv6.s6_addr[8] == 0 ||
+ *(uint32_t*)&smp->data.ipv6.s6_addr[8] == htonl(0xFFFF))) {
+ v4 = *(uint32_t*)&smp->data.ipv6.s6_addr[12];
+ }
+ else if (*(uint16_t*)&smp->data.ipv6.s6_addr[0] == htons(0x2002)) {
+ v4 = htonl((ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[2]) << 16) +
+ ntohs(*(uint16_t*)&smp->data.ipv6.s6_addr[4]));
+ }
+ else
+ return ACL_PAT_FAIL;
+ }
+ else
+ return ACL_PAT_FAIL;
- if (smp->type != SMP_T_IPV4 || pattern->type != SMP_T_IPV4)
- return ACL_PAT_FAIL;
+ if (((v4 ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
+ return ACL_PAT_PASS;
+ else
+ return ACL_PAT_FAIL;
+ }
+ else if (pattern->type == SMP_T_IPV6) {
+ if (smp->type == SMP_T_IPV4) {
+ /* Convert the IPv4 sample address to IPv4 with the
+ * mapping method using the ::ffff: prefix.
+ */
+ memset(&tmp6, 0, 10);
+ *(uint16_t*)&tmp6.s6_addr[10] = htons(0xffff);
+ *(uint32_t*)&tmp6.s6_addr[12] = smp->data.ipv4.s_addr;
+ v6 = &tmp6;
+ }
+ else if (smp->type == SMP_T_IPV6) {
+ v6 = &smp->data.ipv6;
+ }
+ else {
+ return ACL_PAT_FAIL;
+ }
- s = &smp->data.ipv4;
- if (((s->s_addr ^ pattern->val.ipv4.addr.s_addr) & pattern->val.ipv4.mask.s_addr) == 0)
+ bits = pattern->val.ipv6.mask;
+ for (pos = 0; bits > 0; pos += 4, bits -= 32) {
+ v4 = *(uint32_t*)&v6->s6_addr[pos] ^ *(uint32_t*)&pattern->val.ipv6.addr.s6_addr[pos];
+ if (bits < 32)
+ v4 &= (~0U) << (32-bits);
+ if (v4)
+ return ACL_PAT_FAIL;
+ }
return ACL_PAT_PASS;
+ }
return ACL_PAT_FAIL;
}
if (pattern->flags & ACL_PAT_F_TREE_OK)
tree = pattern->val.tree;
- pattern->type = SMP_T_IPV4;
if (str2net(*text, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) {
unsigned int mask = ntohl(pattern->val.ipv4.mask.s_addr);
struct ebmb_node *node;
* the left. This means that this mask + its lower bit added
* once again is null.
*/
+ pattern->type = SMP_T_IPV4;
if (mask + (mask & -mask) == 0 && tree) {
mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
/* FIXME: insert <addr>/<mask> into the tree here */
}
return 1;
}
+ else if (str62net(*text, &pattern->val.ipv6.addr, &pattern->val.ipv6.mask)) {
+ /* no tree support right now */
+ pattern->type = SMP_T_IPV6;
+ return 1;
+ }
else {
if (err)
- memprintf(err, "'%s' is not a valid IPv4 address", *text);
+ memprintf(err, "'%s' is not a valid IPv4 or IPv6 address", *text);
return 0;
}
}