From: Remi Gacogne Date: Wed, 9 Jun 2021 10:06:52 +0000 (+0200) Subject: dnsdist: Fix an EDNS UDP payload size issue for UDP -> TCP only X-Git-Tag: dnsdist-1.7.0-alpha1~45^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33cf6ab4771f66414d7960c736c7577f4f67beb9;p=thirdparty%2Fpdns.git dnsdist: Fix an EDNS UDP payload size issue for UDP -> TCP only --- diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 931d239b47..35406444be 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1325,6 +1325,7 @@ public: thread_local LocalStateHolder> localRespRuleActions = g_respruleactions.getLocal(); DNSResponse dr = makeDNSResponseFromIDState(ids, response.d_buffer); if (response.d_buffer.size() > d_payloadSize) { + vinfolog("Got a response of size %d over TCP, while the initial UDP payload size was %d, truncating", response.d_buffer.size(), d_payloadSize); truncateTC(dr.getMutableData(), dr.getMaximumSize(), dr.qname->wirelength()); dr.getHeader()->tc = true; } @@ -1379,6 +1380,9 @@ public: { uint16_t z = 0; getEDNSUDPPayloadSizeAndZ(reinterpret_cast(buffer.data()), buffer.size(), &d_payloadSize, &z); + if (d_payloadSize < 512) { + d_payloadSize = 512; + } query = InternalQuery(std::move(buffer), std::move(ids)); downstream = ds; proxyProtocolPayloadSize = 0; diff --git a/regression-tests.dnsdist/test_TCPOnly.py b/regression-tests.dnsdist/test_TCPOnly.py new file mode 100644 index 0000000000..7ada4cacd6 --- /dev/null +++ b/regression-tests.dnsdist/test_TCPOnly.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +import dns + +from dnsdisttests import DNSDistTest + +class TestTCPOnly(DNSDistTest): + + _config_template = """ + newServer{address="127.0.0.1:%s", tcpOnly=true} + """ + + def testUDP(self): + """ + TCP Only: UDP query is sent via TCP + """ + name = 'udp.tcp-only.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + expectedResponse = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + expectedResponse.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, expectedResponse) + self.assertEqual(query, receivedQuery) + self.assertEqual(receivedResponse, expectedResponse) + + if 'UDP Responder' in self._responsesCounter: + self.assertEqual(self._responsesCounter['UDP Responder'], 0) + if 'TCP Responder' in self._responsesCounter: + self.assertEqual(self._responsesCounter['TCP Responder'], 1) + + def testTCP(self): + """ + TCP Only: TCP query is sent via TCP + """ + name = 'tcp.tcp-only.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + expectedResponse = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + expectedResponse.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendTCPQuery(query, expectedResponse) + self.assertEqual(query, receivedQuery) + self.assertEqual(receivedResponse, expectedResponse) + if 'UDP Responder' in self._responsesCounter: + self.assertEqual(self._responsesCounter['UDP Responder'], 0) + if 'TCP Responder' in self._responsesCounter: + self.assertEqual(self._responsesCounter['TCP Responder'], 1)