]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnsdist-lua.cc
dnsdist: Add support for the processing of X-Forwarded-For headers
[thirdparty/pdns.git] / pdns / dnsdist-lua.cc
index 79557c6f96caa5098f796d8779aad5953e789488..6df96431978fbbe3fc9b12faff81d0a0aaa9d1db 100644 (file)
@@ -36,6 +36,9 @@
 #include "dnsdist-ecs.hh"
 #include "dnsdist-healthchecks.hh"
 #include "dnsdist-lua.hh"
+#ifdef LUAJIT_VERSION
+#include "dnsdist-lua-ffi.hh"
+#endif /* LUAJIT_VERSION */
 #include "dnsdist-rings.hh"
 #include "dnsdist-secpoll.hh"
 
@@ -180,6 +183,10 @@ static void parseTLSConfig(TLSConfig& config, const std::string& context, boost:
     config.d_preferServerCiphers = boost::get<bool>((*vars)["preferServerCiphers"]);
   }
 
+  if (vars->count("sessionTimeout")) {
+    config.d_sessionTimeout = boost::get<int>((*vars)["sessionTimeout"]);
+  }
+
   if (vars->count("sessionTickets")) {
     config.d_enableTickets = boost::get<bool>((*vars)["sessionTickets"]);
   }
@@ -201,20 +208,25 @@ static void parseTLSConfig(TLSConfig& config, const std::string& context, boost:
   }
 
   if (vars->count("keyLogFile")) {
+#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
     config.d_keyLogFile = boost::get<const string>((*vars)["keyLogFile"]);
+#else
+    errlog("TLS Key logging has been enabled using the 'keyLogFile' parameter to %s(), but this version of OpenSSL does not support it", context);
+    g_outputBuffer = "TLS Key logging has been enabled using the 'keyLogFile' parameter to " + context + "(), but this version of OpenSSL does not support it";
+#endif
   }
 }
 
 #endif // defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS)
 
-void setupLuaConfig(bool client, bool configCheck)
+static void setupLuaConfig(bool client, bool configCheck)
 {
   typedef std::unordered_map<std::string, boost::variant<bool, std::string, vector<pair<int, std::string> >, DownstreamState::checkfunc_t > > newserver_t;
   g_lua.writeFunction("inClientStartup", [client]() {
         return client && !g_configurationDone;
   });
 
-  g_lua.writeFunction("inConfigCheck", [client, configCheck]() {
+  g_lua.writeFunction("inConfigCheck", [configCheck]() {
         return !configCheck;
   });
 
@@ -323,6 +335,9 @@ void setupLuaConfig(bool client, bool configCheck)
 
       // create but don't connect the socket in client or check-config modes
       ret=std::make_shared<DownstreamState>(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets, !(client || configCheck));
+      if (!(client || configCheck)) {
+        infolog("Added downstream server %s", serverAddr.toStringWithPort());
+      }
 
       if(vars.count("qps")) {
         int qpsVal=std::stoi(boost::get<string>(vars["qps"]));
@@ -383,7 +398,7 @@ void setupLuaConfig(bool client, bool configCheck)
       }
 
       if(vars.count("name")) {
-        ret->name=boost::get<string>(vars["name"]);
+        ret->setName(boost::get<string>(vars["name"]));
       }
 
       if (vars.count("id")) {
@@ -422,6 +437,10 @@ void setupLuaConfig(bool client, bool configCheck)
         ret->useECS=boost::get<bool>(vars["useClientSubnet"]);
       }
 
+      if(vars.count("useProxyProtocol")) {
+        ret->useProxyProtocol = boost::get<bool>(vars["useProxyProtocol"]);
+      }
+
       if(vars.count("disableZeroScope")) {
         ret->disableZeroScope=boost::get<bool>(vars["disableZeroScope"]);
       }
@@ -533,20 +552,6 @@ void setupLuaConfig(bool client, bool configCheck)
                         g_dstates.setState(states);
                       } );
 
-  g_lua.writeFunction("setServerPolicy", [](ServerPolicy policy)  {
-      setLuaSideEffect();
-      g_policy.setState(policy);
-    });
-  g_lua.writeFunction("setServerPolicyLua", [](string name, policyfunc_t policy)  {
-      setLuaSideEffect();
-      g_policy.setState(ServerPolicy{name, policy, true});
-    });
-
-  g_lua.writeFunction("showServerPolicy", []() {
-      setLuaSideEffect();
-      g_outputBuffer=g_policy.getLocal()->name+"\n";
-    });
-
   g_lua.writeFunction("truncateTC", [](bool tc) { setLuaSideEffect(); g_truncateTC=tc; });
   g_lua.writeFunction("fixupCase", [](bool fu) { setLuaSideEffect(); g_fixupCase=fu; });
 
@@ -555,6 +560,11 @@ void setupLuaConfig(bool client, bool configCheck)
       g_ACL.modify([domain](NetmaskGroup& nmg) { nmg.addMask(domain); });
     });
 
