[PATCH] Prefer address family matching to local address in resolver (ticket #1535)
Lukas Lihotzki
lukas at lihotzki.de
Wed Jan 19 15:08:32 UTC 2022
# HG changeset patch
# User Lukas Lihotzki <lukas at lihotzki.de>
# Date 1642576371 -3600
# Wed Jan 19 08:12:51 2022 +0100
# Node ID f922980f06b1162ae933c99c03bef09cfc12582f
# Parent aeab41dfd2606dd36cabbf01f1472726e27e8aea
Prefer address family matching to local address in resolver (ticket #1535).
Without this change, upstream connections fail randomly for dual-stack
host names when specifying a proxy_bind address (ticket #1535).
This changeset adds two flags for avoiding resolving to either IPv4 or IPv6
addresses. stream and http set these flags based on the proxy_bind address.
Avoided addresses are still returned if there are none of the other family, so
the same error message as before is produced when connecting is impossible.
diff -r aeab41dfd260 -r f922980f06b1 src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c Mon Jan 17 17:05:12 2022 +0300
+++ b/src/core/ngx_resolver.c Wed Jan 19 08:12:51 2022 +0100
@@ -113,7 +113,7 @@
static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r,
- ngx_resolver_node_t *rn, ngx_uint_t rotate);
+ ngx_resolver_node_t *rn, ngx_uint_t rotate, sa_family_t af, ngx_uint_t *na);
static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx);
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx,
@@ -580,6 +580,7 @@
ngx_str_t *name)
{
uint32_t hash;
+ sa_family_t sa;
ngx_int_t rc;
ngx_str_t cname;
ngx_uint_t i, naddrs;
@@ -634,7 +635,15 @@
addrs = NULL;
} else {
- addrs = ngx_resolver_export(r, rn, 1);
+ sa = AF_UNSPEC;
+#if (NGX_HAVE_INET6)
+ if (ctx->avoid_ipv4 && rn->naddrs6) {
+ sa = AF_INET6;
+ } else if (ctx->avoid_ipv6 && rn->naddrs) {
+ sa = AF_INET;
+ }
+#endif
+ addrs = ngx_resolver_export(r, rn, 1, sa, &naddrs);
if (addrs == NULL) {
return NGX_ERROR;
}
@@ -2403,7 +2412,7 @@
addrs = NULL;
} else {
- addrs = ngx_resolver_export(r, rn, 0);
+ addrs = ngx_resolver_export(r, rn, 0, AF_UNSPEC, &naddrs);
if (addrs == NULL) {
goto failed;
}
@@ -2425,7 +2434,7 @@
ctx = next;
ctx->state = NGX_OK;
ctx->valid = rn->valid;
- ctx->naddrs = naddrs;
+ ctx->naddrs = (ctx->avoid_ipv6 && rn->naddrs) ? rn->naddrs : naddrs;
if (addrs == NULL) {
ctx->addrs = &ctx->addr;
@@ -2437,6 +2446,12 @@
} else {
ctx->addrs = addrs;
+#if (NGX_HAVE_INET6)
+ if (ctx->avoid_ipv4 && rn->naddrs6) {
+ ctx->addrs = addrs + rn->naddrs;
+ ctx->naddrs = rn->naddrs6;
+ }
+#endif
}
next = ctx->next;
@@ -4183,7 +4198,7 @@
static ngx_resolver_addr_t *
ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
- ngx_uint_t rotate)
+ ngx_uint_t rotate, sa_family_t af, ngx_uint_t *na)
{
ngx_uint_t d, i, j, n;
in_addr_t *addr;
@@ -4197,7 +4212,11 @@
n = rn->naddrs;
#if (NGX_HAVE_INET6)
- n += rn->naddrs6;
+ if (af == AF_INET6) {
+ n = rn->naddrs6;
+ } else if (af != AF_INET) {
+ n += rn->naddrs6;
+ }
#endif
dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t));
@@ -4214,7 +4233,11 @@
i = 0;
d = rotate ? ngx_random() % n : 0;
- if (rn->naddrs) {
+ if (rn->naddrs
+#if (NGX_HAVE_INET6)
+ && af != AF_INET6
+#endif
+ ) {
j = rotate ? ngx_random() % rn->naddrs : 0;
addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
@@ -4237,7 +4260,7 @@
}
#if (NGX_HAVE_INET6)
- if (rn->naddrs6) {
+ if (rn->naddrs6 && af != AF_INET) {
j = rotate ? ngx_random() % rn->naddrs6 : 0;
addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
@@ -4260,6 +4283,7 @@
}
#endif
+ *na = n;
return dst;
}
diff -r aeab41dfd260 -r f922980f06b1 src/core/ngx_resolver.h
--- a/src/core/ngx_resolver.h Mon Jan 17 17:05:12 2022 +0300
+++ b/src/core/ngx_resolver.h Wed Jan 19 08:12:51 2022 +0100
@@ -221,6 +221,8 @@
unsigned quick:1;
unsigned async:1;
unsigned cancelable:1;
+ unsigned avoid_ipv4:1;
+ unsigned avoid_ipv6:1;
ngx_uint_t recursion;
ngx_event_t *event;
};
diff -r aeab41dfd260 -r f922980f06b1 src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c Mon Jan 17 17:05:12 2022 +0300
+++ b/src/http/ngx_http_upstream.c Wed Jan 19 08:12:51 2022 +0100
@@ -770,6 +770,18 @@
ctx->handler = ngx_http_upstream_resolve_handler;
ctx->data = r;
ctx->timeout = clcf->resolver_timeout;
+#if (NGX_HAVE_INET6)
+ if (u->peer.local) {
+ switch (u->peer.local->sockaddr->sa_family) {
+ case AF_INET:
+ ctx->avoid_ipv6 = 1;
+ break;
+ case AF_INET6:
+ ctx->avoid_ipv4 = 1;
+ break;
+ }
+ }
+#endif
u->resolved->ctx = ctx;
diff -r aeab41dfd260 -r f922980f06b1 src/stream/ngx_stream_proxy_module.c
--- a/src/stream/ngx_stream_proxy_module.c Mon Jan 17 17:05:12 2022 +0300
+++ b/src/stream/ngx_stream_proxy_module.c Wed Jan 19 08:12:51 2022 +0100
@@ -547,6 +547,18 @@
ctx->handler = ngx_stream_proxy_resolve_handler;
ctx->data = s;
ctx->timeout = cscf->resolver_timeout;
+#if (NGX_HAVE_INET6)
+ if (u->peer.local) {
+ switch (u->peer.local->sockaddr->sa_family) {
+ case AF_INET:
+ ctx->avoid_ipv6 = 1;
+ break;
+ case AF_INET6:
+ ctx->avoid_ipv4 = 1;
+ break;
+ }
+ }
+#endif
u->resolved->ctx = ctx;
More information about the nginx-devel
mailing list