]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: dns: new DNS options to allow/prevent IP address duplication
authorBaptiste Assmann <bedis9@gmail.com>
Fri, 22 Jun 2018 13:04:43 +0000 (15:04 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 12 Jul 2018 15:56:44 +0000 (17:56 +0200)
By default, HAProxy's DNS resolution at runtime ensure that there is no
IP address duplication in a backend (for servers being resolved by the
same hostname).
There are a few cases where people want, on purpose, to disable this
feature.

This patch introduces a couple of new server side options for this purpose:
"resolve-opts allow-dup-ip" or "resolve-opts prevent-dup-ip".

doc/configuration.txt
include/types/dns.h
src/dns.c
src/server.c

index e901d7eeafd8ff00e0da25b30754cab5c2ff8007..b443de661b38b1fe93518f4bd452ff0d9033ee72 100644 (file)
@@ -11682,6 +11682,40 @@ rise <count>
   after <count> consecutive successful health checks. This value defaults to 2
   if unspecified. See also the "check", "inter" and "fall" parameters.
 
+resolve-opts <option>,<option>,...
+  Comma separated list of options to apply to DNS resolution linked to this
+  server.
+
+  Available options:
+
+  * allow-dup-ip
+    By default, HAProxy prevents IP address duplication in a backend when DNS
+    resolution at runtime is in operation.
+    That said, for some cases, it makes sense that two servers (in the same
+    backend, being resolved by the same FQDN) have the same IP address.
+    For such case, simply enable this option.
+    This is the opposite of prevent-dup-ip.
+
+  * prevent-dup-ip
+    Ensure HAProxy's default behavior is enforced on a server: prevent re-using
+    an IP address already set to a server in the same backend and sharing the
+    same fqdn.
+    This is the opposite of allow-dup-ip.
+
+  Example:
+    backend b_myapp
+      default-server init-addr none resolvers dns
+      server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
+      server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
+
+  With the option allow-dup-ip set:
+  * if the nameserver returns a single IP address, then both servers will use
+    it
+  * If the nameserver returns 2 IP addresses, then each server will pick up a
+    different address
+
+  Default value: not set
+
 resolve-prefer <family>
   When DNS resolution is enabled for a server and multiple IP addresses from
   different families are returned, HAProxy will prefer using an IP address
index 9b1d08df7f2e565c249ba5a0a59606da801159e6..488d3996cb5c45932f76cd69c9150d8c16b03c99 100644 (file)
@@ -245,6 +245,8 @@ struct dns_options {
                } mask;
        } pref_net[SRV_MAX_PREF_NET];
        int pref_net_nb; /* The number of registered prefered networks. */
+       int accept_duplicate_ip; /* flag to indicate whether the associated object can use an IP address
+                                   already set to an other object of the same group */
 };
 
 /* Resolution structure associated to single server and used to manage name
index 018c86a8847b1a9fa69167105f6bf5246ed2a3aa..77bf5c00410027da102009961f60d427f9665633 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -962,8 +962,10 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
        int currentip_sel;
        int j;
        int score, max_score;
+       int allowed_duplicated_ip;
 
        family_priority   = dns_opts->family_prio;
+       allowed_duplicated_ip = dns_opts->accept_duplicate_ip;
        *newip = newip4   = newip6 = NULL;
        currentip_found   = 0;
        *newip_sin_family = AF_UNSPEC;
@@ -1027,7 +1029,9 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
                 * member of a group.  If not, the score should be incremented
                 * by 2. */
                if (owner && snr_check_ip_callback(owner, ip, &ip_type)) {
-                       continue;
+                       if (!allowed_duplicated_ip) {
+                               continue;
+                       }
                } else {
                        score += 2;
                }
index 277d1405e78393d3004d8a8ebfe11f0f81e9f7b0..17d7663e818ef75956dc38bc9c81bd18d4e2779c 100644 (file)
@@ -1544,6 +1544,7 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp
        if (src->resolvers_id != NULL)
                srv->resolvers_id = strdup(src->resolvers_id);
        srv->dns_opts.family_prio = src->dns_opts.family_prio;
+       srv->dns_opts.accept_duplicate_ip = src->dns_opts.accept_duplicate_ip;
        if (srv->dns_opts.family_prio == AF_UNSPEC)
                srv->dns_opts.family_prio = AF_INET6;
        memcpy(srv->dns_opts.pref_net,
@@ -2082,6 +2083,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
                        newsrv = &curproxy->defsrv;
                        cur_arg = 1;
                        newsrv->dns_opts.family_prio = AF_INET6;
+                       newsrv->dns_opts.accept_duplicate_ip = 0;
                }
 
                while (*args[cur_arg]) {
@@ -2177,6 +2179,31 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
                                newsrv->resolvers_id = strdup(args[cur_arg + 1]);
                                cur_arg += 2;
                        }
+                       else if (!strcmp(args[cur_arg], "resolve-opts")) {
+                               char *p, *end;
+
+                               for (p = args[cur_arg + 1]; *p; p = end) {
+                                       /* cut on next comma */
+                                       for (end = p; *end && *end != ','; end++);
+                                       if (*end)
+                                               *(end++) = 0;
+
+                                       if (!strcmp(p, "allow-dup-ip")) {
+                                               newsrv->dns_opts.accept_duplicate_ip = 1;
+                                       }
+                                       else if (!strcmp(p, "prevent-dup-ip")) {
+                                               newsrv->dns_opts.accept_duplicate_ip = 0;
+                                       }
+                                       else {
+                                               ha_alert("parsing [%s:%d]: '%s' : unknown resolve-opts option '%s', supported methods are 'allow-dup-ip' and 'prevent-dup-ip'.\n",
+                                                               file, linenum, args[cur_arg], p);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+                               }
+
+                               cur_arg += 2;
+                       }
                        else if (!strcmp(args[cur_arg], "resolve-prefer")) {
                                if (!strcmp(args[cur_arg + 1], "ipv4"))
                                        newsrv->dns_opts.family_prio = AF_INET;