From e21d199dca95aff5d50f133d6b064309e209af00 Mon Sep 17 00:00:00 2001 From: Brian Wellington Date: Fri, 3 Nov 2000 02:45:55 +0000 Subject: [PATCH] 539. [func] Support the blackhole option. --- CHANGES | 2 ++ bin/named/client.c | 34 +++++++++++++++++-- bin/named/include/named/server.h | 3 +- bin/named/server.c | 13 +++++++- doc/misc/options | 4 +-- lib/dns/config/confctx.c | 9 +---- lib/dns/dispatch.c | 57 +++++++++++++++++++++++++++++++- lib/dns/include/dns/dispatch.h | 25 +++++++++++++- lib/dns/include/dns/result.h | 5 +-- lib/dns/request.c | 52 ++++++++++++++++++++++++++++- lib/dns/resolver.c | 31 +++++++++++++++-- lib/dns/result.c | 5 +-- 12 files changed, 217 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 14a6eb9b5a..7cff6d4eae 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + 539. [func] Support the blackhole option. + 538. [bug] fix buffer overruns by 1 in lwres_getnameinfo(). 537. [func] Use transfer-source{-v6} when notify messages. diff --git a/bin/named/client.c b/bin/named/client.c index c7de659cda..4b2d9c646b 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.123 2000/10/25 04:26:19 marka Exp $ */ +/* $Id: client.c,v 1.124 2000/11/03 02:45:37 bwelling Exp $ */ #include @@ -708,6 +708,8 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { isc_region_t r; isc_sockaddr_t *address; isc_socket_t *socket; + isc_netaddr_t netaddr; + int match; if (TCP_CLIENT(client)) { socket = client->tcpsocket; @@ -715,6 +717,14 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { } else { socket = dns_dispatch_getsocket(client->dispatch); address = &client->dispevent->addr; + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + if (ns_g_server->blackholeacl != NULL && + dns_acl_match(&netaddr, NULL, + ns_g_server->blackholeacl, + NULL, &match, NULL) == ISC_R_SUCCESS && + match > 0) + return (DNS_R_BLACKHOLED); } if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0) @@ -725,6 +735,7 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { isc_buffer_usedregion(buffer, &r); CTRACE("sendto"); + result = isc_socket_sendto(socket, &r, client->task, client_senddone, client, address, pktinfo); if (result == ISC_R_SUCCESS) { @@ -1654,6 +1665,9 @@ client_newconn(isc_task_t *task, isc_event_t *event) { goto freeevent; if (nevent->result == ISC_R_SUCCESS) { + int match; + isc_netaddr_t netaddr; + INSIST(client->tcpmsg_valid == ISC_FALSE); dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg); @@ -1662,7 +1676,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { /* * Let a new client take our place immediately, before * we wait for a request packet. If we don't, - * telnetting to port 35 (once per CPU) will + * telnetting to port 53 (once per CPU) will * deny service to legititmate TCP clients. */ result = isc_quota_attach(&ns_g_server->tcpquota, @@ -1675,6 +1689,22 @@ client_newconn(isc_task_t *task, isc_event_t *event) { "no more TCP clients: %s", isc_result_totext(result)); } + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + + if (ns_g_server->blackholeacl != NULL && + dns_acl_match(&netaddr, NULL, + ns_g_server->blackholeacl, + &ns_g_server->aclenv, + &match, NULL) == ISC_R_SUCCESS && + match > 0) + { + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), + "blackholed connection attempt"); + goto freeevent; + } + client_read(client); } diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 12f8f70a83..aef32ac4aa 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.40 2000/10/12 21:51:50 mws Exp $ */ +/* $Id: server.h,v 1.41 2000/11/03 02:45:41 bwelling Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -48,6 +48,7 @@ struct ns_server { isc_quota_t xfroutquota; isc_quota_t tcpquota; isc_quota_t recursionquota; + dns_acl_t *blackholeacl; /* Not really configurable, but covered by conflock. */ dns_aclenv_t aclenv; diff --git a/bin/named/server.c b/bin/named/server.c index e14477db79..0b01b8bf22 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.234 2000/11/01 20:59:20 bwelling Exp $ */ +/* $Id: server.c,v 1.235 2000/11/03 02:45:39 bwelling Exp $ */ #include @@ -1335,6 +1335,13 @@ load_configuration(const char *filename, ns_server_t *server, configure_server_quota(cctx, dns_c_ctx_getrecursiveclients, &server->recursionquota, 1000); + CHECK(configure_view_acl(NULL, cctx, &aclconfctx, ns_g_mctx, NULL, + dns_c_ctx_getblackhole, + &server->blackholeacl)); + if (server->blackholeacl != NULL) + dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, + server->blackholeacl); + /* dns_loadmgr_setlimit(server->loadmgr, 20); XXXMPA */ /* @@ -1739,6 +1746,9 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_zonemgr_shutdown(server->zonemgr); + if (server->blackholeacl != NULL) + dns_acl_detach(&server->blackholeacl); + isc_task_detach(&server->task); isc_event_free(&event); @@ -1778,6 +1788,7 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->interfacemgr = NULL; ISC_LIST_INIT(server->viewlist); server->in_roothints = NULL; + server->blackholeacl = NULL; CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, &server->in_roothints), diff --git a/doc/misc/options b/doc/misc/options index 2027f0b494..571484c911 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -1,7 +1,7 @@ Copyright (C) 2000 Internet Software Consortium. See COPYRIGHT in the source root or http://isc.org/copyright.html for terms. -$Id: options,v 1.37 2000/10/18 22:16:06 bwelling Exp $ +$Id: options,v 1.38 2000/11/03 02:45:42 bwelling Exp $ This is a summary of the implementation status of the various named.conf options in BIND 9. @@ -60,7 +60,7 @@ options { [ allow-query { address_match_list }; ] Yes@ [ allow-transfer { address_match_list }; ] Yes@ [ allow-recursion { address_match_list }; ] Yes@ - [ blackhole { address_match_list }; ] No + [ blackhole { address_match_list }; ] Yes [ listen-on [ port ip_port ] { address_match_list }; ] Yes@ [ listen-on-v6 [ port ip_port ] { address_match_list }; ] Yes* [ query-source ... ] Yes diff --git a/lib/dns/config/confctx.c b/lib/dns/config/confctx.c index 61e9dd0461..837fdd6a3b 100644 --- a/lib/dns/config/confctx.c +++ b/lib/dns/config/confctx.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: confctx.c,v 1.94 2000/10/31 04:20:50 marka Exp $ */ +/* $Id: confctx.c,v 1.95 2000/11/03 02:45:51 bwelling Exp $ */ #include @@ -450,13 +450,6 @@ dns_c_checkconfig(dns_c_ctx_t *cfg) "option 'check-names' is not yet implemented"); } - if (dns_c_ctx_getblackhole(cfg, &ipml) != ISC_R_NOTFOUND) { - dns_c_ipmatchlist_detach(&ipml); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, - DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, - "option 'blackhole' is not yet implemented"); - } - if (dns_c_ctx_getlamettl(cfg, &uintval) != ISC_R_NOTFOUND) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG, DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING, diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index febd7f129d..3912716fed 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.72 2000/10/20 02:21:43 marka Exp $ */ +/* $Id: dispatch.c,v 1.73 2000/11/03 02:45:45 bwelling Exp $ */ #include @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,7 @@ struct dns_dispatchmgr { /* Unlocked. */ unsigned int magic; isc_mem_t *mctx; + dns_acl_t *blackhole; /* Locked by "lock". */ isc_mutex_t lock; @@ -106,6 +108,7 @@ struct dns_dispatch { isc_socket_t *socket; /* isc socket attached to */ isc_sockaddr_t local; /* local address */ unsigned int maxrequests; /* max requests */ + dns_acl_t *blackhole; /* Locked by mgr->lock. */ ISC_LINK(dns_dispatch_t) link; @@ -508,6 +511,8 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { isc_boolean_t queue_response; dns_dispatchmgr_t *mgr; dns_qid_t *qid; + isc_netaddr_t netaddr; + int match; UNUSED(task); @@ -569,6 +574,27 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { goto restart; } + /* + * If this is from a blackholed address, drop it. + */ + isc_netaddr_fromsockaddr(&netaddr, &ev->address); + if (disp->blackhole != NULL && + dns_acl_match(&netaddr, NULL, disp->blackhole, + NULL, &match, NULL) == ISC_R_SUCCESS && + match > 0) + { + if (isc_log_wouldlog(dns_lctx, LVL(10))) { + char netaddrstr[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&netaddr, netaddrstr, + sizeof(netaddrstr)); + dispatch_log(disp, LVL(10), + "blackholed packet from %s", + netaddrstr); + } + free_buffer(disp, ev->region.base, ev->region.length); + goto restart; + } + /* * Peek into the buffer to see what we can see. */ @@ -989,6 +1015,9 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { DESTROYLOCK(&mgr->buffer_lock); + if (mgr->blackhole != NULL) + dns_acl_detach(&mgr->blackhole); + isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t)); isc_mem_detach(&mctx); } @@ -1037,6 +1066,8 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, mgr->mctx = NULL; isc_mem_attach(mctx, &mgr->mctx); + mgr->blackhole = NULL; + result = isc_mutex_init(&mgr->lock); if (result != ISC_R_SUCCESS) goto deallocate; @@ -1119,6 +1150,24 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, return (result); } +void +dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) { + REQUIRE(VALID_DISPATCHMGR(mgr)); + REQUIRE(mgr->blackhole == NULL); + dns_acl_attach(blackhole, &mgr->blackhole); +} + +isc_result_t +dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr, dns_acl_t **blackholep) { + REQUIRE(VALID_DISPATCHMGR(mgr)); + REQUIRE(blackholep != NULL && *blackholep == NULL); + + if (mgr->blackhole == NULL) + return (ISC_R_NOTFOUND); + dns_acl_attach(mgr->blackhole, blackholep); + return (ISC_R_SUCCESS); +} + static isc_result_t dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int buffersize, unsigned int maxbuffers, @@ -1393,6 +1442,10 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, goto kill_lock; } + disp->blackhole = NULL; + if (mgr->blackhole != NULL) + dns_acl_attach(mgr->blackhole, &disp->blackhole); + disp->magic = DISPATCH_MAGIC; *dispp = disp; @@ -1454,6 +1507,8 @@ dispatch_free(dns_dispatch_t **dispp) qid_destroy(mgr->mctx, &disp->qid); disp->mgr = NULL; DESTROYLOCK(&disp->lock); + if (disp->blackhole != NULL) + dns_acl_detach(&disp->blackhole); disp->magic = 0; isc_mempool_put(mgr->dpool, disp); } diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 81323de7cc..bf2f5ee962 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.h,v 1.36 2000/09/01 07:16:06 explorer Exp $ */ +/* $Id: dispatch.h,v 1.37 2000/11/03 02:45:52 bwelling Exp $ */ #ifndef DNS_DISPATCH_H #define DNS_DISPATCH_H 1 @@ -154,6 +154,29 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp); */ +void +dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole); +/* + * Sets the list of addresses that will be blackholed (ignored) + * by all dispatchers created by the dispatchmgr. + * + * Requires: + * mgrp is a valid dispatchmgr + * blackhole is a valid acl + */ + + +isc_result_t +dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr, dns_acl_t **blackholep); +/* + * Gets the list of addresses that will be blackholed (ignored) + * by all dispatchers created by the dispatchmgr. + * + * Requires: + * mgr is a valid dispatchmgr + * blackholep != NULL && *blackholep == NULL + */ + isc_result_t dns_dispatchmgr_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *remote, diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 2165278a17..c39cbfacc9 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.70 2000/10/18 23:53:31 marka Exp $ */ +/* $Id: result.h,v 1.71 2000/11/03 02:45:53 bwelling Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -104,8 +104,9 @@ #define DNS_R_UNEXPECTEDID (ISC_RESULTCLASS_DNS + 65) #define DNS_R_SEENINCLUDE (ISC_RESULTCLASS_DNS + 66) #define DNS_R_NOTEXACT (ISC_RESULTCLASS_DNS + 67) +#define DNS_R_BLACKHOLED (ISC_RESULTCLASS_DNS + 68) -#define DNS_R_NRESULTS 68 /* Number of results */ +#define DNS_R_NRESULTS 69 /* Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/request.c b/lib/dns/request.c index 77f64f0ab0..d387183c88 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.c,v 1.40 2000/10/31 01:17:15 marka Exp $ */ +/* $Id: request.c,v 1.41 2000/11/03 02:45:46 bwelling Exp $ */ #include @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -441,6 +442,7 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, unsigned int attrs; isc_boolean_t tcp = ISC_FALSE; isc_region_t r; + dns_acl_t *blackhole = NULL; REQUIRE(VALID_REQUESTMGR(requestmgr)); REQUIRE(msgbuf != NULL); @@ -456,6 +458,30 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, req_log(ISC_LOG_DEBUG(3), "dns_request_createraw"); + (void)dns_dispatchmgr_getblackhole(requestmgr->dispatchmgr, + &blackhole); + if (blackhole != NULL) { + isc_netaddr_t netaddr; + int match; + isc_boolean_t drop = ISC_FALSE; + + isc_netaddr_fromsockaddr(&netaddr, destaddr); + if (dns_acl_match(&netaddr, NULL, blackhole, + NULL, &match, NULL) == ISC_R_SUCCESS && + match > 0) + drop = ISC_TRUE; + dns_acl_detach(&blackhole); + if (drop) { + char netaddrstr[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&netaddr, netaddrstr, + sizeof(netaddrstr)); + req_log(ISC_LOG_DEBUG(10), "blackholed address %s", + netaddrstr); + return (DNS_R_BLACKHOLED); + } + } + + request = isc_mem_get(mctx, sizeof(*request)); request = isc_mem_get(mctx, sizeof(*request)); if (request == NULL) { return (ISC_R_NOMEMORY); @@ -720,6 +746,7 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, dns_messageid_t id; isc_time_t expires; unsigned int attrs; + dns_acl_t *blackhole = NULL; REQUIRE(VALID_REQUESTMGR(requestmgr)); REQUIRE(message != NULL); @@ -735,6 +762,29 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, req_log(ISC_LOG_DEBUG(3), "dns_request_create"); + (void)dns_dispatchmgr_getblackhole(requestmgr->dispatchmgr, + &blackhole); + if (blackhole != NULL) { + isc_netaddr_t netaddr; + int match; + isc_boolean_t drop = ISC_FALSE; + + isc_netaddr_fromsockaddr(&netaddr, destaddr); + if (dns_acl_match(&netaddr, NULL, blackhole, + NULL, &match, NULL) == ISC_R_SUCCESS && + match > 0) + drop = ISC_TRUE; + dns_acl_detach(&blackhole); + if (drop) { + char netaddrstr[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&netaddr, netaddrstr, + sizeof(netaddrstr)); + req_log(ISC_LOG_DEBUG(10), "blackholed address %s", + netaddrstr); + return (DNS_R_BLACKHOLED); + } + } + request = isc_mem_get(mctx, sizeof(*request)); if (request == NULL) { return (ISC_R_NOMEMORY); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index b18cefed42..f5eeee6d20 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.175 2000/10/31 03:21:59 marka Exp $ */ +/* $Id: resolver.c,v 1.176 2000/11/03 02:45:48 bwelling Exp $ */ #include @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -806,10 +807,11 @@ resquery_send(resquery_t *query) { isc_task_t *task; isc_socket_t *socket; isc_buffer_t tcpbuffer; - isc_sockaddr_t *address; + isc_sockaddr_t *address, taddress; isc_buffer_t *buffer; isc_netaddr_t ipaddr; dns_tsigkey_t *tsigkey = NULL; + dns_acl_t *blackhole = NULL; fctx = query->fctx; QTRACE("send"); @@ -991,7 +993,32 @@ resquery_send(resquery_t *query) { */ if ((query->options & DNS_FETCHOPT_TCP) == 0) address = &query->addrinfo->sockaddr; + else { + result = isc_socket_getpeername(socket, &taddress); + if (result != ISC_R_SUCCESS) + goto cleanup_message; + address = &taddress; + } isc_buffer_usedregion(buffer, &r); + + (void)dns_dispatchmgr_getblackhole(query->dispatchmgr, &blackhole); + if (blackhole != NULL) { + isc_netaddr_t netaddr; + int match; + isc_boolean_t drop = ISC_FALSE; + + isc_netaddr_fromsockaddr(&netaddr, address); + if (dns_acl_match(&netaddr, NULL, blackhole, + NULL, &match, NULL) == ISC_R_SUCCESS && + match > 0) + drop = ISC_TRUE; + dns_acl_detach(&blackhole); + if (drop) { + result = DNS_R_BLACKHOLED; + goto cleanup_message; + } + } + /* * XXXRTH Make sure we don't send to ourselves! We should probably * prune out these addresses when we get them from the ADB. diff --git a/lib/dns/result.c b/lib/dns/result.c index 46d974070d..91eace1db9 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.76 2000/10/18 23:53:26 marka Exp $ */ +/* $Id: result.c,v 1.77 2000/11/03 02:45:49 bwelling Exp $ */ #include @@ -106,7 +106,8 @@ static const char *text[DNS_R_NRESULTS] = { "unexpected message id", /* 65 DNS_R_UNEXPECTEDID */ "seen include file", /* 66 DNS_R_SEENINCLUDE */ - "not exact" /* 67 DNS_R_NOTEXACT */ + "not exact", /* 67 DNS_R_NOTEXACT */ + "address blackholed" /* 68 DNS_R_BLACKHOLED */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = {