]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Ignore TCAction over TCP
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 7 Sep 2021 14:28:07 +0000 (16:28 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 7 Sep 2021 14:28:08 +0000 (16:28 +0200)
pdns/dnsdist.cc
pdns/dnsdistdist/docs/rules-actions.rst
regression-tests.dnsdist/test_Advanced.py
regression-tests.dnsdist/test_Basics.py

index 6f36fcb06a9ec00663998535b9dcac0cc5a823dc..7fc5aaf8f82599c5665d8a54f3b3b224bc4d62d1 100644 (file)
@@ -803,13 +803,15 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     return true;
     break;
   case DNSAction::Action::Truncate:
-    dq.getHeader()->tc = true;
-    dq.getHeader()->qr = true;
-    dq.getHeader()->ra = dq.getHeader()->rd;
-    dq.getHeader()->aa = false;
-    dq.getHeader()->ad = false;
-    ++g_stats.ruleTruncated;
-    return true;
+    if (!dq.overTCP()) {
+      dq.getHeader()->tc = true;
+      dq.getHeader()->qr = true;
+      dq.getHeader()->ra = dq.getHeader()->rd;
+      dq.getHeader()->aa = false;
+      dq.getHeader()->ad = false;
+      ++g_stats.ruleTruncated;
+      return true;
+    }
     break;
   case DNSAction::Action::HeaderModify:
     return true;
index 3fea22df58abfefdb74d05105449849db7c4e895..2de3cc0fcd8040068be8bcc97d2e473887361c55 100644 (file)
@@ -47,10 +47,13 @@ If this is not enough, try::
 
 or::
 
-  addAction(MaxQPSIPRule(5), TCAction())
+  addAction(AndRule{MaxQPSIPRule(5), TCPRule(false)}, TCAction())
 
 This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing clients to fall back to TCP.
 
+In that last one, note the use of :func:`TCPRule`.
+Without it, clients would get TC=1 even if they correctly fell back to TCP.
+
 To turn this per IP or range limit into a global limit, use ``NotRule(MaxQPSRule(5000))`` instead of :func:`MaxQPSIPRule`.
 
 Regular Expressions
@@ -1541,7 +1544,12 @@ The following actions exist.
 
 .. function:: TCAction()
 
+  .. versionchanged:: 1.7.0
+    This action is now only performed over UDP transports.
+
   Create answer to query with the TC bit set, and the RA bit set to the value of RD in the query, to force the client to TCP.
+  Before 1.7.0 this action was performed even when the query had been received over TCP, which required the use of :func:`TCPRule` to
+  prevent the TC bit from being set over TCP transports.
 
 .. function:: TeeAction(remote[, addECS])
 
index 27a9f6b0f534e561d3981078b998b7cbc47228c1..13120564b5fa9de7ab79b0ff357b14b677b8a931 100644 (file)
@@ -409,49 +409,6 @@ class TestAdvancedDelay(DNSDistTest):
         self.assertEqual(response, receivedResponse)
         self.assertTrue((end - begin) < timedelta(0, 1))
 
-
-class TestAdvancedTruncateAnyAndTCP(DNSDistTest):
-
-    _config_template = """
-    truncateTC(false)
-    addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction())
-    newServer{address="127.0.0.1:%s"}
-    """
-    def testTruncateAnyOverTCP(self):
-        """
-        Advanced: Truncate ANY over TCP
-
-        Send an ANY query to "anytruncatetcp.advanced.tests.powerdns.com.",
-        should be truncated over TCP, not over UDP (yes, it makes no sense,
-        deal with it).
-        """
-        name = 'anytruncatetcp.advanced.tests.powerdns.com.'
-        query = dns.message.make_query(name, 'ANY', 'IN')
-        # dnsdist sets RA = RD for TC responses
-        query.flags &= ~dns.flags.RD
-
-        response = dns.message.make_response(query)
-        rrset = dns.rrset.from_text(name,
-                                    3600,
-                                    dns.rdataclass.IN,
-                                    dns.rdatatype.A,
-                                    '127.0.0.1')
-
-        response.answer.append(rrset)
-
-        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
-        self.assertTrue(receivedQuery)
-        self.assertTrue(receivedResponse)
-        receivedQuery.id = query.id
-        self.assertEqual(query, receivedQuery)
-        self.assertEqual(receivedResponse, response)
-
-        expectedResponse = dns.message.make_response(query)
-        expectedResponse.flags |= dns.flags.TC
-
-        (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
-        self.assertEqual(receivedResponse, expectedResponse)
-
 class TestAdvancedAndNot(DNSDistTest):
 
     _config_template = """
index c879566dc925380c1226ee13f7159777cf63e610..7ba61ef27b35f8463bc267606b44d615e141fd32 100644 (file)
@@ -8,7 +8,7 @@ class TestBasics(DNSDistTest):
     _config_template = """
     newServer{address="127.0.0.1:%s"}
     truncateTC(true)
-    addAction(AndRule{QTypeRule(DNSQType.ANY), TCPRule(false)}, TCAction())
+    addAction(QTypeRule(DNSQType.ANY), TCAction())
     addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(DNSRCode.REFUSED))
     mySMN = newSuffixMatchNode()
     mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com."))