+  g_lua.writeFunction("rmACL", [](const std::string& netmask) {
+    setLuaSideEffect();
+    g_ACL.modify([netmask](NetmaskGroup& nmg) { nmg.deleteMask(netmask); });
+  });
+
   g_lua.writeFunction("setLocal", [client](const std::string& addr, boost::optional<localbind_t> vars) {
       setLuaSideEffect();
       if(client)
@@ -573,8 +583,8 @@ void setupLuaConfig(bool client, bool configCheck)
       try {
        ComboAddress loc(addr, 53);
         for (auto it = g_frontends.begin(); it != g_frontends.end(); ) {
-          /* TLS and DNSCrypt frontends are separate */
-          if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr) {
+          /* DoH, DoT and DNSCrypt frontends are separate */
+          if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr && (*it)->dohFrontend == nullptr) {
             it = g_frontends.erase(it);
           }
           else {
@@ -693,11 +703,11 @@ void setupLuaConfig(bool client, bool configCheck)
             pools+=p;
           }
           if (showUUIDs) {
-            ret << (fmt % counter % s->name % s->remote.toStringWithPort() %
+            ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() %
                     status %
                     s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec/1000.0) % s->outstanding.load() % pools % s->id) << endl;
           } else {
-            ret << (fmt % counter % s->name % s->remote.toStringWithPort() %
+            ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() %
                     status %
                     s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec/1000.0) % s->outstanding.load() % pools) << endl;
           }
@@ -1087,8 +1097,8 @@ void setupLuaConfig(bool client, bool configCheck)
       boost::format fmt("%-24s %8d %8d %-10s %-20s %s\n");
       g_outputBuffer = (fmt % "What" % "Seconds" % "Blocks" % "Warning" % "Action" % "Reason").str();
       for(const auto& e: slow) {
-       if(now < e->second.until)
-         g_outputBuffer+= (fmt % e->first.toString() % (e->second.until.tv_sec - now.tv_sec) % e->second.blocks % (e->second.warning ? "true" : "false") % DNSAction::typeToString(e->second.action != DNSAction::Action::None ? e->second.action : g_dynBlockAction) % e->second.reason).str();
+       if(now < e.second.until)
+         g_outputBuffer+= (fmt % e.first.toString() % (e.second.until.tv_sec - now.tv_sec) % e.second.blocks % (e.second.warning ? "true" : "false") % DNSAction::typeToString(e.second.action != DNSAction::Action::None ? e.second.action : g_dynBlockAction) % e.second.reason).str();
       }
       auto slow2 = g_dynblockSMT.getCopy();
       slow2.visit([&now, &fmt](const SuffixMatchTree<DynBlock>& node) {
@@ -1295,6 +1305,11 @@ void setupLuaConfig(bool client, bool configCheck)
 #endif
     });
 
+  g_lua.writeFunction("getDNSCryptBindCount", []() {
+      setLuaNoSideEffect();
+      return g_dnsCryptLocals.size();
+    });
+
   g_lua.writeFunction("generateDNSCryptProviderKeys", [client](const std::string& publicKeyFile, const std::string privateKeyFile) {
       setLuaNoSideEffect();
 #ifdef HAVE_DNSCRYPT
@@ -1399,8 +1414,8 @@ void setupLuaConfig(bool client, bool configCheck)
             if (!servers.empty()) {
               servers += ", ";
             }
-            if (!server.second->name.empty()) {
-              servers += server.second->name;
+            if (!server.second->getName().empty()) {
+              servers += server.second->getName();
               servers += " ";
             }
             servers += server.second->remote.toStringWithPort();
@@ -1451,6 +1466,11 @@ void setupLuaConfig(bool client, bool configCheck)
       return ret;
       });
 
+  g_lua.writeFunction("getBindCount", []() {
+      setLuaNoSideEffect();
+      return g_frontends.size();
+    });
+
   g_lua.writeFunction("help", [](boost::optional<std::string> command) {
       setLuaNoSideEffect();
       g_outputBuffer = "";
@@ -1626,7 +1646,7 @@ void setupLuaConfig(bool client, bool configCheck)
 
   g_lua.writeFunction("setConsistentHashingBalancingFactor", [](double factor) {
       setLuaSideEffect();
-      if (factor >= 0) {
+      if (factor >= 1.0) {
         g_consistentHashBalancingFactor = factor;
       }
       else {
@@ -1636,6 +1656,18 @@ void setupLuaConfig(bool client, bool configCheck)
       }
     });
 
+  g_lua.writeFunction("setWeightedBalancingFactor", [](double factor) {
+      setLuaSideEffect();
+      if (factor >= 1.0) {
+        g_weightedBalancingFactor = factor;
+      }
+      else {
+        errlog("Invalid value passed to setWeightedBalancingFactor()!");
+        g_outputBuffer="Invalid value passed to setWeightedBalancingFactor()!\n";
+        return;
+      }
+    });
+
   g_lua.writeFunction("setRingBuffersSize", [](size_t capacity, boost::optional<size_t> numberOfShards) {
       setLuaSideEffect();
       if (g_configurationDone) {
@@ -1691,11 +1723,30 @@ void setupLuaConfig(bool client, bool configCheck)
     });
 
   g_lua.writeFunction("sendCustomTrap", [](const std::string& str) {
-#ifdef HAVE_NET_SNMP
       if (g_snmpAgent && g_snmpTrapsEnabled) {
         g_snmpAgent->sendCustomTrap(str);
       }
-#endif /* HAVE_NET_SNMP */
+    });
+
+  g_lua.writeFunction("setServerPolicy", [](ServerPolicy policy) {
+      setLuaSideEffect();
+      g_policy.setState(policy);
+    });
+
+  g_lua.writeFunction("setServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy) {
+      setLuaSideEffect();
+      g_policy.setState(ServerPolicy{name, policy, true});
+    });
+
+  g_lua.writeFunction("setServerPolicyLuaFFI", [](string name, ServerPolicy::ffipolicyfunc_t policy) {
+      setLuaSideEffect();
+      auto pol = ServerPolicy(name, policy);
+      g_policy.setState(std::move(pol));
+    });
+
+  g_lua.writeFunction("showServerPolicy", []() {
+      setLuaSideEffect();
+      g_outputBuffer=g_policy.getLocal()->name+"\n";
     });
 
   g_lua.writeFunction("setPoolServerPolicy", [](ServerPolicy policy, string pool) {
@@ -1705,7 +1756,7 @@ void setupLuaConfig(bool client, bool configCheck)
       g_pools.setState(localPools);
     });
 
-  g_lua.writeFunction("setPoolServerPolicyLua", [](string name, policyfunc_t policy, string pool) {
+  g_lua.writeFunction("setPoolServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy, string pool) {
       setLuaSideEffect();
       auto localPools = g_pools.getCopy();
       setPoolPolicy(localPools, pool, std::make_shared<ServerPolicy>(ServerPolicy{name, policy, true}));
@@ -1797,10 +1848,10 @@ void setupLuaConfig(bool client, bool configCheck)
   });
 
   g_lua.writeFunction("addDOHLocal", [client](const std::string& addr, boost::optional<boost::variant<std::string, std::vector<std::pair<int,std::string>>>> certFiles, boost::optional<boost::variant<std::string, std::vector<std::pair<int,std::string>>>> keyFiles, boost::optional<boost::variant<std::string, vector<pair<int, std::string> > > > urls, boost::optional<localbind_t> vars) {
-#ifdef HAVE_DNS_OVER_HTTPS
     if (client) {
       return;
     }
+#ifdef HAVE_DNS_OVER_HTTPS
     setLuaSideEffect();
     if (g_configurationDone) {
       g_outputBuffer="addDOHLocal cannot be used at runtime!\n";
@@ -1832,7 +1883,7 @@ void setupLuaConfig(bool client, bool configCheck)
       }
     }
     else {
-      frontend->d_urls = {"/"};
+      frontend->d_urls = {"/dns-query"};
     }
 
     bool reusePort = false;
@@ -1858,6 +1909,14 @@ void setupLuaConfig(bool client, bool configCheck)
         }
       }
 
+      if (vars->count("sendCacheControlHeaders")) {
+        frontend->d_sendCacheControlHeaders = boost::get<bool>((*vars)["sendCacheControlHeaders"]);
+      }
+
+      if (vars->count("trustForwardedForHeader")) {
+        frontend->d_trustForwardedForHeader = boost::get<bool>((*vars)["trustForwardedForHeader"]);
+      }
+
       parseTLSConfig(frontend->d_tlsConfig, "addDOHLocal", vars);
     }
     g_dohlocals.push_back(frontend);
@@ -1952,6 +2011,11 @@ void setupLuaConfig(bool client, bool configCheck)
         return result;
       });
 
+    g_lua.writeFunction("getDOHFrontendCount", []() {
+        setLuaNoSideEffect();
+        return g_dohlocals.size();
+      });
+
     g_lua.registerFunction<void(std::shared_ptr<DOHFrontend>::*)()>("reloadCertificates", [](std::shared_ptr<DOHFrontend> frontend) {
         if (frontend != nullptr) {
           frontend->reloadCertificates();
@@ -1984,9 +2048,10 @@ void setupLuaConfig(bool client, bool configCheck)
       });
 
   g_lua.writeFunction("addTLSLocal", [client](const std::string& addr, boost::variant<std::string, std::vector<std::pair<int,std::string>>> certFiles, boost::variant<std::string, std::vector<std::pair<int,std::string>>> keyFiles, boost::optional<localbind_t> vars) {
-#ifdef HAVE_DNS_OVER_TLS
-        if (client)
+        if (client) {
           return;
+        }
+#ifdef HAVE_DNS_OVER_TLS
         setLuaSideEffect();
         if (g_configurationDone) {
           g_outputBuffer="addTLSLocal cannot be used at runtime!\n";
@@ -2110,6 +2175,11 @@ void setupLuaConfig(bool client, bool configCheck)
         return result;
       });
 
+    g_lua.writeFunction("getTLSFrontendCount", []() {
+        setLuaNoSideEffect();
+        return g_tlslocals.size();
+      });
+
     g_lua.registerFunction<void(std::shared_ptr<TLSCtx>::*)()>("rotateTicketsKey", [](std::shared_ptr<TLSCtx> ctx) {
         if (ctx != nullptr) {
           ctx->rotateTicketsKey(time(nullptr));
@@ -2187,6 +2257,10 @@ vector<std::function<void(void)>> setupLua(bool client, bool configCheck, const
   setupLuaRules();
   setupLuaVars();
 
+#ifdef LUAJIT_VERSION
+  g_lua.executeCode(getLuaFFIWrappers());
+#endif
+
   std::ifstream ifs(config);
   if(!ifs)
     warnlog("Unable to read configuration from '%s'", config);