]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: add `udr-ignore-list` option
authorEnsar Sarajčić <dev@ensarsarajcic.com>
Mon, 3 Jun 2024 14:27:34 +0000 (16:27 +0200)
committerEnsar Sarajčić <dev@ensarsarajcic.com>
Mon, 3 Jun 2024 15:01:53 +0000 (17:01 +0200)
This adds a `udr-ignore-list` option, similar to `new-domain-ignore-list`
option which can be used to provide a list of domains to not consider
for UDR algorithm.

Fixes: #14273
pdns/recursordist/docs/nod_udr.rst
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/settings/table.py

index 2da15412ad1b6356425e16cef6de417f99f44518..705090633d2a606b7e5a83186a1473178bd08e41 100644 (file)
@@ -59,6 +59,8 @@ The data is persisted to /var/lib/pdns-recursor/udr by default, which can be cha
 
 The SBF (which is maintained separately per recursor thread) cell size defaults to 67108864, which can be changed using the setting ``unique-response-db-size``. The same caveats regarding FPs/FNs apply as for NOD.
 
+Similarly to NOD, administrators may wish to prevent certain domains or subdomains from ever triggering the UDR algorithm, in which case those domains must be added to the ``udr-ignore-list`` setting as a comma separated list. No domain (or subdomain of a domain) listed will be considered a new unique domain response.
+
 Similarly to NOD, unique domain responses can be tracked using several mechanisms:
 
 Logging
index 5e0c98ee5ae1c522d82dca213878152206f54b15..f43314b2d1d1e4bfcf38047ef12cf6c28782a04c 100644 (file)
@@ -664,22 +664,25 @@ static void sendNODLookup(Logr::log_t nodlogger, const DNSName& dname)
 static bool udrCheckUniqueDNSRecord(Logr::log_t nodlogger, const DNSName& dname, uint16_t qtype, const DNSRecord& record)
 {
   bool ret = false;
-  if (record.d_place == DNSResourceRecord::ANSWER || record.d_place == DNSResourceRecord::ADDITIONAL) {
-    // Create a string that represent a triplet of (qname, qtype and RR[type, name, content])
-    std::stringstream strStream;
-    strStream << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.getContent()->getZoneRepresentation();
-    if (g_udrDBp && g_udrDBp->isUniqueResponse(strStream.str())) {
-      if (g_udrLog) {
-        // This should also probably log to a dedicated file.
-        SLOG(g_log << Logger::Notice << "Unique response observed: qname=" << dname << " qtype=" << QType(qtype) << " rrtype=" << QType(record.d_type) << " rrname=" << record.d_name << " rrcontent=" << record.getContent()->getZoneRepresentation() << endl,
-             nodlogger->info(Logr::Notice, "New response observed",
-                             "qtype", Logging::Loggable(QType(qtype)),
-                             "rrtype", Logging::Loggable(QType(record.d_type)),
-                             "rrname", Logging::Loggable(record.d_name),
-                             "rrcontent", Logging::Loggable(record.getContent()->getZoneRepresentation())););
-      }
-      t_Counters.at(rec::Counter::udrCount)++;
-      ret = true;
+  // First check the (sub)domain isn't ignored for UDR purposes
+  if (!g_udrDomainWL.check(dname)) {
+    if (record.d_place == DNSResourceRecord::ANSWER || record.d_place == DNSResourceRecord::ADDITIONAL) {
+      // Create a string that represent a triplet of (qname, qtype and RR[type, name, content])
+      std::stringstream strStream;
+      strStream << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.getContent()->getZoneRepresentation();
+      if (g_udrDBp && g_udrDBp->isUniqueResponse(strStream.str())) {
+        if (g_udrLog) {
+          // This should also probably log to a dedicated file.
+          SLOG(g_log << Logger::Notice << "Unique response observed: qname=" << dname << " qtype=" << QType(qtype) << " rrtype=" << QType(record.d_type) << " rrname=" << record.d_name << " rrcontent=" << record.getContent()->getZoneRepresentation() << endl,
+               nodlogger->info(Logr::Notice, "New response observed",
+                               "qtype", Logging::Loggable(QType(qtype)),
+                               "rrtype", Logging::Loggable(QType(record.d_type)),
+                               "rrname", Logging::Loggable(record.d_name),
+                               "rrcontent", Logging::Loggable(record.getContent()->getZoneRepresentation())););
+        }
+        t_Counters.at(rec::Counter::udrCount)++;
+        ret = true;
+      }
     }
   }
   return ret;
index 2b2d1705b3ae3b8023ee1af112aa21ce92bba9bb..11c75955c8a47e38fb649eabace54f62acb1efd3 100644 (file)
@@ -92,6 +92,7 @@ bool g_nodEnabled;
 DNSName g_nodLookupDomain;
 bool g_nodLog;
 SuffixMatchNode g_nodDomainWL;
+SuffixMatchNode g_udrDomainWL;
 std::string g_nod_pbtag;
 bool g_udrEnabled;
 bool g_udrLog;
@@ -867,6 +868,15 @@ static void parseNODIgnorelist(const std::string& wlist)
   }
 }
 
+static void parseUDRIgnorelist(const std::string& wlist)
+{
+  vector<string> parts;
+  stringtok(parts, wlist, ",; ");
+  for (const auto& part : parts) {
+    g_udrDomainWL.add(DNSName(part));
+  }
+}
+
 static void setupNODGlobal()
 {
   // Setup NOD subsystem
@@ -881,6 +891,7 @@ static void setupNODGlobal()
   g_udrLog = ::arg().mustDo("unique-response-log");
   g_nod_pbtag = ::arg()["new-domain-pb-tag"];
   g_udr_pbtag = ::arg()["unique-response-pb-tag"];
+  parseUDRIgnorelist(::arg()["udr-ignore-list"]);
 }
 #endif /* NOD_ENABLED */
 
index c69e4de74a199d780584fba52c71cae5b187b346..67e60785ad223b790c099e067ace8259cf55feb4 100644 (file)
@@ -245,6 +245,7 @@ extern bool g_nodEnabled;
 extern DNSName g_nodLookupDomain;
 extern bool g_nodLog;
 extern SuffixMatchNode g_nodDomainWL;
+extern SuffixMatchNode g_udrDomainWL;
 extern std::string g_nod_pbtag;
 extern bool g_udrEnabled;
 extern bool g_udrLog;
index e16200c7d11e708318c2c1826179766cadfa7704..758d3ed6f76badff1dd7fd6768a3cb363ec143a4 100644 (file)
@@ -1795,6 +1795,23 @@ feature.
  ''',
     'versionadded': '4.5.0'
     },
+    {
+        'name' : 'udr_ignore_list',
+        'section' : 'nod',
+        'oldname' : 'udr-ignore-list',
+        'type' : LType.ListStrings,
+        'default' : '',
+        'help' : 'List of domains (and implicitly all subdomains) which will never be considered for UDR',
+        'doc' : '''
+This setting is a list of all domains (and implicitly all subdomains)
+that will never be considered for a new unique domain request.
+For example, if the domain 'xyz123.tv' is in the list, then 'foo.bar.xyz123.tv'
+will never be considered for a new unique domain request. One use-case for the
+ignore list is to never reveal details of internal subdomains
+via the new-domain-lookup feature.
+ ''',
+        'versionadded' : '5.1.0'
+    },
     {
         'name' : 'pb_tag',
         'section' : 'nod',