2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00

BIND: Add 'allow-proxy' and 'allow-proxy-on' options

The main intention of PROXY protocol is to pass endpoints information
to a back-end server (in our case - BIND). That means that it is a
valid way to spoof endpoints information, as the addresses and ports
extracted from PROXYv2 headers, from the point of view of BIND, are
used instead of the real connection addresses.

Of course, an ability to easily spoof endpoints information can be
considered a security issue when used uncontrollably. To resolve that,
we introduce 'allow-proxy' and 'allow-proxy-on' ACL options. These are
the only ACL options in BIND that work with real PROXY connections
addresses, allowing a DNS server operator to specify from what clients
and on which interfaces he or she is willing to accept PROXY
headers. By default, for security reasons we do not allow to accept
them.
This commit is contained in:
Artem Boldariev 2023-10-31 12:39:04 +02:00
parent 6725d36cfd
commit 5ed3a76f9d
9 changed files with 135 additions and 5 deletions

View File

@ -132,6 +132,8 @@ options {\n\
/* view */\n\
allow-new-zones no;\n\
allow-notify {none;};\n\
allow-proxy {none;};\n\
allow-proxy-on {any;};\n\
allow-query-cache { localnets; localhost; };\n\
allow-query-cache-on { any; };\n\
allow-recursion { localnets; localhost; };\n\

View File

@ -5205,6 +5205,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on",
NULL, actx, named_g_mctx, &view->cacheonacl));
CHECK(configure_view_acl(vconfig, config, named_g_config, "allow-proxy",
NULL, actx, named_g_mctx, &view->proxyacl));
CHECK(configure_view_acl(vconfig, config, named_g_config,
"allow-proxy-on", NULL, actx, named_g_mctx,
&view->proxyonacl));
if (strcmp(view->name, "_bind") != 0 &&
view->rdclass != dns_rdataclass_chaos)
{

View File

@ -2833,6 +2833,44 @@ for details on how to specify IP address lists.
the configured :any:`primaries` for the zone. :any:`allow-notify` can be used
to expand the list of permitted hosts, not to reduce it.
.. namedconf:statement:: allow-proxy
:tags: server
:short: Defines an :any:`address_match_list` for the client addresses allowed to send PROXYv2 headers.
The default :any:`address_match_list` is `none`, which means that
no client is allowed to do that by default for security reasons, as
the PROXYv2 protocol provides an easy way to spoof both source and
destination addresses.
This :any:`address_match_list` is primarily meant to have addresses
and subnets of the proxies that are allowed to send PROXYv2 headers
to BIND. In most cases, we do not recommend setting this
:any:`address_match_list` to be very allowing, in particular, to
set it to `any`, especially in the cases when PROXYv2 headers can be
accepted on publically available networking interfaces.
The specified option is the only option that matches against real
peer addresses when PROXYv2 headers are used. Most of the options
that work with peer addresses, use the ones extracted from PROXYv2
headers.
Also, see: :namedconf:ref:`allow-proxy-on`
.. namedconf:statement:: allow-proxy-on
:tags: server
:short: Defines an :any:`address_match_list` for the interface addresses allowed to accept PROXYv2 headers. The option is mostly intended for multi-homed configurations.
The default :any:`address_match_list` is `any`, which means that
accepting PROXYv2 is allowed on any interface.
The option is useful in cases when you need to have precise control
over which interfaces PROXYv2 is allowed, as it is the only one
that matches against real interface addresses when PROXYv2 headers
are used. Most of the options that work with interface addresses
will use the ones extracted from PROXYv2 headers.
You may want to set :namedconf:ref:`allow-proxy` first.
.. namedconf:statement:: allow-query
:tags: query
:short: Specifies which hosts (an IP address list) are allowed to send queries to this resolver.
@ -3128,6 +3166,14 @@ queries may be specified using the :any:`listen-on` and :any:`listen-on-v6` opti
headers. Apart from that, this additional data, while accepted, is
not currently used by BIND for anything else.
By default, no client is allowed to send queries that contain
PROXYv2 protocol headers, even when support for the protocol is
enabled in a :any:`listen-on` statement. If you are interested in
enabling the PROXYv2 protocol support, you may also want to take a
look at :namedconf:ref:`allow-proxy` and
:namedconf:ref:`allow-proxy-on` options to adjust the corresponding
ACLs.
If a TLS configuration is specified, :iscman:`named` will listen for DNS-over-TLS
(DoT) connections, using the key and certificate specified in the
referenced :any:`tls` statement. If the name ``ephemeral`` is used,

View File

@ -62,6 +62,8 @@ managed-keys { <string> ( static-key | initial-key | static-ds | initial-ds ) <i
options {
allow-new-zones <boolean>;
allow-notify { <address_match_element>; ... };
allow-proxy { <address_match_element>; ... }; // experimental
allow-proxy-on { <address_match_element>; ... }; // experimental
allow-query { <address_match_element>; ... };
allow-query-cache { <address_match_element>; ... };
allow-query-cache-on { <address_match_element>; ... };
@ -366,6 +368,8 @@ trusted-keys { <string> <integer> <integer> <integer> <quoted_string>; ... }; //
view <string> [ <class> ] {
allow-new-zones <boolean>;
allow-notify { <address_match_element>; ... };
allow-proxy { <address_match_element>; ... }; // experimental
allow-proxy-on { <address_match_element>; ... }; // experimental
allow-query { <address_match_element>; ... };
allow-query-cache { <address_match_element>; ... };
allow-query-cache-on { <address_match_element>; ... };

View File

@ -139,6 +139,8 @@ struct dns_view {
dns_acl_t *upfwdacl;
dns_acl_t *denyansweracl;
dns_acl_t *nocasecompress;
dns_acl_t *proxyacl;
dns_acl_t *proxyonacl;
bool msgcompression;
dns_nametree_t *answeracl_exclude;
dns_nametree_t *denyanswernames;

View File

@ -339,6 +339,12 @@ destroy(dns_view_t *view) {
if (view->pad_acl != NULL) {
dns_acl_detach(&view->pad_acl);
}
if (view->proxyacl != NULL) {
dns_acl_detach(&view->proxyacl);
}
if (view->proxyonacl != NULL) {
dns_acl_detach(&view->proxyonacl);
}
if (view->answeracl_exclude != NULL) {
dns_nametree_detach(&view->answeracl_exclude);
}

View File

@ -595,11 +595,17 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
isc_result_t result = ISC_R_SUCCESS, tresult;
int i = 0;
static const char *acls[] = {
"allow-query", "allow-query-on", "allow-query-cache",
"allow-query-cache-on", "blackhole", "match-clients",
"match-destinations", "sortlist", NULL
};
static const char *acls[] = { "allow-proxy",
"allow-proxy-on",
"allow-query",
"allow-query-on",
"allow-query-cache",
"allow-query-cache-on",
"blackhole",
"match-clients",
"match-destinations",
"sortlist",
NULL };
while (acls[i] != NULL) {
tresult = checkacl(acls[i++], actx, NULL, voptions, config,

View File

@ -2026,6 +2026,9 @@ static cfg_clausedef_t view_clauses[] = {
{ "additional-from-auth", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "additional-from-cache", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "allow-new-zones", &cfg_type_boolean, 0 },
{ "allow-proxy", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_EXPERIMENTAL },
{ "allow-proxy-on", &cfg_type_bracketed_aml,
CFG_CLAUSEFLAG_EXPERIMENTAL },
{ "allow-query-cache", &cfg_type_bracketed_aml, 0 },
{ "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
{ "allow-recursion", &cfg_type_bracketed_aml, 0 },

View File

@ -2001,6 +2001,60 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
return;
}
if (isc_nm_is_proxy_handle(client->handle)) {
char fmtbuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
isc_netaddr_t real_local_addr, real_peer_addr;
isc_sockaddr_t real_local, real_peer;
int log_level = ISC_LOG_DEBUG(10);
real_peer = isc_nmhandle_real_peeraddr(client->handle);
isc_netaddr_fromsockaddr(&real_peer_addr, &real_peer);
real_local = isc_nmhandle_real_localaddr(client->handle);
isc_netaddr_fromsockaddr(&real_local_addr, &real_local);
/* do not allow by default */
if (ns_client_checkaclsilent(client, &real_peer_addr,
client->view->proxyacl,
false) != ISC_R_SUCCESS)
{
if (isc_log_wouldlog(ns_lctx, log_level)) {
isc_sockaddr_format(&real_peer, fmtbuf,
sizeof(fmtbuf));
ns_client_log(
client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, log_level,
"dropped request: PROXY is not allowed "
"for that client (real client address: "
"%s). Rejected by the 'allow-proxy' "
"ACL",
fmtbuf);
}
isc_nm_bad_request(handle);
return;
}
/* allow by default */
if (ns_client_checkaclsilent(client, &real_local_addr,
client->view->proxyonacl,
true) != ISC_R_SUCCESS)
{
if (isc_log_wouldlog(ns_lctx, log_level)) {
isc_sockaddr_format(&real_local, fmtbuf,
sizeof(fmtbuf));
ns_client_log(
client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, log_level,
"dropped request: PROXY is not allowed "
"on the interface (real interface "
"address: %s). Rejected by the "
"'allow-proxy-on' ACL",
fmtbuf);
}
isc_nm_bad_request(handle);
return;
}
}
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
ISC_LOG_DEBUG(5), "using view '%s'", client->view->name);