Commit 386d3a99 authored by Tatuya JINMEI 神明達哉's avatar Tatuya JINMEI 神明達哉
Browse files

2375. [security] Fully randomize UDP query ports to improve

			forgery resilience. [RT #17949, #18098]
parent 40976ef8
......@@ -24,7 +24,8 @@
2376. [bug] Change #2144 was not complete.
2375. [placeholder]
2375. [security] Fully randomize UDP query ports to improve
forgery resilience. [RT #17949, #18098]
2374. [bug] "blackhole" ACLs could cause named to segfault due
to some uninitialized memory. [RT #18095]
......
......@@ -15,7 +15,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- $Id: bind9.xsl,v 1.17 2008/04/09 22:48:17 jinmei Exp $ -->
<!-- $Id: bind9.xsl,v 1.18 2008/06/23 19:41:18 jinmei Exp $ -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
......@@ -86,7 +86,6 @@ td, th {
</head>
<body>
<div class="header">Bind 9 Configuration and Statistics</div>
<br/>
<table>
......
......@@ -91,7 +91,6 @@ static char xslmsg[] =
" </head>\n"
" <body>\n"
" <div class=\"header\">Bind 9 Configuration and Statistics</div>\n"
"\n"
" <br/>\n"
"\n"
" <table>\n"
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.257 2008/04/03 06:09:04 tbox Exp $ */
/* $Id: client.c,v 1.258 2008/06/23 19:41:18 jinmei Exp $ */
#include <config.h>
......@@ -1524,14 +1524,6 @@ client_request(isc_task_t *task, isc_event_t *event) {
dns_generalstats_increment(ns_g_server->nsstats,
dns_nsstatscounter_tcp);
/*
* Hash the incoming request here as it is after
* dns_dispatch_importrecv().
*/
dns_dispatch_hash(&client->now, sizeof(client->now));
dns_dispatch_hash(isc_buffer_base(buffer),
isc_buffer_usedlength(buffer));
/*
* It's a request. Parse it.
*/
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.508 2008/05/21 23:47:00 tbox Exp $ */
/* $Id: server.c,v 1.509 2008/06/23 19:41:18 jinmei Exp $ */
/*! \file */
......@@ -33,6 +33,7 @@
#include <isc/httpd.h>
#include <isc/lex.h>
#include <isc/parseint.h>
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/resource.h>
#include <isc/stdio.h>
......@@ -538,13 +539,15 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
*/
static isc_result_t
get_view_querysource_dispatch(const cfg_obj_t **maps,
int af, dns_dispatch_t **dispatchp)
int af, dns_dispatch_t **dispatchp,
isc_boolean_t is_firstview)
{
isc_result_t result;
dns_dispatch_t *disp;
isc_sockaddr_t sa;
unsigned int attrs, attrmask;
const cfg_obj_t *obj = NULL;
unsigned int maxdispatchbuffers;
/*
* Make compiler happy.
......@@ -596,6 +599,20 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
attrs |= DNS_DISPATCHATTR_IPV6;
break;
}
if (isc_sockaddr_getport(&sa) == 0) {
attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
maxdispatchbuffers = 4096;
} else {
INSIST(obj != NULL);
if (is_firstview) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
"using specific query-source port "
"suppresses port randomization and can be "
"insecure.");
}
maxdispatchbuffers = 1000;
}
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP;
attrmask |= DNS_DISPATCHATTR_TCP;
......@@ -605,7 +622,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
disp = NULL;
result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
ns_g_taskmgr, &sa, 4096,
1000, 32768, 16411, 16433,
maxdispatchbuffers, 32768, 16411, 16433,
attrs, attrmask, &disp);
if (result != ISC_R_SUCCESS) {
isc_sockaddr_t any;
......@@ -1015,7 +1032,6 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
isc_boolean_t rfc1918;
isc_boolean_t empty_zones_enable;
const cfg_obj_t *disablelist = NULL;
isc_uint32_t nqports, qports_updateinterval;
dns_stats_t *resstats = NULL;
dns_stats_t *resquerystats = NULL;
......@@ -1272,8 +1288,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*
* XXXRTH Hardwired number of tasks.
*/
CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
ISC_TF(ISC_LIST_PREV(view, link)
== NULL)));
CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
ISC_TF(ISC_LIST_PREV(view, link)
== NULL)));
if (dispatch4 == NULL && dispatch6 == NULL) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"unable to obtain neither an IPv4 nor"
......@@ -1281,93 +1301,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
result = ISC_R_UNEXPECTED;
goto cleanup;
}
obj = NULL;
(void)ns_config_get(maps, "use-queryport-pool", &obj);
if (obj == NULL || cfg_obj_asboolean(obj)) {
isc_sockaddr_t sa;
isc_boolean_t logit4 = ISC_FALSE, logit6 = ISC_FALSE;
resopts |= (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6);
/* Check consistency with query-source(-v6) */
if (dispatch4 == NULL)
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL4;
else {
result = dns_dispatch_getlocaladdress(dispatch4, &sa);
INSIST(result == ISC_R_SUCCESS);
if (isc_sockaddr_getport(&sa) != 0) {
logit4 = ISC_TRUE;
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL4;
}
}
if (dispatch6 == NULL)
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL6;
else {
result = dns_dispatch_getlocaladdress(dispatch6, &sa);
INSIST(result == ISC_R_SUCCESS);
if (isc_sockaddr_getport(&sa) != 0) {
logit6 = ISC_TRUE;
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL6;
}
}
if (logit4 && obj != NULL)
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"specific query-source port "
"cannot coexist with queryport-pool. "
"(Pool disabled)");
if (logit6 && obj != NULL)
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"specific query-source-v6 port "
"cannot coexist with queryport-pool. "
"(Pool disabled)");
}
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
ns_g_socketmgr, ns_g_timermgr,
resopts, ns_g_dispatchmgr,
dispatch4, dispatch6));
/*
* Query-port pool parameters.
*/
obj = NULL;
nqports = 8;
result = ns_config_get(maps, "queryport-pool-ports", &obj);
if (result == ISC_R_SUCCESS) {
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) == 0) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"queryport-pool-ports is effective only "
"with 'use-queryport-pool yes' (ignored)");
} else
nqports = cfg_obj_asuint32(obj);
}
obj = NULL;
qports_updateinterval = 15;
result = ns_config_get(maps, "queryport-pool-updateinterval", &obj);
if (result == ISC_R_SUCCESS) {
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) == 0) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"queryport-pool-updateinterval is "
"effective only with 'use-queryport-pool "
"yes' (ignored)");
} else
qports_updateinterval = cfg_obj_asuint32(obj);
}
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) != 0) {
CHECK(dns_resolver_createdispatchpool(view->resolver,
nqports,
qports_updateinterval
* 60));
}
if (resstats == NULL) {
CHECK(dns_generalstats_create(mctx, &resstats,
dns_resstatscounter_max));
......@@ -2674,8 +2612,6 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
dns_dispatch_t *dispatch6;
isc_boolean_t use_portpool = ISC_FALSE;
unsigned int resopts;
dispatch6 = dns_resolver_dispatchv6(view->resolver);
if (dispatch6 == NULL)
......@@ -2683,19 +2619,16 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
result = dns_dispatch_getlocaladdress(dispatch6, &addr);
if (result != ISC_R_SUCCESS)
goto fail;
resopts = dns_resolver_getoptions(view->resolver);
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) != 0) {
/*
* If the resolver uses a dynamic pool of query ports
* with a specific source address, some of the current
* and future ports may override an existing wildcard
* IPv6 port. So we need to allow wildcard match
* in this case.
*/
use_portpool = ISC_TRUE;
}
result = add_listenelt(mctx, list, &addr, use_portpool);
/*
* We always add non-wildcard address regardless of whether
* the port is 'any' (the fourth arg is TRUE): if the port is
* specific, we need to add it since it may conflict with a
* listening interface; if it's zero, we'll dynamically open
* query ports, and some of them may override an existing
* wildcard IPv6 port.
*/
result = add_listenelt(mctx, list, &addr, ISC_TRUE);
if (result != ISC_R_SUCCESS)
goto fail;
}
......@@ -2884,24 +2817,41 @@ set_limits(const cfg_obj_t **maps) {
SETLIMIT("files", openfiles, "open files");
}
static isc_result_t
portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
const cfg_obj_t *ports)
static void
portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
isc_boolean_t positive)
{
const cfg_listelt_t *element;
isc_result_t result = ISC_R_SUCCESS;
for (element = cfg_list_first(ports);
element != NULL;
element = cfg_list_next(element)) {
const cfg_obj_t *obj = cfg_listelt_value(element);
in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
result = dns_portlist_add(portlist, family, port);
if (result != ISC_R_SUCCESS)
break;
if (cfg_obj_isuint32(obj)) {
in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
if (positive)
isc_portset_add(portset, port);
else
isc_portset_remove(portset, port);
} else {
const cfg_obj_t *obj_loport, *obj_hiport;
in_port_t loport, hiport;
obj_loport = cfg_tuple_get(obj, "loport");
loport = (in_port_t)cfg_obj_asuint32(obj_loport);
obj_hiport = cfg_tuple_get(obj, "hiport");
hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
if (positive)
isc_portset_addrange(portset, loport, hiport);
else {
isc_portset_removerange(portset, loport,
hiport);
}
}
}
return (result);
}
static isc_result_t
......@@ -2940,7 +2890,7 @@ load_configuration(const char *filename, ns_server_t *server,
const cfg_obj_t *options;
const cfg_obj_t *views;
const cfg_obj_t *obj;
const cfg_obj_t *v4ports, *v6ports;
const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
const cfg_obj_t *maps[3];
const cfg_obj_t *builtin_views;
const cfg_listelt_t *element;
......@@ -2952,7 +2902,9 @@ load_configuration(const char *filename, ns_server_t *server,
isc_uint32_t interface_interval;
isc_uint32_t heartbeat_interval;
isc_uint32_t udpsize;
in_port_t listen_port;
in_port_t listen_port, udpport_low, udpport_high;
isc_portset_t *v4portset = NULL;
isc_portset_t *v6portset = NULL;
int i;
cfg_aclconfctx_init(&aclconfctx);
......@@ -3069,24 +3021,64 @@ load_configuration(const char *filename, ns_server_t *server,
CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
"configuring statistics server(s)");
v4ports = NULL;
v6ports = NULL;
(void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
(void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
if (v4ports != NULL || v6ports != NULL) {
dns_portlist_t *portlist = NULL;
result = dns_portlist_create(ns_g_mctx, &portlist);
if (result == ISC_R_SUCCESS && v4ports != NULL)
result = portlist_fromconf(portlist, AF_INET, v4ports);
if (result == ISC_R_SUCCESS && v6ports != NULL)
portlist_fromconf(portlist, AF_INET6, v6ports);
if (result == ISC_R_SUCCESS)
dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
if (portlist != NULL)
dns_portlist_detach(&portlist);
CHECK(result);
} else
dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
/*
* Configure sets of UDP query source ports.
*/
CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
"creating UDP port set");
CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
"creating UDP port set");
usev4ports = NULL;
usev6ports = NULL;
avoidv4ports = NULL;
avoidv6ports = NULL;
(void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
if (usev4ports != NULL)
portset_fromconf(v4portset, usev4ports, ISC_TRUE);
else {
CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
&udpport_high),
"get the default UDP/IPv4 port range");
if (udpport_low == udpport_high)
isc_portset_add(v4portset, udpport_low);
else {
isc_portset_addrange(v4portset, udpport_low,
udpport_high);
}
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"using default UDP/IPv4 port range: [%d, %d]",
udpport_low, udpport_high);
}
(void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
if (avoidv4ports != NULL)
portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
(void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
if (usev6ports != NULL)
portset_fromconf(v6portset, usev6ports, ISC_TRUE);
else {
CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
&udpport_high),
"get the default UDP/IPv6 port range");
if (udpport_low == udpport_high)
isc_portset_add(v6portset, udpport_low);
else {
isc_portset_addrange(v6portset, udpport_low,
udpport_high);
}
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"using default UDP/IPv6 port range: [%d, %d]",
udpport_low, udpport_high);
}
(void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
if (avoidv6ports != NULL)
portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
/*
* Set the EDNS UDP size when we don't match a view.
......@@ -3569,6 +3561,12 @@ load_configuration(const char *filename, ns_server_t *server,
result = ISC_R_SUCCESS;
cleanup:
if (v4portset != NULL)
isc_portset_destroy(ns_g_mctx, &v4portset);
if (v6portset != NULL)
isc_portset_destroy(ns_g_mctx, &v6portset);
cfg_aclconfctx_destroy(&aclconfctx);
if (parser != NULL) {
......
......@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl
AC_REVISION($Revision: 1.443 $)
AC_REVISION($Revision: 1.444 $)
AC_INIT(lib/dns/name.c)
AC_PREREQ(2.59)
......@@ -317,6 +317,43 @@ lifconf.lifc_len = 0;
ISC_PLATFORM_HAVELIFCONF="#undef ISC_PLATFORM_HAVELIFCONF"])
AC_SUBST(ISC_PLATFORM_HAVELIFCONF)
#
# check if we have kqueue
#
AC_CHECK_FUNC(kqueue, ac_cv_have_kqueue=yes, ac_cv_have_kqueue=no)
case $ac_cv_have_kqueue in
yes)
ISC_PLATFORM_HAVEKQUEUE="#define ISC_PLATFORM_HAVEKQUEUE 1"
;;
*)
ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
;;
esac
AC_SUBST(ISC_PLATFORM_HAVEKQUEUE)
#
# check if we have epoll
#
AC_CHECK_FUNC(epoll_create, ac_cv_have_epoll=yes, ac_cv_have_epoll=no)
case $ac_cv_have_epoll in
yes)
ISC_PLATFORM_HAVEEPOLL="#define ISC_PLATFORM_HAVEEPOLL 1"
;;
*)
ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"
;;
esac
AC_SUBST(ISC_PLATFORM_HAVEEPOLL)
#
# check if we support /dev/poll
#
AC_CHECK_HEADERS(sys/devpoll.h,
ISC_PLATFORM_HAVEDEVPOLL="#define ISC_PLATFORM_HAVEDEVPOLL 1"
,
ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
)
AC_SUBST(ISC_PLATFORM_HAVEDEVPOLL)
#
# check if we need to #include sys/select.h explicitly
......
......@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- File: $Id: Bv9ARM-book.xml,v 1.359 2008/06/17 20:59:25 jreed Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.360 2008/06/23 19:41:18 jinmei Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
......@@ -2955,6 +2955,33 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
</para>
</entry>
</row>
<row rowsep="0">
<entry colname="1">
<para>
<varname>port_list</varname>
</para>
</entry>
<entry colname="2">
<para>
A list of an <varname>ip_port</varname> or a port
range.
A port range is specified in the form of
<userinput>range</userinput> followed by
two <varname>ip_port</varname>s,
<varname>port_low</varname> and
<varname>port_high</varname>, which represents
port numbers from <varname>port_low</varname> through
<varname>port_high</varname>, inclusive.
<varname>port_low</varname> must not be larger than
<varname>port_high</varname>.
For example,
<userinput>range 1024 65535</userinput> represents
ports from 1024 through 65535.
In either case an asterisk (`*') character is not
allowed as a valid <varname>ip_port</varname>.
</para>
</entry>
</row>
<row rowsep="0">
<entry colname="1">
<para>
......@@ -4513,7 +4540,9 @@ category notify { null; };
<optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
<optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
<optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
<optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
<optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
<optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
<optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
<optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
<optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
......@@ -6269,32 +6298,104 @@ listen-on-v6 port 1234 { !2001:db8::/32; any; };
If <command>address</command> is <command>*</command> (asterisk) or is omitted,
a wildcard IP address (<command>INADDR_ANY</command>)
will be used.
</para>
<para>
If <command>port</command> is <command>*</command> or is omitted,
a pool of random unprivileged ports will be used. See the
<command>use-queryport-pool</command>,
<command>queryport-pool-ports</command> and
<command>queryport-pool-updateinterval</command> options below for how the pool
is configured.
The <command>avoid-v4-udp-ports</command>
and <command>avoid-v6-udp-ports</command> options can be used
to prevent named
from selecting certain ports.
The defaults are:
a random port number from a pre-configured
range is picked up and will be used for each query.
The port range(s) is that specified in
the <command>use-v4-udp-ports</command> (for IPv4)
and <command>use-v6-udp-ports</command> (for IPv6)
options, excluding the ranges specified in
the <command>avoid-v4-udp-ports</command>
and <command>avoid-v6-udp-ports</command> options, respectively.
</para>
<para>
The defaults of the <command>query-source</command> and
<command>query-source-v6</command> options
are:
</para>
<programlisting>query-source address * port *;
query-source-v6 address * port *;
</programlisting>
<para>
If <command>use-v4-udp-ports</command> or
<command>use-v6-udp-ports</command> is unspecified,
<command>named</command> will check if the operating
system provides a programming interface to retrieve the
system's default range for ephemeral ports.
If such an interface is available,
<command>named</command> will use the corresponding system
default range; otherwise, it will use its own defaults:
</para>
<programlisting>use-v4-udp-ports { range 1024 65535; };
use-v6-udp-ports { range 1024 65535; };
</programlisting>
<para>
Note: make sure the ranges be sufficiently large for
security. A desirable size depends on various parameters,
but we generally recommend it contain at least 16384 ports
(14 bits of entropy).
Note also that the system's default range when used may be
too small for this purpose, and that the range may even be
changed while <command>named</command> is running; the new
range will automatically be applied when <command>named</command>
is reloaded.
It is encouraged to
configure <command>use-v4-udp-ports</command> and
<command>use-v6-udp-ports</command> explicitly so that the
ranges are sufficiently large and are reasonably
independent from the ranges used by other applications.
</para>
<para>
Note: the operational configuration
where <command>named</command> runs may prohibit the use
of some ports. For example, UNIX systems will not allow
<command>named</command> running without a root privilege
to use ports less than 1024.
If such ports are included in the specified (or detected)
set of query ports, the corresponding query attempts will
fail, resulting in resolution failures or delay.
It is therefore important to configure the set of ports
that can be safely used in the expected operational environment.