[ratelimits] Extending RRL to refused recursive queries
shawmplayer at yahoo.com
shawmplayer at yahoo.com
Wed Apr 17 04:08:08 UTC 2013
I installed the Bind 2013/04/04 RRL-only patch (rl-9.9.2-P1.patch) to
see how well it performs against the DNS reflection attempts my domains
are experiencing. It had some impact, but overall it only marginally
reduced the DNS spam traffic, which can be as much as 50X my ham.
I've not dug into the bowels of bind before, but after a quick look it
appears most of this is coming from external recursion requests being
refused by my DNS. Recursion is only enabled for internal clients and
my immediate WAN subnet. My external zone is only authoritative. While
the outbound traffic from the reflection attempts isn't staggering, I
see no point subjecting the victims to any of this, and furthermore I
would like to disincentivize the rabble by absorbing their recursion
request noise while delivering nothing in return to their victims.
However that didn't seem to be possible with the RRL patch, and when I
read the code it was apparent that refused recursion queries never pass
through through it. Hence I slapped together the attached patch (to be
applied on top of rl-9.9.2-P1.patch), which adds a
"cantdelegates-per-second" option to "rate-limit". Because my external
zone always refuses recursion requests, I don't mind telling this to a
client that occasionally asks. However I don't care what name they're
trying to query, so the hash key only applies to the client address.
Being a neophyte this patch is probably a mess, and might be useless to
the general DNS public. But it works great for me and drops recursive
refusals to virtually all the remaining reflection attempts I am
seeing. Sorry for the trouble if I am turning up dust that was put to
rest before.
-------------- next part --------------
--- ../../ref/bind-9.9.2-P1/bin/named/query.c Tue Apr 16 21:00:42 2013
+++ bin/named/query.c Tue Apr 16 20:12:47 2013
@@ -5433,6 +5433,51 @@
return (ISC_TRUE);
}
+static isc_boolean_t
+rrl_log_n_drop(ns_client_t *client, dns_rrl_result_t rrl_result, isc_result_t *query_error,
+ isc_boolean_t wouldlog, char *log_buf)
+{
+ /*
+ * Log dropped or slipped responses in the query
+ * category so that requests are not silently lost.
+ * Starts of rate-limited bursts are logged in
+ * DNS_LOGCATEGORY_RRL.
+ *
+ * Dropped responses are counted with dropped queries
+ * in QryDropped while slipped responses are counted
+ * with other truncated responses in RespTruncated.
+ */
+ *query_error = 0;
+ if (wouldlog && ns_g_server->log_queries) {
+ ns_client_log(client, NS_LOGCATEGORY_QUERIES,
+ NS_LOGMODULE_CLIENT,
+ DNS_RRL_LOG_DROP,
+ "%s", log_buf);
+ }
+ if (!client->view->rrl->log_only) {
+ if (rrl_result == DNS_RRL_RESULT_DROP) {
+ /*
+ * These will also be counted in
+ * dns_nsstatscounter_dropped
+ */
+ inc_stats(client,
+ dns_nsstatscounter_ratedropped);
+ *query_error = DNS_R_DROP;
+ } else {
+ /*
+ * These will also be counted in
+ * dns_nsstatscounter_truncatedresp
+ */
+ inc_stats(client,
+ dns_nsstatscounter_rateslipped);
+ client->message->flags |=
+ DNS_MESSAGEFLAG_TC;
+ }
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
/*
* Do the bulk of query processing for the current query of 'client'.
* If 'event' is non-NULL, we are returning from recursion and 'qtype'
@@ -5683,6 +5728,33 @@
if (WANTRECURSION(client)) {
inc_stats(client,
dns_nsstatscounter_recurserej);
+
+ if (client->view->rrl != NULL &&
+ (client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) {
+ isc_boolean_t wouldlog;
+ char log_buf[DNS_RRL_LOG_BUF_LEN];
+ dns_rrl_result_t rrl_result;
+
+ client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
+ wouldlog = isc_log_wouldlog(ns_g_lctx, DNS_RRL_LOG_DROP);
+
+ rrl_result = DNS_R_CANTDELEGATE;
+ rrl_result = dns_rrl(client->view, &client->peeraddr,
+ ISC_TF((client->attributes
+ & NS_CLIENTATTR_TCP) != 0),
+ client->message->rdclass, qtype, NULL,
+ rrl_result, client->now,
+ wouldlog, log_buf, sizeof(log_buf));
+ if (rrl_result != DNS_RRL_RESULT_OK) {
+ isc_result_t query_error;
+
+ rrl_log_n_drop(client, rrl_result, &query_error, wouldlog, log_buf);
+ if (query_error) {
+ QUERY_ERROR(query_error);
+ }
+ goto cleanup;
+ }
+ }
} else
inc_stats(client, dns_nsstatscounter_authrej);
if (!PARTIALANSWER(client))
@@ -5807,41 +5879,14 @@
rrl_result, client->now,
wouldlog, log_buf, sizeof(log_buf));
if (rrl_result != DNS_RRL_RESULT_OK) {
- /*
- * Log dropped or slipped responses in the query
- * category so that requests are not silently lost.
- * Starts of rate-limited bursts are logged in
- * DNS_LOGCATEGORY_RRL.
- *
- * Dropped responses are counted with dropped queries
- * in QryDropped while slipped responses are counted
- * with other truncated responses in RespTruncated.
- */
- if (wouldlog && ns_g_server->log_queries) {
- ns_client_log(client, NS_LOGCATEGORY_QUERIES,
- NS_LOGMODULE_CLIENT,
- DNS_RRL_LOG_DROP,
- "%s", log_buf);
- }
- if (!client->view->rrl->log_only) {
- if (rrl_result == DNS_RRL_RESULT_DROP) {
- /*
- * These will also be counted in
- * dns_nsstatscounter_dropped
- */
- inc_stats(client,
- dns_nsstatscounter_ratedropped);
- QUERY_ERROR(DNS_R_DROP);
- } else {
- /*
- * These will also be counted in
- * dns_nsstatscounter_truncatedresp
- */
- inc_stats(client,
- dns_nsstatscounter_rateslipped);
- client->message->flags |=
- DNS_MESSAGEFLAG_TC;
+ isc_result_t query_error;
+ isc_boolean_t goto_cleanup;
+
+ goto_cleanup = rrl_log_n_drop(client, rrl_result, &query_error, wouldlog, log_buf);
+ if (query_error) {
+ QUERY_ERROR(query_error);
}
+ if (goto_cleanup) {
goto cleanup;
}
}
--- ../../ref/bind-9.9.2-P1/bin/named/server.c Tue Apr 16 21:00:42 2013
+++ bin/named/server.c Tue Apr 16 15:40:37 2013
@@ -1619,6 +1619,17 @@
rrl->responses_per_second = i;
rrl->scaled_responses_per_second = rrl->responses_per_second;
+ i = 0;
+ obj = NULL;
+ result = cfg_map_get(map, "cantdelegates-per-second", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ CHECK_RRL(obj, i <= DNS_RRL_MAX_RATE,
+ "cantdelegates-per-second %d > %d",
+ i, DNS_RRL_MAX_RATE);
+ }
+ rrl->cantdelegates_per_second = i;
+ rrl->scaled_cantdelegates_per_second = rrl->cantdelegates_per_second;
/*
* The default error rate is the response rate,
* and so off by default.
--- ../../ref/bind-9.9.2-P1/lib/dns/include/dns/result.h Thu Oct 25 22:50:34 2012
+++ lib/dns/include/dns/result.h Tue Apr 16 15:44:42 2013
@@ -152,8 +152,9 @@
#define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106)
#define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107)
#define DNS_R_NOTDYNAMIC (ISC_RESULTCLASS_DNS + 108)
+#define DNS_R_CANTDELEGATE (ISC_RESULTCLASS_DNS + 109)
-#define DNS_R_NRESULTS 109 /*%< Number of results */
+#define DNS_R_NRESULTS 110 /*%< Number of results */
/*
* DNS wire format rcodes.
--- ../../ref/bind-9.9.2-P1/lib/dns/include/dns/rrl.h Tue Apr 16 21:00:42 2013
+++ lib/dns/include/dns/rrl.h Tue Apr 16 15:45:22 2013
@@ -76,6 +76,7 @@
DNS_RRL_RTYPE_ERROR,
DNS_RRL_RTYPE_ALL,
DNS_RRL_RTYPE_TCP,
+ DNS_RRL_RTYPE_CANTDELEGATE,
} dns_rrl_rtype_t;
/*
@@ -200,6 +201,7 @@
isc_boolean_t log_only;
int responses_per_second;
+ int cantdelegates_per_second;
int errors_per_second;
int nxdomains_per_second;
int all_per_second;
@@ -216,6 +218,7 @@
isc_stdtime_t qps_time;
double qps;
int scaled_responses_per_second;
+ int scaled_cantdelegates_per_second;
int scaled_errors_per_second;
int scaled_nxdomains_per_second;
int scaled_all_per_second;
--- ../../ref/bind-9.9.2-P1/lib/dns/rrl.c Tue Apr 16 21:00:42 2013
+++ lib/dns/rrl.c Tue Apr 16 19:44:32 2013
@@ -451,6 +451,9 @@
case DNS_RRL_RTYPE_DELEGATION:
rate = rrl->scaled_responses_per_second;
break;
+ case DNS_RRL_RTYPE_CANTDELEGATE:
+ rate = rrl->scaled_cantdelegates_per_second;
+ break;
case DNS_RRL_RTYPE_NXDOMAIN:
rate = rrl->scaled_nxdomains_per_second;
break;
@@ -612,6 +615,10 @@
rate = rrl->responses_per_second;
ratep = &rrl->scaled_responses_per_second;
break;
+ case DNS_RRL_RTYPE_CANTDELEGATE:
+ rate = rrl->cantdelegates_per_second;
+ ratep = &rrl->scaled_cantdelegates_per_second;
+ break;
case DNS_RRL_RTYPE_NXDOMAIN:
rate = rrl->nxdomains_per_second;
ratep = &rrl->scaled_nxdomains_per_second;
@@ -655,6 +662,9 @@
case DNS_RRL_RTYPE_DELEGATION:
rate_str = "responses-per-second";
break;
+ case DNS_RRL_RTYPE_CANTDELEGATE:
+ rate_str = "cantdelegates-per-second";
+ break;
case DNS_RRL_RTYPE_NXDOMAIN:
rate_str = "nxdomains-per-second";
break;
@@ -858,6 +868,9 @@
case DNS_RRL_RTYPE_DELEGATION:
ADD_LOG_CSTR(&lb, "referral");
break;
+ case DNS_RRL_RTYPE_CANTDELEGATE:
+ ADD_LOG_CSTR(&lb, "cannot refer response");
+ break;
case DNS_RRL_RTYPE_NXDOMAIN:
ADD_LOG_CSTR(&lb, "NXDOMAIN response");
break;
@@ -1121,6 +1134,8 @@
rtype = DNS_RRL_RTYPE_QUERY;
else if (resp_result == DNS_R_DELEGATION)
rtype = DNS_RRL_RTYPE_DELEGATION;
+ else if (resp_result == DNS_R_CANTDELEGATE)
+ rtype = DNS_RRL_RTYPE_CANTDELEGATE;
else if (resp_result == DNS_R_NXDOMAIN)
rtype = DNS_RRL_RTYPE_NXDOMAIN;
else
--- ../../ref/bind-9.9.2-P1/lib/isccfg/namedconf.c Tue Apr 16 21:00:43 2013
+++ lib/isccfg/namedconf.c Tue Apr 16 15:59:56 2013
@@ -1251,7 +1251,7 @@
{ "responses-per-second", &cfg_type_uint32, 0 },
{ "errors-per-second", &cfg_type_uint32, 0 },
{ "nxdomains-per-second", &cfg_type_uint32, 0 },
- { "responses-per-second", &cfg_type_uint32, 0 },
+ { "cantdelegates-per-second", &cfg_type_uint32, 0 },
{ "all-per-second", &cfg_type_uint32, 0 },
{ "slip", &cfg_type_uint32, 0 },
{ "window", &cfg_type_uint32, 0 },
More information about the ratelimits
mailing list