patch suggestion for 9.9.1-P1 - clear rrset when truncated flag is set in responses-

Sebastiano Di Paola sebastiano.dipaola at gmail.com
Tue Jul 24 13:29:45 UTC 2012


Hi there,
After posting some emails on bind-user to see if it was possible to
achieve the following behaviour with specific bind configuration, but
I couldn't find the solution so I tried to develop and submit my own
patch.
I hope this is the proper way to suggest and submit a patch in order
to have it evaluated/discussed with the bind developers team.

What I would like to achieve is reducing outgoing data volumes by
clearing the RRset that could be present inside a truncated response,
so no "partial" response are returned to the client/resolver. This
decision is taken "server" side no matter if the client has specified
EDNS0 additional record.

In this case only the question section is returned to the client, that
eventually might do again the same query using TCP prorocol.

According to me this achieved behaviour is useful when used in
conjunction with *max-udp-size* parameter, not only for "broken
firewall traversal" purposes, but also for reducing impact on DNS
refilection attack carried by UDP/IP spoofing (ie attack reflecting
qtype ANY isc.org to the victim), reducing the "amplification" factor.
Many dns related RFCs states that "Where TC is set, the partial RRSet
that would not completely fit may be left in the response" but nothig
prevents us to remove them.

I introduced a new parameter in configure script
(--enable-clear-rrset-on-trunc)  in order to allow this behaviour only
a compile time (using the same idea of filter-aaaa parameter) defining
ALLOW_CLEAR_RRSET_ON_TRUNC , and then clearing the response in
function  dns_message_renderend (the same code is executed when TC
flag is set and presence of TSIG o SIG(0) records). Applying the patch
then RRset (from answer section to the end of packet) are removed
every time TC flag is set.

As I'm not wrong looking at bind code flow is not possible to know if
the packet will be truncated or not before rendereing the response. So
the clearing process is done after the packet has been rendered. But
anyhow the allocation/disallocation of memory will be done even if the
"partial" RRset are not cleared. So there shouldn't be any perfomance
issue related to this.

I tried to point out pros and cons...
Pros:
- The amout of data sent out by the server is reduced when TC flag is
set. This is more evident when for some reason max-udp-size is set
i.e. to 512 bytes so the number of reponses with TC flag set is higher
expecially with EDSN0 additional record and in presence of i.e. query
type ANY.
- DNS reflection attacks using amplification are mitigated (as seen
from the victim side) by sending out few data (acually the same data
sent by query)
- If not enabled at compile time the bind code is not touched at all
- Expecially effective when also max-udp-size is set so we already
want our server to handle a "max" size packet. This will surely reduce
bandwidth used.

Cons:
- Not TCP capable dns client are not able to do the query (but if the
client is not TCP capable, what are the chances that it will support
EDNS0?)
- No partial results could be extracted from response (Who uses now
partial responses without re-querying the DNS with TCP)?
- Response time is higher because if response is needed client MUST do
again the query using TCP (and TCP is somehow "slower" than UDP (3-way
handshake and so on).


Here's follow the patch
---------------------------------------------------------------------------------------------------------------------------

diff -rau a/bind-9.9.1-P1/configure.in b/bind-9.9.1-P1/configure.in
--- a/bind-9.9.1-P1/configure.in	2012-06-01 17:29:52.000000000 +0200
+++ b/bind-9.9.1-P1/configure.in	2012-07-24 12:58:33.000000000 +0200
@@ -2865,6 +2865,26 @@
 esac

 #
+# Activate "clear-rrset-on-trunc" or not?
+#
+AC_ARG_ENABLE(clear-rrset-on-trunc,
+	[  --enable-clear-rrset-on-trunc
+			enable clearing of RRset in truncated UDP responses
+			[[default=no]]],
+			enable_filter="$enableval",
+			enable_filter="no")
+case "$enable_filter" in
+	yes)
+		AC_DEFINE(ALLOW_CLEAR_RRSET_ON_TRUNC_RESPONSES, 1,
+			  [Define to enable the "clear-rrset-on-trunc" option.])
+		;;
+	no)
+		;;
+	*)
+		;;
+esac
+
+#
 #  The following sets up how non-blocking i/o is established.
 #  Sunos, cygwin and solaris 2.x (x<5) require special handling.
 #
diff -rau a/bind-9.9.1-P1/lib/dns/message.c b/bind-9.9.1-P1/lib/dns/message.c
--- a/bind-9.9.1-P1/lib/dns/message.c	2012-06-01 17:29:52.000000000 +0200
+++ b/bind-9.9.1-P1/lib/dns/message.c	2012-07-24 12:58:51.000000000 +0200
@@ -2140,9 +2140,17 @@
 	 * clear all rdatasets from the message except for the question
 	 * before adding the TSIG or SIG(0).  If the question doesn't fit,
 	 * don't include it.
+	 *
+	 * All rdataset are cleared also on truncated message provided we
+	 * decided to compile bind with --enable-clear-rrset-on-trunc option.
+	 *
 	 */
+#ifndef ALLOW_CLEAR_RRSET_ON_TRUNC_RESPONSES	
 	if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
 	    (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+#else
+	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+#endif	
 	{
 		isc_buffer_t *buf;


---------------------------------------------------------------------------------------------------------------------------

Hope to discuss pros and cons soon.
Kind regards.
Seba


More information about the bind-workers mailing list