From 6e9fd1248fe8acf093f5ea182b582860d54ac110 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Tue, 9 Apr 2019 15:52:27 +0200 Subject: [PATCH] dnsdist: Unify the management of DNS/DNSCrypt/DoT frontends --- pdns/dnsdist-lua.cc | 62 +++++-- pdns/dnsdist-web.cc | 11 +- pdns/dnsdist.cc | 402 +++++++++++++------------------------------ pdns/dnsdist.hh | 15 +- pdns/tcpiohandler.hh | 4 - 5 files changed, 194 insertions(+), 300 deletions(-) diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 69e5c571f6..a260593065 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -497,10 +497,23 @@ void setupLuaConfig(bool client) try { ComboAddress loc(addr, 53); - g_locals.clear(); - g_locals.push_back(std::make_tuple(loc, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus)); /// only works pre-startup, so no sync necessary + for (auto it = g_frontends.begin(); it != g_frontends.end(); ) { + /* TLS and DNSCrypt frontends are separate */ + if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr) { + it = g_frontends.erase(it); + } + else { + ++it; + } + } + + // only works pre-startup, so no sync necessary + g_frontends.push_back(std::unique_ptr(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus))); + if (doTCP) { + g_frontends.push_back(std::unique_ptr(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus))); + } } - catch(std::exception& e) { + catch(const std::exception& e) { g_outputBuffer="Error: "+string(e.what())+"\n"; } }); @@ -523,7 +536,11 @@ void setupLuaConfig(bool client) try { ComboAddress loc(addr, 53); - g_locals.push_back(std::make_tuple(loc, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus)); /// only works pre-startup, so no sync necessary + // only works pre-startup, so no sync necessary + g_frontends.push_back(std::unique_ptr(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus))); + if (doTCP) { + g_frontends.push_back(std::unique_ptr(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus))); + } } catch(std::exception& e) { g_outputBuffer="Error: "+string(e.what())+"\n"; @@ -1095,7 +1112,17 @@ void setupLuaConfig(bool client) try { auto ctx = std::make_shared(providerName, certFile, keyFile); - g_dnsCryptLocals.push_back(std::make_tuple(ComboAddress(addr, 443), ctx, reusePort, tcpFastOpenQueueSize, interface, cpus)); + + /* UDP */ + auto cs = std::unique_ptr(new ClientState(ComboAddress(addr, 443), false, reusePort, tcpFastOpenQueueSize, interface, cpus)); + cs->dnscryptCtx = ctx; + g_dnsCryptLocals.push_back(ctx); + g_frontends.push_back(std::move(cs)); + + /* TCP */ + cs = std::unique_ptr(new ClientState(ComboAddress(addr, 443), true, reusePort, tcpFastOpenQueueSize, interface, cpus)); + cs->dnscryptCtx = ctx; + g_frontends.push_back(std::move(cs)); } catch(std::exception& e) { errlog(e.what()); @@ -1115,9 +1142,9 @@ void setupLuaConfig(bool client) ret << (fmt % "#" % "Address" % "Provider Name") << endl; size_t idx = 0; - for (const auto& local : g_dnsCryptLocals) { - const std::shared_ptr ctx = std::get<1>(local); - ret<< (fmt % idx % std::get<0>(local).toStringWithPort() % ctx->getProviderName()) << endl; + for (const auto& frontend : g_frontends) { + const std::shared_ptr ctx = frontend->dnscryptCtx; + ret<< (fmt % idx % frontend->local.toStringWithPort() % ctx->getProviderName()) << endl; idx++; } @@ -1132,7 +1159,7 @@ void setupLuaConfig(bool client) #ifdef HAVE_DNSCRYPT std::shared_ptr ret = nullptr; if (idx < g_dnsCryptLocals.size()) { - ret = std::get<1>(g_dnsCryptLocals.at(idx)); + ret = g_dnsCryptLocals.at(idx); } return ret; #else @@ -1285,7 +1312,7 @@ void setupLuaConfig(bool client) setLuaNoSideEffect(); ClientState* ret = nullptr; if(num < g_frontends.size()) { - ret=g_frontends[num]; + ret=g_frontends[num].get(); } return ret; }); @@ -1633,9 +1660,16 @@ void setupLuaConfig(bool client) return; } + bool doTCP = true; + bool reusePort = false; + int tcpFastOpenQueueSize = 0; + std::string interface; + std::set cpus; + (void) doTCP; + if (vars) { bool doTCP = true; - parseLocalBindVars(vars, doTCP, frontend->d_reusePort, frontend->d_tcpFastOpenQueueSize, frontend->d_interface, frontend->d_cpus); + parseLocalBindVars(vars, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus); if (vars->count("provider")) { frontend->d_provider = boost::get((*vars)["provider"]); @@ -1675,7 +1709,11 @@ void setupLuaConfig(bool client) try { frontend->d_addr = ComboAddress(addr, 853); vinfolog("Loading TLS provider %s", frontend->d_provider); - g_tlslocals.push_back(frontend); /// only works pre-startup, so no sync necessary + // only works pre-startup, so no sync necessary + auto cs = std::unique_ptr(new ClientState(frontend->d_addr, true, reusePort, tcpFastOpenQueueSize, interface, cpus)); + cs->tlsFrontend = frontend; + g_tlslocals.push_back(cs->tlsFrontend); + g_frontends.push_back(std::move(cs)); } catch(const std::exception& e) { g_outputBuffer="Error: "+string(e.what())+"\n"; diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index 291e16661d..704c575172 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -681,9 +681,14 @@ static void connectionThread(int sock, ComboAddress remote) acl+=s; } string localaddresses; - for(const auto& loc : g_locals) { - if(!localaddresses.empty()) localaddresses += ", "; - localaddresses += std::get<0>(loc).toStringWithPort(); + for(const auto& front : g_frontends) { + if (front->tcp) { + continue; + } + if (!localaddresses.empty()) { + localaddresses += ", "; + } + localaddresses += front->local.toStringWithPort(); } Json my_json = Json::object { diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 461c5f3896..c5c03f6da1 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -92,14 +92,13 @@ bool g_allowEmptyResponse{false}; GlobalStateHolder g_ACL; string g_outputBuffer; -vector>> g_locals; std::vector> g_tlslocals; -std::vector,bool, int, string, std::set >> g_dnsCryptLocals; +std::vector> g_dnsCryptLocals; #ifdef HAVE_EBPF shared_ptr g_defaultBPFFilter; std::vector > g_dynBPFFilters; #endif /* HAVE_EBPF */ -vector g_frontends; +std::vector> g_frontends; GlobalStateHolder g_pools; size_t g_udpVectorSize{1}; @@ -2168,6 +2167,102 @@ static void checkFileDescriptorsLimits(size_t udpBindsCount, size_t tcpBindsCoun } } +static void setUpLocalBind(std::unique_ptr& cs) +{ + /* skip some warnings if there is an identical UDP context */ + bool warn = cs->tcp == false || cs->tlsFrontend != nullptr; + int& fd = cs->tcp == false ? cs->udpFD : cs->tcpFD; + (void) warn; + + fd = SSocket(cs->local.sin4.sin_family, cs->tcp == false ? SOCK_DGRAM : SOCK_STREAM, 0); + + if (cs->tcp) { + SSetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1); +#ifdef TCP_DEFER_ACCEPT + SSetsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); +#endif + if (cs->fastOpenQueueSize > 0) { +#ifdef TCP_FASTOPEN + SSetsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, cs->fastOpenQueueSize); +#else + if (warn) { + warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", cs->local.toStringWithPort()); + } +#endif + } + } + + if(cs->local.sin4.sin_family == AF_INET6) { + SSetsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1); + } + + bindAny(cs->local.sin4.sin_family, fd); + + if(!cs->tcp && IsAnyAddress(cs->local)) { + int one=1; + setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems +#ifdef IPV6_RECVPKTINFO + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); +#endif + } + + if (cs->reuseport) { +#ifdef SO_REUSEPORT + SSetsockopt(fd, SOL_SOCKET, SO_REUSEPORT, 1); +#else + if (warn) { + /* no need to warn again if configured but support is not available, we already did for UDP */ + warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", cs->local.toStringWithPort()); + } +#endif + } + + const std::string& itf = cs->interface; + if (!itf.empty()) { +#ifdef SO_BINDTODEVICE + int res = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length()); + if (res != 0) { + warnlog("Error setting up the interface on local address '%s': %s", cs->local.toStringWithPort(), strerror(errno)); + } +#else + if (warn) { + warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", cs->local.toStringWithPort()); + } +#endif + } + +#ifdef HAVE_EBPF + if (g_defaultBPFFilter) { + cs->attachFilter(g_defaultBPFFilter); + vinfolog("Attaching default BPF Filter to %s frontend %s", (!cs->tcp ? "UDP" : "TCP"), cs->local.toStringWithPort()); + } +#endif /* HAVE_EBPF */ + + if (cs->tlsFrontend != nullptr) { + if (!cs->tlsFrontend->setupTLS()) { + errlog("Error while setting up TLS on local address '%s', exiting", cs->local.toStringWithPort()); + _exit(EXIT_FAILURE); + } + } + + SBind(fd, cs->local); + + if (cs->tcp) { + SListen(cs->tcpFD, 64); + if (cs->tlsFrontend != nullptr) { + warnlog("Listening on %s for TLS", cs->local.toStringWithPort()); + } + else if (cs->dnscryptCtx != nullptr) { + warnlog("Listening on %s for DNSCrypt", cs->local.toStringWithPort()); + } + else { + warnlog("Listening on %s", cs->local.toStringWithPort()); + } + } + + cs->ready = true; +} + struct { vector locals; @@ -2449,291 +2544,42 @@ try } } - if(g_cmdLine.locals.size()) { - g_locals.clear(); - for(auto loc : g_cmdLine.locals) - g_locals.push_back(std::make_tuple(ComboAddress(loc, 53), true, false, 0, "", std::set())); - } - - if(g_locals.empty()) - g_locals.push_back(std::make_tuple(ComboAddress("127.0.0.1", 53), true, false, 0, "", std::set())); - - g_configurationDone = true; - - vector toLaunch; - for(const auto& local : g_locals) { - ClientState* cs = new ClientState; - cs->local= std::get<0>(local); - cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0); - if(cs->local.sin4.sin_family == AF_INET6) { - SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1); - } - //if(g_vm.count("bind-non-local")) - bindAny(cs->local.sin4.sin_family, cs->udpFD); - - // if (!setSocketTimestamps(cs->udpFD)) - // g_log<local)) { - int one=1; - setsockopt(cs->udpFD, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems -#ifdef IPV6_RECVPKTINFO - setsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); -#endif - } - - if (std::get<2>(local)) { -#ifdef SO_REUSEPORT - SSetsockopt(cs->udpFD, SOL_SOCKET, SO_REUSEPORT, 1); -#else - warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", std::get<0>(local).toStringWithPort()); -#endif - } - - const std::string& itf = std::get<4>(local); - if (!itf.empty()) { -#ifdef SO_BINDTODEVICE - int res = setsockopt(cs->udpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length()); - if (res != 0) { - warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(local).toStringWithPort(), strerror(errno)); + if (!g_cmdLine.locals.empty()) { + for (auto it = g_frontends.begin(); it != g_frontends.end(); ) { + /* TLS and DNSCrypt frontends are separate */ + if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr) { + it = g_frontends.erase(it); } -#else - warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(local).toStringWithPort()); -#endif - } - -#ifdef HAVE_EBPF - if (g_defaultBPFFilter) { - cs->attachFilter(g_defaultBPFFilter); - vinfolog("Attaching default BPF Filter to UDP frontend %s", cs->local.toStringWithPort()); - } -#endif /* HAVE_EBPF */ - - cs->cpus = std::get<5>(local); - - SBind(cs->udpFD, cs->local); - toLaunch.push_back(cs); - g_frontends.push_back(cs); - udpBindsCount++; - } - - for(const auto& local : g_locals) { - if(!std::get<1>(local)) { // no TCP/IP - warnlog("Not providing TCP/IP service on local address '%s'", std::get<0>(local).toStringWithPort()); - continue; - } - ClientState* cs = new ClientState; - cs->local= std::get<0>(local); - - cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0); - - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1); -#ifdef TCP_DEFER_ACCEPT - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); -#endif - if (std::get<3>(local) > 0) { -#ifdef TCP_FASTOPEN - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, std::get<3>(local)); -#else - warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", std::get<0>(local).toStringWithPort()); -#endif - } - if(cs->local.sin4.sin_family == AF_INET6) { - SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1); - } -#ifdef SO_REUSEPORT - /* no need to warn again if configured but support is not available, we already did for UDP */ - if (std::get<2>(local)) { - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1); - } -#endif - - const std::string& itf = std::get<4>(local); - if (!itf.empty()) { -#ifdef SO_BINDTODEVICE - int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length()); - if (res != 0) { - warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(local).toStringWithPort(), strerror(errno)); + else { + ++it; } -#else - warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(local).toStringWithPort()); -#endif } -#ifdef HAVE_EBPF - if (g_defaultBPFFilter) { - cs->attachFilter(g_defaultBPFFilter); - vinfolog("Attaching default BPF Filter to TCP frontend %s", cs->local.toStringWithPort()); + for(const auto& loc : g_cmdLine.locals) { + /* UDP */ + g_frontends.push_back(std::unique_ptr(new ClientState(ComboAddress(loc, 53), false, false, 0, "", {}))); + /* TCP */ + g_frontends.push_back(std::unique_ptr(new ClientState(ComboAddress(loc, 53), true, false, 0, "", {}))); } -#endif /* HAVE_EBPF */ - - // if(g_vm.count("bind-non-local")) - bindAny(cs->local.sin4.sin_family, cs->tcpFD); - SBind(cs->tcpFD, cs->local); - SListen(cs->tcpFD, 64); - warnlog("Listening on %s", cs->local.toStringWithPort()); - - toLaunch.push_back(cs); - g_frontends.push_back(cs); - tcpBindsCount++; } - for(auto& dcLocal : g_dnsCryptLocals) { - ClientState* cs = new ClientState; - cs->local = std::get<0>(dcLocal); - cs->dnscryptCtx = std::get<1>(dcLocal); - cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0); - if(cs->local.sin4.sin_family == AF_INET6) { - SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1); - } - bindAny(cs->local.sin4.sin_family, cs->udpFD); - if(IsAnyAddress(cs->local)) { - int one=1; - setsockopt(cs->udpFD, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems -#ifdef IPV6_RECVPKTINFO - setsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); -#endif - } - if (std::get<2>(dcLocal)) { -#ifdef SO_REUSEPORT - SSetsockopt(cs->udpFD, SOL_SOCKET, SO_REUSEPORT, 1); -#else - warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", std::get<0>(dcLocal).toStringWithPort()); -#endif - } - - const std::string& itf = std::get<4>(dcLocal); - if (!itf.empty()) { -#ifdef SO_BINDTODEVICE - int res = setsockopt(cs->udpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length()); - if (res != 0) { - warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(dcLocal).toStringWithPort(), strerror(errno)); - } -#else - warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(dcLocal).toStringWithPort()); -#endif - } - -#ifdef HAVE_EBPF - if (g_defaultBPFFilter) { - cs->attachFilter(g_defaultBPFFilter); - vinfolog("Attaching default BPF Filter to UDP DNSCrypt frontend %s", cs->local.toStringWithPort()); - } -#endif /* HAVE_EBPF */ - SBind(cs->udpFD, cs->local); - toLaunch.push_back(cs); - g_frontends.push_back(cs); - udpBindsCount++; - - cs = new ClientState; - cs->local = std::get<0>(dcLocal); - cs->dnscryptCtx = std::get<1>(dcLocal); - cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0); - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1); -#ifdef TCP_DEFER_ACCEPT - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); -#endif - if (std::get<3>(dcLocal) > 0) { -#ifdef TCP_FASTOPEN - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, std::get<3>(dcLocal)); -#else - warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", std::get<0>(dcLocal).toStringWithPort()); -#endif - } - -#ifdef SO_REUSEPORT - /* no need to warn again if configured but support is not available, we already did for UDP */ - if (std::get<2>(dcLocal)) { - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1); - } -#endif - - if (!itf.empty()) { -#ifdef SO_BINDTODEVICE - int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length()); - if (res != 0) { - warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(dcLocal).toStringWithPort(), strerror(errno)); - } -#else - warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(dcLocal).toStringWithPort()); -#endif - } - - if(cs->local.sin4.sin_family == AF_INET6) { - SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1); - } -#ifdef HAVE_EBPF - if (g_defaultBPFFilter) { - cs->attachFilter(g_defaultBPFFilter); - vinfolog("Attaching default BPF Filter to TCP DNSCrypt frontend %s", cs->local.toStringWithPort()); - } -#endif /* HAVE_EBPF */ - - cs->cpus = std::get<5>(dcLocal); - - bindAny(cs->local.sin4.sin_family, cs->tcpFD); - SBind(cs->tcpFD, cs->local); - SListen(cs->tcpFD, 64); - warnlog("Listening on %s", cs->local.toStringWithPort()); - toLaunch.push_back(cs); - g_frontends.push_back(cs); - tcpBindsCount++; + if (g_frontends.empty()) { + /* UDP */ + g_frontends.push_back(std::unique_ptr(new ClientState(ComboAddress("127.0.0.1", 53), false, false, 0, "", {}))); + /* TCP */ + g_frontends.push_back(std::unique_ptr(new ClientState(ComboAddress("127.0.0.1", 53), true, false, 0, "", {}))); } - for(auto& frontend : g_tlslocals) { - ClientState* cs = new ClientState; - cs->local = frontend->d_addr; - cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0); - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1); -#ifdef TCP_DEFER_ACCEPT - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); -#endif - if (frontend->d_tcpFastOpenQueueSize > 0) { -#ifdef TCP_FASTOPEN - SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, frontend->d_tcpFastOpenQueueSize); -#else - warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", cs->local.toStringWithPort()); -#endif - } - if (frontend->d_reusePort) { -#ifdef SO_REUSEPORT - SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1); -#else - warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", cs->local.toStringWithPort()); -#endif - } - if(cs->local.sin4.sin_family == AF_INET6) { - SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1); - } - - if (!frontend->d_interface.empty()) { -#ifdef SO_BINDTODEVICE - int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, frontend->d_interface.c_str(), frontend->d_interface.length()); - if (res != 0) { - warnlog("Error setting up the interface on local address '%s': %s", cs->local.toStringWithPort(), strerror(errno)); - } -#else - warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", cs->local.toStringWithPort()); -#endif - } + g_configurationDone = true; - cs->cpus = frontend->d_cpus; + for(auto& frontend : g_frontends) { + setUpLocalBind(frontend); - bindAny(cs->local.sin4.sin_family, cs->tcpFD); - if (frontend->setupTLS()) { - cs->tlsFrontend = frontend; - SBind(cs->tcpFD, cs->local); - SListen(cs->tcpFD, 64); - warnlog("Listening on %s for TLS", cs->local.toStringWithPort()); - toLaunch.push_back(cs); - g_frontends.push_back(cs); - tcpBindsCount++; + if (frontend->tcp == false) { + ++udpBindsCount; } else { - errlog("Error while setting up TLS on local address '%s', exiting", cs->local.toStringWithPort()); - delete cs; - _exit(EXIT_FAILURE); + ++tcpBindsCount; } } @@ -2831,16 +2677,16 @@ try } } - for(auto& cs : toLaunch) { + for(auto& cs : g_frontends) { if (cs->udpFD >= 0) { - thread t1(udpClientThread, cs); + thread t1(udpClientThread, cs.get()); if (!cs->cpus.empty()) { mapThreadToCPUList(t1.native_handle(), cs->cpus); } t1.detach(); } else if (cs->tcpFD >= 0) { - thread t1(tcpAcceptorThread, cs); + thread t1(tcpAcceptorThread, cs.get()); if (!cs->cpus.empty()) { mapThreadToCPUList(t1.native_handle(), cs->cpus); } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 663e18061b..8ffdaca2b4 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -581,10 +581,15 @@ extern QueryCount g_qcount; struct ClientState { + ClientState(const ComboAddress& local_, bool isTCP, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set& cpus_): cpus(cpus_), local(local_), interface(itfName), fastOpenQueueSize(fastOpenQueue), tcp(isTCP), reuseport(doReusePort) + { + } + std::set cpus; ComboAddress local; std::shared_ptr dnscryptCtx{nullptr}; - shared_ptr tlsFrontend; + std::shared_ptr tlsFrontend{nullptr}; + std::string interface; std::atomic queries{0}; std::atomic tcpDiedReadingQuery{0}; std::atomic tcpDiedSendingResponse{0}; @@ -597,7 +602,11 @@ struct ClientState std::atomic tcpAvgConnectionDuration{0.0}; int udpFD{-1}; int tcpFD{-1}; + int fastOpenQueueSize{0}; bool muted{false}; + bool tcp; + bool reuseport; + bool ready{false}; int getSocket() const { @@ -1008,7 +1017,7 @@ extern ComboAddress g_serverControl; // not changed during runtime extern std::vector>> g_locals; // not changed at runtime (we hope XXX) extern std::vector> g_tlslocals; -extern vector g_frontends; +extern std::vector> g_frontends; extern bool g_truncateTC; extern bool g_fixupCase; extern int g_tcpRecvTimeout; @@ -1098,7 +1107,7 @@ bool processResponse(char** response, uint16_t* responseLen, size_t* responseSiz bool checkQueryHeaders(const struct dnsheader* dh); -extern std::vector, bool, int, std::string, std::set > > g_dnsCryptLocals; +extern std::vector> g_dnsCryptLocals; int handleDNSCryptQuery(char* packet, uint16_t len, std::shared_ptr query, uint16_t* decryptedQueryLen, bool tcp, time_t now, std::vector& response); boost::optional> checkDNSCryptQuery(const ClientState& cs, const char* query, uint16_t& len, std::shared_ptr& dnsCryptQuery, time_t now, bool tcp); diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index e14c535d85..5c2c90a053 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -137,19 +137,15 @@ public: return res; } - std::set d_cpus; std::vector> d_certKeyPairs; ComboAddress d_addr; std::string d_ciphers; std::string d_provider; - std::string d_interface; std::string d_ticketKeyFile; size_t d_maxStoredSessions{20480}; time_t d_ticketsKeyRotationDelay{43200}; - int d_tcpFastOpenQueueSize{0}; uint8_t d_numberOfTicketsKeys{5}; - bool d_reusePort{false}; bool d_enableTickets{true}; private: -- 2.39.2