You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.8 KiB

  1. commit c1bfcd002f54d1d84a99282d13f875c2649f3d70
  2. Author: Baptiste Assmann <bedis9@gmail.com>
  3. Date: Fri Jun 22 15:04:43 2018 +0200
  4. MINOR: dns: new DNS options to allow/prevent IP address duplication
  5. By default, HAProxy's DNS resolution at runtime ensure that there is no
  6. IP address duplication in a backend (for servers being resolved by the
  7. same hostname).
  8. There are a few cases where people want, on purpose, to disable this
  9. feature.
  10. This patch introduces a couple of new server side options for this purpose:
  11. "resolve-opts allow-dup-ip" or "resolve-opts prevent-dup-ip".
  12. (cherry picked from commit 8e2d9430c0562ed74276d7f58e92706c384c0a36)
  13. [wt: this is backported to 1.8 upon request from Baptiste because it offers
  14. the option to revert to 1.7 behaviour, which some people depend on. The
  15. address deduplication used on 1.8 apparently is not suited to everyone]
  16. Signed-off-by: Willy Tarreau <w@1wt.eu>
  17. diff --git a/doc/configuration.txt b/doc/configuration.txt
  18. index 011533a0..1973bbf2 100644
  19. --- a/doc/configuration.txt
  20. +++ b/doc/configuration.txt
  21. @@ -11623,6 +11623,40 @@ rise <count>
  22. after <count> consecutive successful health checks. This value defaults to 2
  23. if unspecified. See also the "check", "inter" and "fall" parameters.
  24. +resolve-opts <option>,<option>,...
  25. + Comma separated list of options to apply to DNS resolution linked to this
  26. + server.
  27. +
  28. + Available options:
  29. +
  30. + * allow-dup-ip
  31. + By default, HAProxy prevents IP address duplication in a backend when DNS
  32. + resolution at runtime is in operation.
  33. + That said, for some cases, it makes sense that two servers (in the same
  34. + backend, being resolved by the same FQDN) have the same IP address.
  35. + For such case, simply enable this option.
  36. + This is the opposite of prevent-dup-ip.
  37. +
  38. + * prevent-dup-ip
  39. + Ensure HAProxy's default behavior is enforced on a server: prevent re-using
  40. + an IP address already set to a server in the same backend and sharing the
  41. + same fqdn.
  42. + This is the opposite of allow-dup-ip.
  43. +
  44. + Example:
  45. + backend b_myapp
  46. + default-server init-addr none resolvers dns
  47. + server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
  48. + server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
  49. +
  50. + With the option allow-dup-ip set:
  51. + * if the nameserver returns a single IP address, then both servers will use
  52. + it
  53. + * If the nameserver returns 2 IP addresses, then each server will pick up a
  54. + different address
  55. +
  56. + Default value: not set
  57. +
  58. resolve-prefer <family>
  59. When DNS resolution is enabled for a server and multiple IP addresses from
  60. different families are returned, HAProxy will prefer using an IP address
  61. diff --git a/include/types/dns.h b/include/types/dns.h
  62. index 9b1d08df..488d3996 100644
  63. --- a/include/types/dns.h
  64. +++ b/include/types/dns.h
  65. @@ -245,6 +245,8 @@ struct dns_options {
  66. } mask;
  67. } pref_net[SRV_MAX_PREF_NET];
  68. int pref_net_nb; /* The number of registered prefered networks. */
  69. + int accept_duplicate_ip; /* flag to indicate whether the associated object can use an IP address
  70. + already set to an other object of the same group */
  71. };
  72. /* Resolution structure associated to single server and used to manage name
  73. diff --git a/src/dns.c b/src/dns.c
  74. index d8388ef1..b31000a2 100644
  75. --- a/src/dns.c
  76. +++ b/src/dns.c
  77. @@ -965,8 +965,10 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
  78. int currentip_sel;
  79. int j;
  80. int score, max_score;
  81. + int allowed_duplicated_ip;
  82. family_priority = dns_opts->family_prio;
  83. + allowed_duplicated_ip = dns_opts->accept_duplicate_ip;
  84. *newip = newip4 = newip6 = NULL;
  85. currentip_found = 0;
  86. *newip_sin_family = AF_UNSPEC;
  87. @@ -1030,7 +1032,9 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
  88. * member of a group. If not, the score should be incremented
  89. * by 2. */
  90. if (owner && snr_check_ip_callback(owner, ip, &ip_type)) {
  91. - continue;
  92. + if (!allowed_duplicated_ip) {
  93. + continue;
  94. + }
  95. } else {
  96. score += 2;
  97. }
  98. diff --git a/src/server.c b/src/server.c
  99. index fbed6cd4..36a05e27 100644
  100. --- a/src/server.c
  101. +++ b/src/server.c
  102. @@ -1506,6 +1506,7 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp
  103. if (src->resolvers_id != NULL)
  104. srv->resolvers_id = strdup(src->resolvers_id);
  105. srv->dns_opts.family_prio = src->dns_opts.family_prio;
  106. + srv->dns_opts.accept_duplicate_ip = src->dns_opts.accept_duplicate_ip;
  107. if (srv->dns_opts.family_prio == AF_UNSPEC)
  108. srv->dns_opts.family_prio = AF_INET6;
  109. memcpy(srv->dns_opts.pref_net,
  110. @@ -2044,6 +2045,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
  111. newsrv = &curproxy->defsrv;
  112. cur_arg = 1;
  113. newsrv->dns_opts.family_prio = AF_INET6;
  114. + newsrv->dns_opts.accept_duplicate_ip = 0;
  115. }
  116. while (*args[cur_arg]) {
  117. @@ -2139,6 +2141,31 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
  118. newsrv->resolvers_id = strdup(args[cur_arg + 1]);
  119. cur_arg += 2;
  120. }
  121. + else if (!strcmp(args[cur_arg], "resolve-opts")) {
  122. + char *p, *end;
  123. +
  124. + for (p = args[cur_arg + 1]; *p; p = end) {
  125. + /* cut on next comma */
  126. + for (end = p; *end && *end != ','; end++);
  127. + if (*end)
  128. + *(end++) = 0;
  129. +
  130. + if (!strcmp(p, "allow-dup-ip")) {
  131. + newsrv->dns_opts.accept_duplicate_ip = 1;
  132. + }
  133. + else if (!strcmp(p, "prevent-dup-ip")) {
  134. + newsrv->dns_opts.accept_duplicate_ip = 0;
  135. + }
  136. + else {
  137. + ha_alert("parsing [%s:%d]: '%s' : unknown resolve-opts option '%s', supported methods are 'allow-dup-ip' and 'prevent-dup-ip'.\n",
  138. + file, linenum, args[cur_arg], p);
  139. + err_code |= ERR_ALERT | ERR_FATAL;
  140. + goto out;
  141. + }
  142. + }
  143. +
  144. + cur_arg += 2;
  145. + }
  146. else if (!strcmp(args[cur_arg], "resolve-prefer")) {
  147. if (!strcmp(args[cur_arg + 1], "ipv4"))
  148. newsrv->dns_opts.family_prio = AF_INET;