From: Remi Gacogne Date: Wed, 23 Oct 2019 14:41:49 +0000 (+0200) Subject: dnsdist: Separate the check-config and client modes X-Git-Tag: auth-4.3.0-beta1~33^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=203b5348f420d1b2bd871dcf3a8019a444f15da3;p=thirdparty%2Fpdns.git dnsdist: Separate the check-config and client modes In client (and single command) mode we do not care too much about parsing the syntax of commands that do not relate to the console itself, and we do not want to create sockets and touch files on the local filesystem while parsing the configuration. In check-config mode, however, we want to parse as much configuration directives as possible, and we to generate some files that might be required to validate the rest of the configuration (DNSCrypt certificates and keys, OCSP responses..). This PR separates the two modes and tries to skip only the following parts when in check-config mode, compared to 'normal' configuration parsing: - we still parse and create objects when processing 'add*Local()' and 'set*Local()' directives, since the actual binding is delayed anyway ; - we do not connect the outgoing sockets toward our backends ; - we do not create Protocol Buffer or DNSTap outgoing connections ; - we do not start the console, SNMP or webserver threads. --- diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 39ef2da24d..33e1426b30 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -206,15 +206,19 @@ static void parseTLSConfig(TLSConfig& config, const std::string& context, boost: #endif // defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS) -void setupLuaConfig(bool client) +void setupLuaConfig(bool client, bool configCheck) { typedef std::unordered_map >, DownstreamState::checkfunc_t > > newserver_t; g_lua.writeFunction("inClientStartup", [client]() { return client && !g_configurationDone; }); + g_lua.writeFunction("inConfigCheck", [client, configCheck]() { + return !configCheck; + }); + g_lua.writeFunction("newServer", - [client](boost::variant pvars, boost::optional qps) { + [client, configCheck](boost::variant pvars, boost::optional qps) { setLuaSideEffect(); std::shared_ptr ret = std::make_shared(ComboAddress()); @@ -316,11 +320,8 @@ void setupLuaConfig(bool client) } } - if(client) { - // do not construct DownstreamState now, it would try binding sockets. - return ret; - } - ret=std::make_shared(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets); + // create but don't connect the socket in client or check-config modes + ret=std::make_shared(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets, !(client || configCheck)); if(vars.count("qps")) { int qpsVal=std::stoi(boost::get(vars["qps"])); @@ -746,7 +747,7 @@ void setupLuaConfig(bool client) g_carbon.setState(ours); }); - g_lua.writeFunction("webserver", [client](const std::string& address, const std::string& password, const boost::optional apiKey, const boost::optional > customHeaders) { + g_lua.writeFunction("webserver", [client,configCheck](const std::string& address, const std::string& password, const boost::optional apiKey, const boost::optional > customHeaders) { setLuaSideEffect(); ComboAddress local; try { @@ -756,7 +757,7 @@ void setupLuaConfig(bool client) throw std::runtime_error(std::string("Error parsing the bind address for the webserver: ") + e.reason); } - if (client) { + if (client || configCheck) { return; } @@ -809,11 +810,11 @@ void setupLuaConfig(bool client) } }); - g_lua.writeFunction("controlSocket", [client](const std::string& str) { + g_lua.writeFunction("controlSocket", [client,configCheck](const std::string& str) { setLuaSideEffect(); ComboAddress local(str, 5199); - if(client) { + if(client || configCheck) { g_serverControl = local; return; } @@ -1267,9 +1268,12 @@ void setupLuaConfig(bool client) #endif }); - g_lua.writeFunction("generateDNSCryptProviderKeys", [](const std::string& publicKeyFile, const std::string privateKeyFile) { + g_lua.writeFunction("generateDNSCryptProviderKeys", [client](const std::string& publicKeyFile, const std::string privateKeyFile) { setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT + if (client) { + return; + } unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; unsigned char privateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE]; sodium_mlock(privateKey, sizeof(privateKey)); @@ -1324,8 +1328,11 @@ void setupLuaConfig(bool client) }); #ifdef HAVE_DNSCRYPT - g_lua.writeFunction("generateDNSCryptCertificate", [](const std::string& providerPrivateKeyFile, const std::string& certificateFile, const std::string privateKeyFile, uint32_t serial, time_t begin, time_t end, boost::optional version) { + g_lua.writeFunction("generateDNSCryptCertificate", [client](const std::string& providerPrivateKeyFile, const std::string& certificateFile, const std::string privateKeyFile, uint32_t serial, time_t begin, time_t end, boost::optional version) { setLuaNoSideEffect(); + if (client) { + return; + } DNSCryptPrivateKey privateKey; DNSCryptCert cert; @@ -1619,8 +1626,8 @@ void setupLuaConfig(bool client) g_useTCPSinglePipe = flag; }); - g_lua.writeFunction("snmpAgent", [client](bool enableTraps, boost::optional masterSocket) { - if(client) + g_lua.writeFunction("snmpAgent", [client,configCheck](bool enableTraps, boost::optional masterSocket) { + if(client || configCheck) return; #ifdef HAVE_NET_SNMP if (g_configurationDone) { @@ -2105,24 +2112,28 @@ void setupLuaConfig(bool client) g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); #if defined(HAVE_LIBSSL) && defined(HAVE_OCSP_BASIC_SIGN) - g_lua.writeFunction("generateOCSPResponse", [](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { - return libssl_generate_ocsp_response(certFile, caCert, caKey, outFile, ndays, nmin); + g_lua.writeFunction("generateOCSPResponse", [client](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { + if (client) { + return; + } + + libssl_generate_ocsp_response(certFile, caCert, caKey, outFile, ndays, nmin); }); #endif /* HAVE_LIBSSL && HAVE_OCSP_BASIC_SIGN*/ } -vector> setupLua(bool client, const std::string& config) +vector> setupLua(bool client, bool configCheck, const std::string& config) { g_launchWork= new vector>(); setupLuaActions(); - setupLuaConfig(client); + setupLuaConfig(client, configCheck); setupLuaBindings(client); setupLuaBindingsDNSCrypt(); setupLuaBindingsDNSQuestion(); setupLuaBindingsKVS(client); setupLuaBindingsPacketCache(); - setupLuaBindingsProtoBuf(client); + setupLuaBindingsProtoBuf(client, configCheck); setupLuaInspection(); setupLuaRules(); setupLuaVars(); diff --git a/pdns/dnsdist-lua.hh b/pdns/dnsdist-lua.hh index 9bd33266de..827d6e1cfb 100644 --- a/pdns/dnsdist-lua.hh +++ b/pdns/dnsdist-lua.hh @@ -84,13 +84,14 @@ void parseRuleParams(boost::optional params, boost::uuids::uuid typedef NetmaskTree nmts_t; +vector> setupLua(bool client, bool configCheck, const std::string& config); void setupLuaActions(); void setupLuaBindings(bool client); void setupLuaBindingsDNSCrypt(); void setupLuaBindingsDNSQuestion(); void setupLuaBindingsKVS(bool client); void setupLuaBindingsPacketCache(); -void setupLuaBindingsProtoBuf(bool client); +void setupLuaBindingsProtoBuf(bool client, bool configCheck); void setupLuaRules(); void setupLuaInspection(); void setupLuaVars(); diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 1674e9fc85..8e143d9240 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -788,7 +788,7 @@ void DownstreamState::setWeight(int newWeight) } } -DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf_, const std::string& sourceItfName_, size_t numberOfSockets): sourceItfName(sourceItfName_), remote(remote_), sourceAddr(sourceAddr_), sourceItf(sourceItf_) +DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf_, const std::string& sourceItfName_, size_t numberOfSockets, bool connect=true): sourceItfName(sourceItfName_), remote(remote_), sourceAddr(sourceAddr_), sourceItf(sourceItf_) { pthread_rwlock_init(&d_lock, nullptr); id = getUniqueID(); @@ -801,7 +801,7 @@ DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress fd = -1; } - if (!IsAnyAddress(remote)) { + if (connect && !IsAnyAddress(remote)) { reconnect(); idStates.resize(g_maxOutstanding); sw.start(); @@ -2613,7 +2613,7 @@ try g_policy.setState(leastOutstandingPol); if(g_cmdLine.beClient || !g_cmdLine.command.empty()) { - setupLua(true, g_cmdLine.config); + setupLua(true, false, g_cmdLine.config); if (clientAddress != ComboAddress()) g_serverControl = clientAddress; doClient(g_serverControl, g_cmdLine.command); @@ -2634,13 +2634,13 @@ try g_consoleACL.setState(consoleACL); if (g_cmdLine.checkConfig) { - setupLua(true, g_cmdLine.config); + setupLua(false, true, g_cmdLine.config); // No exception was thrown infolog("Configuration '%s' OK!", g_cmdLine.config); _exit(EXIT_SUCCESS); } - auto todo=setupLua(false, g_cmdLine.config); + auto todo=setupLua(false, false, g_cmdLine.config); auto localPools = g_pools.getCopy(); { diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 69bc783362..6a7c9c3192 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -835,8 +835,8 @@ struct DownstreamState { typedef std::function(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t; - DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets); - DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1) {} + DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets, bool connect); + DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1, true) {} ~DownstreamState() { for (auto& fd : sockets) { @@ -1187,7 +1187,6 @@ struct LocalHolders struct dnsheader; void controlThread(int fd, ComboAddress local); -vector> setupLua(bool client, const std::string& config); std::shared_ptr getPool(const pools_t& pools, const std::string& poolName); std::shared_ptr createPoolIfNotExists(pools_t& pools, const string& poolName); NumberedServerVector getDownstreamCandidates(const pools_t& pools, const std::string& poolName); diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc index 876c8124dd..0375e1ea45 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc @@ -32,7 +32,7 @@ #include "ipcipher.hh" #endif /* HAVE_LIBCRYPTO */ -void setupLuaBindingsProtoBuf(bool client) +void setupLuaBindingsProtoBuf(bool client, bool configCheck) { #ifdef HAVE_LIBCRYPTO g_lua.registerFunction("ipencrypt", [](const ComboAddress& ca, const std::string& key) { @@ -94,16 +94,16 @@ void setupLuaBindingsProtoBuf(bool client) }); /* RemoteLogger */ - g_lua.writeFunction("newRemoteLogger", [client](const std::string& remote, boost::optional timeout, boost::optional maxQueuedEntries, boost::optional reconnectWaitTime) { - if (client) { + g_lua.writeFunction("newRemoteLogger", [client,configCheck](const std::string& remote, boost::optional timeout, boost::optional maxQueuedEntries, boost::optional reconnectWaitTime) { + if (client || configCheck) { return std::shared_ptr(nullptr); } return std::shared_ptr(new RemoteLogger(ComboAddress(remote), timeout ? *timeout : 2, maxQueuedEntries ? (*maxQueuedEntries*100) : 10000, reconnectWaitTime ? *reconnectWaitTime : 1, client)); }); - g_lua.writeFunction("newFrameStreamUnixLogger", [client](const std::string& address) { + g_lua.writeFunction("newFrameStreamUnixLogger", [client,configCheck](const std::string& address) { #ifdef HAVE_FSTRM - if (client) { + if (client || configCheck) { return std::shared_ptr(nullptr); } return std::shared_ptr(new FrameStreamLogger(AF_UNIX, address, !client)); @@ -112,9 +112,9 @@ void setupLuaBindingsProtoBuf(bool client) #endif /* HAVE_FSTRM */ }); - g_lua.writeFunction("newFrameStreamTcpLogger", [client](const std::string& address) { + g_lua.writeFunction("newFrameStreamTcpLogger", [client,configCheck](const std::string& address) { #if defined(HAVE_FSTRM) && defined(HAVE_FSTRM_TCP_WRITER_INIT) - if (client) { + if (client || configCheck) { return std::shared_ptr(nullptr); } return std::shared_ptr(new FrameStreamLogger(AF_INET, address, !client)); diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 8dcb9a70c6..9a3a0deaf0 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -227,6 +227,12 @@ Control Socket, Console and Webserver Returns true while the console client is parsing the configuration. +.. function:: inConfigCheck() + + .. versionadded:: 1.5.0 + + Returns true while the configuration is being checked, ie when run with ``--check-config``. + .. function:: makeKey() Generate and print an encryption key.