MINOR: dns: new DNS options to allow/prevent IP address duplication

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".
This commit is contained in:
Baptiste Assmann 2018-06-22 15:04:43 +02:00 committed by Willy Tarreau
parent 84221b4e90
commit 8e2d9430c0
4 changed files with 68 additions and 1 deletions

View 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

View 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

View File

@ -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;
}

View 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;