1 /* 2 * This file is part of PowerDNS or dnsdist. 3 * Copyright -- PowerDNS.COM B.V. and its contributors 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * In addition, for the avoidance of any doubt, permission is granted to 10 * link this program with OpenSSL and to (re)distribute the binaries 11 * produced as the result of such linking. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 #pragma once 23 #include "config.h" 24 #include "ext/luawrapper/include/LuaContext.hpp" 25 26 #include <mutex> 27 #include <string> 28 #include <thread> 29 #include <time.h> 30 #include <unistd.h> 31 #include <unordered_map> 32 33 #include <boost/variant.hpp> 34 35 #include "capabilities.hh" 36 #include "circular_buffer.hh" 37 #include "dnscrypt.hh" 38 #include "dnsdist-cache.hh" 39 #include "dnsdist-dynbpf.hh" 40 #include "dnsdist-lbpolicies.hh" 41 #include "dnsname.hh" 42 #include "doh.hh" 43 #include "ednsoptions.hh" 44 #include "gettime.hh" 45 #include "iputils.hh" 46 #include "misc.hh" 47 #include "mplexer.hh" 48 #include "noinitvector.hh" 49 #include "sholder.hh" 50 #include "tcpiohandler.hh" 51 #include "uuid-utils.hh" 52 #include "proxy-protocol.hh" 53 #include "stat_t.hh" 54 55 void carbonDumpThread(); 56 uint64_t uptimeOfProcess(const std::string& str); 57 58 extern uint16_t g_ECSSourcePrefixV4; 59 extern uint16_t g_ECSSourcePrefixV6; 60 extern bool g_ECSOverride; 61 62 using QTag = std::unordered_map<string, string>; 63 64 struct DNSQuestion 65 { DNSQuestionDNSQuestion66 DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_): 67 data(data_), qname(name), local(lc), remote(rem), queryTime(queryTime_), tempFailureTTL(boost::none), qtype(type), qclass(class_), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tcp(isTcp), ecsOverride(g_ECSOverride) { 68 const uint16_t* flags = getFlagsFromDNSHeader(getHeader()); 69 origFlags = *flags; 70 } 71 DNSQuestion(const DNSQuestion&) = delete; 72 DNSQuestion& operator=(const DNSQuestion&) = delete; 73 DNSQuestion(DNSQuestion&&) = default; 74 75 std::string getTrailingData() const; 76 bool setTrailingData(const std::string&); getDataDNSQuestion77 const PacketBuffer& getData() const 78 { 79 return data; 80 } getMutableDataDNSQuestion81 PacketBuffer& getMutableData() 82 { 83 return data; 84 } 85 getHeaderDNSQuestion86 dnsheader* getHeader() 87 { 88 if (data.size() < sizeof(dnsheader)) { 89 throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer"); 90 } 91 return reinterpret_cast<dnsheader*>(&data.at(0)); 92 } 93 getHeaderDNSQuestion94 const dnsheader* getHeader() const 95 { 96 if (data.size() < sizeof(dnsheader)) { 97 throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer"); 98 } 99 return reinterpret_cast<const dnsheader*>(&data.at(0)); 100 } 101 hasRoomForDNSQuestion102 bool hasRoomFor(size_t more) const 103 { 104 return data.size() <= getMaximumSize() && (getMaximumSize() - data.size()) >= more; 105 } 106 getMaximumSizeDNSQuestion107 size_t getMaximumSize() const 108 { 109 if (tcp) { 110 return std::numeric_limits<uint16_t>::max(); 111 } 112 return 4096; 113 } 114 115 protected: 116 PacketBuffer& data; 117 118 public: 119 boost::optional<boost::uuids::uuid> uniqueId; 120 Netmask ecs; 121 boost::optional<Netmask> subnet; 122 std::string sni; /* Server Name Indication, if any (DoT or DoH) */ 123 std::string poolname; 124 const DNSName* qname{nullptr}; 125 const ComboAddress* local{nullptr}; 126 const ComboAddress* remote{nullptr}; 127 /* this is the address dnsdist received the packet on, 128 which might not match local when support for incoming proxy protocol 129 is enabled */ 130 const ComboAddress* hopLocal{nullptr}; /* the address dnsdist received the packet from, see above */ 131 const ComboAddress* hopRemote{nullptr}; 132 std::shared_ptr<QTag> qTag{nullptr}; 133 std::unique_ptr<std::vector<ProxyProtocolValue>> proxyProtocolValues{nullptr}; 134 mutable std::shared_ptr<std::map<uint16_t, EDNSOptionView> > ednsOptions; 135 std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr}; 136 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr}; 137 const struct timespec* queryTime{nullptr}; 138 struct DOHUnit* du{nullptr}; 139 int delayMsec{0}; 140 boost::optional<uint32_t> tempFailureTTL; 141 uint32_t cacheKeyNoECS{0}; 142 uint32_t cacheKey{0}; 143 const uint16_t qtype; 144 const uint16_t qclass; 145 uint16_t ecsPrefixLength; 146 uint16_t origFlags; 147 uint16_t cacheFlags; /* DNS flags as sent to the backend */ 148 uint8_t ednsRCode{0}; 149 const bool tcp; 150 bool skipCache{false}; 151 bool ecsOverride; 152 bool useECS{true}; 153 bool addXPF{true}; 154 bool ecsSet{false}; 155 bool ecsAdded{false}; 156 bool ednsAdded{false}; 157 bool useZeroScope{false}; 158 bool dnssecOK{false}; 159 }; 160 161 struct DNSResponse : DNSQuestion 162 { DNSResponseDNSResponse163 DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_): 164 DNSQuestion(name, type, class_, lc, rem, data_, isTcp, queryTime_) { } 165 DNSResponse(const DNSResponse&) = delete; 166 DNSResponse& operator=(const DNSResponse&) = delete; 167 DNSResponse(DNSResponse&&) = default; 168 }; 169 170 /* so what could you do: 171 drop, 172 fake up nxdomain, 173 provide actual answer, 174 allow & and stop processing, 175 continue processing, 176 modify header: (servfail|refused|notimp), set TC=1, 177 send to pool */ 178 179 class DNSAction 180 { 181 public: 182 enum class Action { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw }; typeToString(const Action & action)183 static std::string typeToString(const Action& action) 184 { 185 switch(action) { 186 case Action::Drop: 187 return "Drop"; 188 case Action::Nxdomain: 189 return "Send NXDomain"; 190 case Action::Refused: 191 return "Send Refused"; 192 case Action::Spoof: 193 return "Spoof an answer"; 194 case Action::SpoofRaw: 195 return "Spoof an answer from raw bytes"; 196 case Action::Allow: 197 return "Allow"; 198 case Action::HeaderModify: 199 return "Modify the header"; 200 case Action::Pool: 201 return "Route to a pool"; 202 case Action::Delay: 203 return "Delay"; 204 case Action::Truncate: 205 return "Truncate over UDP"; 206 case Action::ServFail: 207 return "Send ServFail"; 208 case Action::None: 209 case Action::NoOp: 210 return "Do nothing"; 211 case Action::NoRecurse: 212 return "Set rd=0"; 213 } 214 215 return "Unknown"; 216 } 217 218 virtual Action operator()(DNSQuestion*, string* ruleresult) const =0; ~DNSAction()219 virtual ~DNSAction() 220 { 221 } 222 virtual string toString() const = 0; getStats() const223 virtual std::map<string, double> getStats() const 224 { 225 return {{}}; 226 } 227 }; 228 229 class DNSResponseAction 230 { 231 public: 232 enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, None }; 233 virtual Action operator()(DNSResponse*, string* ruleresult) const =0; ~DNSResponseAction()234 virtual ~DNSResponseAction() 235 { 236 } 237 virtual string toString() const = 0; 238 }; 239 240 struct DynBlock 241 { DynBlockDynBlock242 DynBlock(): action(DNSAction::Action::None), warning(false) 243 { 244 until.tv_sec = 0; 245 until.tv_nsec = 0; 246 } 247 DynBlockDynBlock248 DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_): reason(reason_), domain(domain_), until(until_), action(action_), warning(false) 249 { 250 } 251 DynBlockDynBlock252 DynBlock(const DynBlock& rhs): reason(rhs.reason), domain(rhs.domain), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) 253 { 254 blocks.store(rhs.blocks); 255 } 256 DynBlockDynBlock257 DynBlock(DynBlock&& rhs): reason(std::move(rhs.reason)), domain(std::move(rhs.domain)), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) 258 { 259 blocks.store(rhs.blocks); 260 } 261 operator =DynBlock262 DynBlock& operator=(const DynBlock& rhs) 263 { 264 reason = rhs.reason; 265 until = rhs.until; 266 domain = rhs.domain; 267 action = rhs.action; 268 blocks.store(rhs.blocks); 269 warning = rhs.warning; 270 bpf = rhs.bpf; 271 return *this; 272 } 273 operator =DynBlock274 DynBlock& operator=(DynBlock&& rhs) 275 { 276 reason = std::move(rhs.reason); 277 until = rhs.until; 278 domain = std::move(rhs.domain); 279 action = rhs.action; 280 blocks.store(rhs.blocks); 281 warning = rhs.warning; 282 bpf = rhs.bpf; 283 return *this; 284 } 285 286 string reason; 287 DNSName domain; 288 struct timespec until; 289 mutable std::atomic<unsigned int> blocks; 290 DNSAction::Action action{DNSAction::Action::None}; 291 bool warning{false}; 292 bool bpf{false}; 293 }; 294 295 extern GlobalStateHolder<NetmaskTree<DynBlock>> g_dynblockNMG; 296 297 extern vector<pair<struct timeval, std::string> > g_confDelta; 298 299 extern uint64_t getLatencyCount(const std::string&); 300 301 using pdns::stat_t; 302 303 struct DNSDistStats 304 { 305 stat_t responses{0}; 306 stat_t servfailResponses{0}; 307 stat_t queries{0}; 308 stat_t frontendNXDomain{0}; 309 stat_t frontendServFail{0}; 310 stat_t frontendNoError{0}; 311 stat_t nonCompliantQueries{0}; 312 stat_t nonCompliantResponses{0}; 313 stat_t rdQueries{0}; 314 stat_t emptyQueries{0}; 315 stat_t aclDrops{0}; 316 stat_t dynBlocked{0}; 317 stat_t ruleDrop{0}; 318 stat_t ruleNXDomain{0}; 319 stat_t ruleRefused{0}; 320 stat_t ruleServFail{0}; 321 stat_t ruleTruncated{0}; 322 stat_t selfAnswered{0}; 323 stat_t downstreamTimeouts{0}; 324 stat_t downstreamSendErrors{0}; 325 stat_t truncFail{0}; 326 stat_t noPolicy{0}; 327 stat_t cacheHits{0}; 328 stat_t cacheMisses{0}; 329 stat_t latency0_1{0}, latency1_10{0}, latency10_50{0}, latency50_100{0}, latency100_1000{0}, latencySlow{0}, latencySum{0}; 330 stat_t securityStatus{0}; 331 stat_t dohQueryPipeFull{0}; 332 stat_t dohResponsePipeFull{0}; 333 stat_t proxyProtocolInvalid{0}; 334 335 double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0}; 336 typedef std::function<uint64_t(const std::string&)> statfunction_t; 337 typedef boost::variant<stat_t*, double*, statfunction_t> entry_t; 338 std::vector<std::pair<std::string, entry_t>> entries{ 339 {"responses", &responses}, 340 {"servfail-responses", &servfailResponses}, 341 {"queries", &queries}, 342 {"frontend-nxdomain", &frontendNXDomain}, 343 {"frontend-servfail", &frontendServFail}, 344 {"frontend-noerror", &frontendNoError}, 345 {"acl-drops", &aclDrops}, 346 {"rule-drop", &ruleDrop}, 347 {"rule-nxdomain", &ruleNXDomain}, 348 {"rule-refused", &ruleRefused}, 349 {"rule-servfail", &ruleServFail}, 350 {"rule-truncated", &ruleTruncated}, 351 {"self-answered", &selfAnswered}, 352 {"downstream-timeouts", &downstreamTimeouts}, 353 {"downstream-send-errors", &downstreamSendErrors}, 354 {"trunc-failures", &truncFail}, 355 {"no-policy", &noPolicy}, 356 {"latency0-1", &latency0_1}, 357 {"latency1-10", &latency1_10}, 358 {"latency10-50", &latency10_50}, 359 {"latency50-100", &latency50_100}, 360 {"latency100-1000", &latency100_1000}, 361 {"latency-slow", &latencySlow}, 362 {"latency-avg100", &latencyAvg100}, 363 {"latency-avg1000", &latencyAvg1000}, 364 {"latency-avg10000", &latencyAvg10000}, 365 {"latency-avg1000000", &latencyAvg1000000}, 366 {"uptime", uptimeOfProcess}, 367 {"real-memory-usage", getRealMemoryUsage}, 368 {"special-memory-usage", getSpecialMemoryUsage}, 369 {"udp-in-errors", boost::bind(udpErrorStats, "udp-in-errors")}, 370 {"udp-noport-errors", boost::bind(udpErrorStats, "udp-noport-errors")}, 371 {"udp-recvbuf-errors", boost::bind(udpErrorStats, "udp-recvbuf-errors")}, 372 {"udp-sndbuf-errors", boost::bind(udpErrorStats, "udp-sndbuf-errors")}, 373 {"tcp-listen-overflows", std::bind(tcpErrorStats, "ListenOverflows")}, 374 {"noncompliant-queries", &nonCompliantQueries}, 375 {"noncompliant-responses", &nonCompliantResponses}, 376 {"proxy-protocol-invalid", &proxyProtocolInvalid}, 377 {"rdqueries", &rdQueries}, 378 {"empty-queries", &emptyQueries}, 379 {"cache-hits", &cacheHits}, 380 {"cache-misses", &cacheMisses}, 381 {"cpu-iowait", getCPUIOWait}, 382 {"cpu-steal", getCPUSteal}, 383 {"cpu-sys-msec", getCPUTimeSystem}, 384 {"cpu-user-msec", getCPUTimeUser}, 385 {"fd-usage", getOpenFileDescriptors}, 386 {"dyn-blocked", &dynBlocked}, __anond93cc1860102DNSDistStats387 {"dyn-block-nmg-size", [](const std::string&) { return g_dynblockNMG.getLocal()->size(); }}, 388 {"security-status", &securityStatus}, 389 {"doh-query-pipe-full", &dohQueryPipeFull}, 390 {"doh-response-pipe-full", &dohResponsePipeFull}, 391 // Latency histogram 392 {"latency-sum", &latencySum}, 393 {"latency-count", getLatencyCount}, 394 }; 395 }; 396 397 extern struct DNSDistStats g_stats; 398 void doLatencyStats(double udiff); 399 400 401 struct StopWatch 402 { StopWatchStopWatch403 StopWatch(bool realTime=false): d_needRealTime(realTime) 404 { 405 } 406 struct timespec d_start{0,0}; 407 bool d_needRealTime{false}; 408 startStopWatch409 void start() { 410 if(gettime(&d_start, d_needRealTime) < 0) 411 unixDie("Getting timestamp"); 412 413 } 414 setStopWatch415 void set(const struct timespec& from) { 416 d_start = from; 417 } 418 udiffStopWatch419 double udiff() const { 420 struct timespec now; 421 if(gettime(&now, d_needRealTime) < 0) 422 unixDie("Getting timestamp"); 423 424 return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0; 425 } 426 udiffAndSetStopWatch427 double udiffAndSet() { 428 struct timespec now; 429 if(gettime(&now, d_needRealTime) < 0) 430 unixDie("Getting timestamp"); 431 432 auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0; 433 d_start = now; 434 return ret; 435 } 436 437 }; 438 439 class BasicQPSLimiter 440 { 441 public: BasicQPSLimiter()442 BasicQPSLimiter() 443 { 444 } 445 BasicQPSLimiter(unsigned int burst)446 BasicQPSLimiter(unsigned int burst): d_tokens(burst) 447 { 448 d_prev.start(); 449 } 450 ~BasicQPSLimiter()451 virtual ~BasicQPSLimiter() 452 { 453 } 454 check(unsigned int rate,unsigned int burst) const455 bool check(unsigned int rate, unsigned int burst) const // this is not quite fair 456 { 457 if (checkOnly(rate, burst)) { 458 addHit(); 459 return true; 460 } 461 462 return false; 463 } 464 checkOnly(unsigned int rate,unsigned int burst) const465 bool checkOnly(unsigned int rate, unsigned int burst) const // this is not quite fair 466 { 467 auto delta = d_prev.udiffAndSet(); 468 469 if (delta > 0.0) { // time, frequently, does go backwards.. 470 d_tokens += 1.0 * rate * (delta/1000000.0); 471 } 472 473 if (d_tokens > burst) { 474 d_tokens = burst; 475 } 476 477 bool ret = false; 478 if (d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise 479 ret = true; 480 } 481 482 return ret; 483 } 484 addHit() const485 virtual void addHit() const 486 { 487 --d_tokens; 488 } 489 seenSince(const struct timespec & cutOff) const490 bool seenSince(const struct timespec& cutOff) const 491 { 492 return cutOff < d_prev.d_start; 493 } 494 495 protected: 496 mutable StopWatch d_prev; 497 mutable double d_tokens{0.0}; 498 }; 499 500 class QPSLimiter : public BasicQPSLimiter 501 { 502 public: QPSLimiter()503 QPSLimiter(): BasicQPSLimiter() 504 { 505 } 506 QPSLimiter(unsigned int rate,unsigned int burst)507 QPSLimiter(unsigned int rate, unsigned int burst): BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false) 508 { 509 d_prev.start(); 510 } 511 getRate() const512 unsigned int getRate() const 513 { 514 return d_passthrough ? 0 : d_rate; 515 } 516 check() const517 bool check() const // this is not quite fair 518 { 519 if (d_passthrough) { 520 return true; 521 } 522 523 return BasicQPSLimiter::check(d_rate, d_burst); 524 } 525 checkOnly() const526 bool checkOnly() const 527 { 528 if (d_passthrough) { 529 return true; 530 } 531 532 return BasicQPSLimiter::checkOnly(d_rate, d_burst); 533 } 534 addHit() const535 void addHit() const override 536 { 537 if (!d_passthrough) { 538 --d_tokens; 539 } 540 } 541 542 private: 543 unsigned int d_rate{0}; 544 unsigned int d_burst{0}; 545 bool d_passthrough{true}; 546 }; 547 548 struct ClientState; 549 550 /* g++ defines __SANITIZE_THREAD__ 551 clang++ supports the nice __has_feature(thread_sanitizer), 552 let's merge them */ 553 #if defined(__has_feature) 554 #if __has_feature(thread_sanitizer) 555 #define __SANITIZE_THREAD__ 1 556 #endif 557 #endif 558 559 struct IDState 560 { IDStateIDState561 IDState(): sentTime(true), delayMsec(0), tempFailureTTL(boost::none) { origDest.sin4.sin_family = 0;} 562 IDState(const IDState& orig) = delete; IDStateIDState563 IDState(IDState&& rhs): origRemote(rhs.origRemote), origDest(rhs.origDest), sentTime(rhs.sentTime), qname(std::move(rhs.qname)), dnsCryptQuery(std::move(rhs.dnsCryptQuery)), subnet(rhs.subnet), packetCache(std::move(rhs.packetCache)), qTag(std::move(rhs.qTag)), cs(rhs.cs), du(std::move(rhs.du)), cacheKey(rhs.cacheKey), cacheKeyNoECS(rhs.cacheKeyNoECS), qtype(rhs.qtype), qclass(rhs.qclass), origID(rhs.origID), origFlags(rhs.origFlags), cacheFlags(rhs.cacheFlags), origFD(rhs.origFD), delayMsec(rhs.delayMsec), tempFailureTTL(rhs.tempFailureTTL), ednsAdded(rhs.ednsAdded), ecsAdded(rhs.ecsAdded), skipCache(rhs.skipCache), destHarvested(rhs.destHarvested), dnssecOK(rhs.dnssecOK), useZeroScope(rhs.useZeroScope) 564 { 565 if (rhs.isInUse()) { 566 throw std::runtime_error("Trying to move an in-use IDState"); 567 } 568 569 uniqueId = std::move(rhs.uniqueId); 570 #ifdef __SANITIZE_THREAD__ 571 age.store(rhs.age.load()); 572 #else 573 age = rhs.age; 574 #endif 575 } 576 operator =IDState577 IDState& operator=(IDState&& rhs) 578 { 579 if (isInUse()) { 580 throw std::runtime_error("Trying to overwrite an in-use IDState"); 581 } 582 583 if (rhs.isInUse()) { 584 throw std::runtime_error("Trying to move an in-use IDState"); 585 } 586 587 origRemote = rhs.origRemote; 588 origDest = rhs.origDest; 589 sentTime = rhs.sentTime; 590 qname = std::move(rhs.qname); 591 dnsCryptQuery = std::move(rhs.dnsCryptQuery); 592 subnet = rhs.subnet; 593 packetCache = std::move(rhs.packetCache); 594 qTag = std::move(rhs.qTag); 595 cs = rhs.cs; 596 du = std::move(rhs.du); 597 cacheKey = rhs.cacheKey; 598 cacheKeyNoECS = rhs.cacheKeyNoECS; 599 qtype = rhs.qtype; 600 qclass = rhs.qclass; 601 origID = rhs.origID; 602 origFlags = rhs.origFlags; 603 cacheFlags = rhs.cacheFlags; 604 origFD = rhs.origFD; 605 delayMsec = rhs.delayMsec; 606 tempFailureTTL = rhs.tempFailureTTL; 607 ednsAdded = rhs.ednsAdded; 608 ecsAdded = rhs.ecsAdded; 609 skipCache = rhs.skipCache; 610 destHarvested = rhs.destHarvested; 611 dnssecOK = rhs.dnssecOK; 612 useZeroScope = rhs.useZeroScope; 613 #ifdef __SANITIZE_THREAD__ 614 age.store(rhs.age.load()); 615 #else 616 age = rhs.age; 617 #endif 618 uniqueId = std::move(rhs.uniqueId); 619 620 return *this; 621 } 622 623 static const int64_t unusedIndicator = -1; 624 isInUseIDState625 static bool isInUse(int64_t usageIndicator) 626 { 627 return usageIndicator != unusedIndicator; 628 } 629 isInUseIDState630 bool isInUse() const 631 { 632 return usageIndicator != unusedIndicator; 633 } 634 635 /* return true if the value has been successfully replaced meaning that 636 no-one updated the usage indicator in the meantime */ tryMarkUnusedIDState637 bool tryMarkUnused(int64_t expectedUsageIndicator) 638 { 639 return usageIndicator.compare_exchange_strong(expectedUsageIndicator, unusedIndicator); 640 } 641 642 /* mark as unused no matter what, return true if the state was in use before */ markAsUsedIDState643 bool markAsUsed() 644 { 645 auto currentGeneration = generation++; 646 return markAsUsed(currentGeneration); 647 } 648 649 /* mark as unused no matter what, return true if the state was in use before */ markAsUsedIDState650 bool markAsUsed(int64_t currentGeneration) 651 { 652 int64_t oldUsage = usageIndicator.exchange(currentGeneration); 653 return oldUsage != unusedIndicator; 654 } 655 656 /* We use this value to detect whether this state is in use. 657 For performance reasons we don't want to use a lock here, but that means 658 we need to be very careful when modifying this value. Modifications happen 659 from: 660 - one of the UDP or DoH 'client' threads receiving a query, selecting a backend 661 then picking one of the states associated to this backend (via the idOffset). 662 Most of the time this state should not be in use and usageIndicator is -1, but we 663 might not yet have received a response for the query previously associated to this 664 state, meaning that we will 'reuse' this state and erase the existing state. 665 If we ever receive a response for this state, it will be discarded. This is 666 mostly fine for UDP except that we still need to be careful in order to miss 667 the 'outstanding' counters, which should only be increased when we are picking 668 an empty state, and not when reusing ; 669 For DoH, though, we have dynamically allocated a DOHUnit object that needs to 670 be freed, as well as internal objects internals to libh2o. 671 - one of the UDP receiver threads receiving a response from a backend, picking 672 the corresponding state and sending the response to the client ; 673 - the 'healthcheck' thread scanning the states to actively discover timeouts, 674 mostly to keep some counters like the 'outstanding' one sane. 675 We previously based that logic on the origFD (FD on which the query was received, 676 and therefore from where the response should be sent) but this suffered from an 677 ABA problem since it was quite likely that a UDP 'client thread' would reset it to the 678 same value since we only have so much incoming sockets: 679 - 1/ 'client' thread gets a query and set origFD to its FD, say 5 ; 680 - 2/ 'receiver' thread gets a response, read the value of origFD to 5, check that the qname, 681 qtype and qclass match 682 - 3/ during that time the 'client' thread reuses the state, setting again origFD to 5 ; 683 - 4/ the 'receiver' thread uses compare_exchange_strong() to only replace the value if it's still 684 5, except it's not the same 5 anymore and it overrides a fresh state. 685 We now use a 32-bit unsigned counter instead, which is incremented every time the state is set, 686 wrapping around if necessary, and we set an atomic signed 64-bit value, so that we still have -1 687 when the state is unused and the value of our counter otherwise. 688 */ 689 std::atomic<int64_t> usageIndicator{unusedIndicator}; // set to unusedIndicator to indicate this state is empty // 8 690 std::atomic<uint32_t> generation{0}; // increased every time a state is used, to be able to detect an ABA issue // 4 691 ComboAddress origRemote; // 28 692 ComboAddress origDest; // 28 693 ComboAddress hopRemote; 694 ComboAddress hopLocal; 695 StopWatch sentTime; // 16 696 DNSName qname; // 80 697 std::shared_ptr<DNSCryptQuery> dnsCryptQuery{nullptr}; 698 boost::optional<boost::uuids::uuid> uniqueId; 699 boost::optional<Netmask> subnet{boost::none}; 700 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr}; 701 std::shared_ptr<QTag> qTag{nullptr}; 702 const ClientState* cs{nullptr}; 703 DOHUnit* du{nullptr}; 704 uint32_t cacheKey{0}; // 4 705 uint32_t cacheKeyNoECS{0}; // 4 706 #ifdef __SANITIZE_THREAD__ 707 std::atomic<uint16_t> age{0}; 708 #else 709 uint16_t age{0}; // 4 710 #endif 711 uint16_t qtype{0}; // 2 712 uint16_t qclass{0}; // 2 713 uint16_t origID{0}; // 2 714 uint16_t origFlags{0}; // 2 715 uint16_t cacheFlags{0}; // DNS flags as sent to the backend // 2 716 int origFD{-1}; 717 int delayMsec{0}; 718 boost::optional<uint32_t> tempFailureTTL; 719 bool ednsAdded{false}; 720 bool ecsAdded{false}; 721 bool skipCache{false}; 722 bool destHarvested{false}; // if true, origDest holds the original dest addr, otherwise the listening addr 723 bool dnssecOK{false}; 724 bool useZeroScope{false}; 725 }; 726 727 typedef std::unordered_map<string, unsigned int> QueryCountRecords; 728 typedef std::function<std::tuple<bool, string>(const DNSQuestion* dq)> QueryCountFilter; 729 struct QueryCount { QueryCountQueryCount730 QueryCount() 731 { 732 } ~QueryCountQueryCount733 ~QueryCount() 734 { 735 } 736 QueryCountRecords records; 737 QueryCountFilter filter; 738 ReadWriteLock queryLock; 739 bool enabled{false}; 740 }; 741 742 extern QueryCount g_qcount; 743 744 struct ClientState 745 { ClientStateClientState746 ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set<int>& cpus_): cpus(cpus_), local(local_), interface(itfName), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort) 747 { 748 } 749 750 std::set<int> cpus; 751 ComboAddress local; 752 std::shared_ptr<DNSCryptContext> dnscryptCtx{nullptr}; 753 std::shared_ptr<TLSFrontend> tlsFrontend{nullptr}; 754 std::shared_ptr<DOHFrontend> dohFrontend{nullptr}; 755 std::string interface; 756 stat_t queries{0}; 757 mutable stat_t responses{0}; 758 stat_t tcpDiedReadingQuery{0}; 759 stat_t tcpDiedSendingResponse{0}; 760 stat_t tcpGaveUp{0}; 761 stat_t tcpClientTimeouts{0}; 762 stat_t tcpDownstreamTimeouts{0}; 763 /* current number of connections to this frontend */ 764 stat_t tcpCurrentConnections{0}; 765 /* maximum number of concurrent connections to this frontend reached */ 766 stat_t tcpMaxConcurrentConnections{0}; 767 stat_t tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption 768 stat_t tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket 769 stat_t tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired) 770 stat_t tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one 771 stat_t tls10queries{0}; // valid DNS queries received via TLSv1.0 772 stat_t tls11queries{0}; // valid DNS queries received via TLSv1.1 773 stat_t tls12queries{0}; // valid DNS queries received via TLSv1.2 774 stat_t tls13queries{0}; // valid DNS queries received via TLSv1.3 775 stat_t tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version 776 pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0}; 777 /* in ms */ 778 pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0}; 779 size_t d_maxInFlightQueriesPerConn{1}; 780 size_t d_tcpConcurrentConnectionsLimit{0}; 781 int udpFD{-1}; 782 int tcpFD{-1}; 783 int tcpListenQueueSize{SOMAXCONN}; 784 int fastOpenQueueSize{0}; 785 bool muted{false}; 786 bool tcp; 787 bool reuseport; 788 bool ready{false}; 789 getSocketClientState790 int getSocket() const 791 { 792 return udpFD != -1 ? udpFD : tcpFD; 793 } 794 isUDPClientState795 bool isUDP() const 796 { 797 return udpFD != -1; 798 } 799 isTCPClientState800 bool isTCP() const 801 { 802 return udpFD == -1; 803 } 804 hasTLSClientState805 bool hasTLS() const 806 { 807 return tlsFrontend != nullptr || dohFrontend != nullptr; 808 } 809 getTypeClientState810 std::string getType() const 811 { 812 std::string result = udpFD != -1 ? "UDP" : "TCP"; 813 814 if (dohFrontend) { 815 result += " (DNS over HTTPS)"; 816 } 817 else if (tlsFrontend) { 818 result += " (DNS over TLS)"; 819 } 820 else if (dnscryptCtx) { 821 result += " (DNSCrypt)"; 822 } 823 824 return result; 825 } 826 827 shared_ptr<BPFFilter> d_filter; 828 detachFilterClientState829 void detachFilter() 830 { 831 if (d_filter) { 832 d_filter->removeSocket(getSocket()); 833 d_filter = nullptr; 834 } 835 } 836 attachFilterClientState837 void attachFilter(shared_ptr<BPFFilter> bpf) 838 { 839 detachFilter(); 840 841 bpf->addSocket(getSocket()); 842 d_filter = bpf; 843 } 844 updateTCPMetricsClientState845 void updateTCPMetrics(size_t nbQueries, uint64_t durationMs) 846 { 847 tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0); 848 tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0); 849 } 850 }; 851 852 class TCPClientCollection { 853 std::vector<int> d_tcpclientthreads; 854 stat_t d_numthreads{0}; 855 stat_t d_pos{0}; 856 stat_t d_queued{0}; 857 const uint64_t d_maxthreads{0}; 858 std::mutex d_mutex; 859 int d_singlePipe[2]; 860 const bool d_useSinglePipe; 861 public: 862 863 TCPClientCollection(size_t maxThreads, bool useSinglePipe=false); getThread()864 int getThread() 865 { 866 if (d_numthreads == 0) { 867 throw std::runtime_error("No TCP worker thread yet"); 868 } 869 870 uint64_t pos = d_pos++; 871 ++d_queued; 872 return d_tcpclientthreads.at(pos % d_numthreads); 873 } hasReachedMaxThreads() const874 bool hasReachedMaxThreads() const 875 { 876 return d_numthreads >= d_maxthreads; 877 } getThreadsCount() const878 uint64_t getThreadsCount() const 879 { 880 return d_numthreads; 881 } getQueuedCount() const882 uint64_t getQueuedCount() const 883 { 884 return d_queued; 885 } decrementQueuedCount()886 void decrementQueuedCount() 887 { 888 --d_queued; 889 } 890 void addTCPClientThread(); 891 }; 892 893 extern std::unique_ptr<TCPClientCollection> g_tcpclientthreads; 894 895 struct DownstreamState 896 { 897 typedef std::function<std::tuple<DNSName, uint16_t, uint16_t>(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t; 898 899 DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets, bool connect); DownstreamStateDownstreamState900 DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1, true) {} 901 ~DownstreamState(); 902 903 boost::uuids::uuid id; 904 std::vector<unsigned int> hashes; 905 mutable ReadWriteLock d_lock; 906 std::vector<int> sockets; 907 const std::string sourceItfName; 908 std::mutex socketsLock; 909 std::mutex connectLock; 910 std::unique_ptr<FDMultiplexer> mplexer{nullptr}; 911 std::shared_ptr<TLSCtx> d_tlsCtx{nullptr}; 912 std::thread tid; 913 const ComboAddress remote; 914 QPSLimiter qps; 915 vector<IDState> idStates; 916 const ComboAddress sourceAddr; 917 checkfunc_t checkFunction; 918 DNSName checkName{"a.root-servers.net."}; 919 QType checkType{QType::A}; 920 uint16_t checkClass{QClass::IN}; 921 std::atomic<uint64_t> idOffset{0}; 922 stat_t sendErrors{0}; 923 stat_t outstanding{0}; 924 stat_t reuseds{0}; 925 stat_t queries{0}; 926 stat_t responses{0}; 927 struct { 928 stat_t sendErrors{0}; 929 stat_t reuseds{0}; 930 stat_t queries{0}; 931 } prev; 932 stat_t tcpDiedSendingQuery{0}; 933 stat_t tcpDiedReadingResponse{0}; 934 stat_t tcpGaveUp{0}; 935 stat_t tcpReadTimeouts{0}; 936 stat_t tcpWriteTimeouts{0}; 937 stat_t tcpConnectTimeouts{0}; 938 /* current number of connections to this backend */ 939 stat_t tcpCurrentConnections{0}; 940 /* maximum number of concurrent connections to this backend reached */ 941 stat_t tcpMaxConcurrentConnections{0}; 942 stat_t tcpReusedConnections{0}; 943 stat_t tcpNewConnections{0}; 944 pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0}; 945 /* in ms */ 946 pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0}; 947 size_t socketsOffset{0}; 948 size_t d_maxInFlightQueriesPerConn{1}; 949 size_t d_tcpConcurrentConnectionsLimit{0}; 950 pdns::stat_t_trait<double> queryLoad{0.0}; 951 pdns::stat_t_trait<double> dropRate{0.0}; 952 double latencyUsec{0.0}; 953 int order{1}; 954 int weight{1}; 955 int tcpConnectTimeout{5}; 956 int tcpRecvTimeout{30}; 957 int tcpSendTimeout{30}; 958 unsigned int checkInterval{1}; 959 unsigned int lastCheck{0}; 960 const unsigned int sourceItf{0}; 961 uint16_t retries{5}; 962 uint16_t xpfRRCode{0}; 963 uint16_t checkTimeout{1000}; /* in milliseconds */ 964 uint8_t currentCheckFailures{0}; 965 uint8_t consecutiveSuccessfulChecks{0}; 966 uint8_t maxCheckFailures{1}; 967 uint8_t minRiseSuccesses{1}; 968 StopWatch sw; 969 set<string> pools; 970 enum class Availability { Up, Down, Auto} availability{Availability::Auto}; 971 bool mustResolve{false}; 972 bool upStatus{false}; 973 bool useECS{false}; 974 bool useProxyProtocol{false}; 975 bool setCD{false}; 976 bool disableZeroScope{false}; 977 std::atomic<bool> connected{false}; 978 std::atomic_flag threadStarted; 979 bool tcpFastOpen{false}; 980 bool ipBindAddrNoPort{true}; 981 bool reconnectOnUp{false}; 982 isUpDownstreamState983 bool isUp() const 984 { 985 if(availability == Availability::Down) 986 return false; 987 if(availability == Availability::Up) 988 return true; 989 return upStatus; 990 } setUpDownstreamState991 void setUp() { availability = Availability::Up; } setDownDownstreamState992 void setDown() { availability = Availability::Down; } setAutoDownstreamState993 void setAuto() { availability = Availability::Auto; } getNameDownstreamState994 const string& getName() const { 995 return name; 996 } getNameWithAddrDownstreamState997 const string& getNameWithAddr() const { 998 return nameWithAddr; 999 } setNameDownstreamState1000 void setName(const std::string& newName) 1001 { 1002 name = newName; 1003 nameWithAddr = newName.empty() ? remote.toStringWithPort() : (name + " (" + remote.toStringWithPort()+ ")"); 1004 } 1005 getStatusDownstreamState1006 string getStatus() const 1007 { 1008 string status; 1009 if(availability == DownstreamState::Availability::Up) 1010 status = "UP"; 1011 else if(availability == DownstreamState::Availability::Down) 1012 status = "DOWN"; 1013 else 1014 status = (upStatus ? "up" : "down"); 1015 return status; 1016 } 1017 bool reconnect(); 1018 void hash(); 1019 void setId(const boost::uuids::uuid& newId); 1020 void setWeight(int newWeight); 1021 void stop(); isStoppedDownstreamState1022 bool isStopped() const 1023 { 1024 return d_stopped; 1025 } 1026 updateTCPMetricsDownstreamState1027 void updateTCPMetrics(size_t nbQueries, uint64_t durationMs) 1028 { 1029 tcpAvgQueriesPerConnection = (99.0 * tcpAvgQueriesPerConnection / 100.0) + (nbQueries / 100.0); 1030 tcpAvgConnectionDuration = (99.0 * tcpAvgConnectionDuration / 100.0) + (durationMs / 100.0); 1031 } 1032 incQueriesCountDownstreamState1033 void incQueriesCount() 1034 { 1035 ++queries; 1036 qps.addHit(); 1037 } 1038 1039 private: 1040 std::string name; 1041 std::string nameWithAddr; 1042 bool d_stopped{false}; 1043 }; 1044 using servers_t =vector<std::shared_ptr<DownstreamState>>; 1045 1046 void responderThread(std::shared_ptr<DownstreamState> state); 1047 extern std::mutex g_luamutex; 1048 extern LuaContext g_lua; 1049 extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex 1050 1051 class DNSRule 1052 { 1053 public: ~DNSRule()1054 virtual ~DNSRule () 1055 { 1056 } 1057 virtual bool matches(const DNSQuestion* dq) const =0; 1058 virtual string toString() const = 0; 1059 mutable stat_t d_matches{0}; 1060 }; 1061 1062 struct ServerPool 1063 { ServerPoolServerPool1064 ServerPool(): d_servers(std::make_shared<ServerPolicy::NumberedServerVector>()) 1065 { 1066 } 1067 ~ServerPoolServerPool1068 ~ServerPool() 1069 { 1070 } 1071 getCacheServerPool1072 const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; }; 1073 getECSServerPool1074 bool getECS() const 1075 { 1076 return d_useECS; 1077 } 1078 setECSServerPool1079 void setECS(bool useECS) 1080 { 1081 d_useECS = useECS; 1082 } 1083 1084 std::shared_ptr<DNSDistPacketCache> packetCache{nullptr}; 1085 std::shared_ptr<ServerPolicy> policy{nullptr}; 1086 countServersServerPool1087 size_t countServers(bool upOnly) 1088 { 1089 size_t count = 0; 1090 ReadLock rl(&d_lock); 1091 for (const auto& server : *d_servers) { 1092 if (!upOnly || std::get<1>(server)->isUp() ) { 1093 count++; 1094 } 1095 } 1096 return count; 1097 } 1098 getServersServerPool1099 const std::shared_ptr<ServerPolicy::NumberedServerVector> getServers() 1100 { 1101 std::shared_ptr<ServerPolicy::NumberedServerVector> result; 1102 { 1103 ReadLock rl(&d_lock); 1104 result = d_servers; 1105 } 1106 return result; 1107 } 1108 addServerServerPool1109 void addServer(shared_ptr<DownstreamState>& server) 1110 { 1111 WriteLock wl(&d_lock); 1112 /* we can't update the content of the shared pointer directly even when holding the lock, 1113 as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */ 1114 unsigned int count = static_cast<unsigned int>(d_servers->size()); 1115 auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers); 1116 newServers->push_back(make_pair(++count, server)); 1117 /* we need to reorder based on the server 'order' */ 1118 std::stable_sort(newServers->begin(), newServers->end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) { 1119 return a.second->order < b.second->order; 1120 }); 1121 /* and now we need to renumber for Lua (custom policies) */ 1122 size_t idx = 1; 1123 for (auto& serv : *newServers) { 1124 serv.first = idx++; 1125 } 1126 d_servers = newServers; 1127 } 1128 removeServerServerPool1129 void removeServer(shared_ptr<DownstreamState>& server) 1130 { 1131 WriteLock wl(&d_lock); 1132 /* we can't update the content of the shared pointer directly even when holding the lock, 1133 as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */ 1134 auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*d_servers); 1135 size_t idx = 1; 1136 bool found = false; 1137 for (auto it = newServers->begin(); it != newServers->end();) { 1138 if (found) { 1139 /* we need to renumber the servers placed 1140 after the removed one, for Lua (custom policies) */ 1141 it->first = idx++; 1142 it++; 1143 } 1144 else if (it->second == server) { 1145 it = newServers->erase(it); 1146 found = true; 1147 } else { 1148 idx++; 1149 it++; 1150 } 1151 } 1152 d_servers = newServers; 1153 } 1154 1155 private: 1156 std::shared_ptr<ServerPolicy::NumberedServerVector> d_servers; 1157 ReadWriteLock d_lock; 1158 bool d_useECS{false}; 1159 }; 1160 1161 struct CarbonConfig 1162 { 1163 ComboAddress server; 1164 std::string namespace_name; 1165 std::string ourname; 1166 std::string instance_name; 1167 unsigned int interval; 1168 }; 1169 1170 enum ednsHeaderFlags { 1171 EDNS_HEADER_FLAG_NONE = 0, 1172 EDNS_HEADER_FLAG_DO = 32768 1173 }; 1174 1175 struct DNSDistRuleAction 1176 { 1177 std::shared_ptr<DNSRule> d_rule; 1178 std::shared_ptr<DNSAction> d_action; 1179 std::string d_name; 1180 boost::uuids::uuid d_id; 1181 uint64_t d_creationOrder; 1182 }; 1183 1184 struct DNSDistResponseRuleAction 1185 { 1186 std::shared_ptr<DNSRule> d_rule; 1187 std::shared_ptr<DNSResponseAction> d_action; 1188 std::string d_name; 1189 boost::uuids::uuid d_id; 1190 uint64_t d_creationOrder; 1191 }; 1192 1193 extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT; 1194 extern DNSAction::Action g_dynBlockAction; 1195 1196 extern GlobalStateHolder<vector<CarbonConfig> > g_carbon; 1197 extern GlobalStateHolder<ServerPolicy> g_policy; 1198 extern GlobalStateHolder<servers_t> g_dstates; 1199 extern GlobalStateHolder<pools_t> g_pools; 1200 extern GlobalStateHolder<vector<DNSDistRuleAction> > g_ruleactions; 1201 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_respruleactions; 1202 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_cachehitrespruleactions; 1203 extern GlobalStateHolder<vector<DNSDistResponseRuleAction> > g_selfansweredrespruleactions; 1204 extern GlobalStateHolder<NetmaskGroup> g_ACL; 1205 1206 extern ComboAddress g_serverControl; // not changed during runtime 1207 1208 extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals; 1209 extern std::vector<shared_ptr<DOHFrontend>> g_dohlocals; 1210 extern std::vector<std::unique_ptr<ClientState>> g_frontends; 1211 extern bool g_truncateTC; 1212 extern bool g_fixupCase; 1213 extern int g_tcpRecvTimeout; 1214 extern int g_tcpSendTimeout; 1215 extern int g_udpTimeout; 1216 extern uint16_t g_maxOutstanding; 1217 extern std::atomic<bool> g_configurationDone; 1218 extern boost::optional<uint64_t> g_maxTCPClientThreads; 1219 extern uint64_t g_maxTCPQueuedConnections; 1220 extern size_t g_maxTCPQueriesPerConn; 1221 extern size_t g_maxTCPConnectionDuration; 1222 extern size_t g_maxTCPConnectionsPerClient; 1223 extern size_t g_tcpInternalPipeBufferSize; 1224 extern pdns::stat16_t g_cacheCleaningDelay; 1225 extern pdns::stat16_t g_cacheCleaningPercentage; 1226 extern uint32_t g_staleCacheEntriesTTL; 1227 extern bool g_apiReadWrite; 1228 extern std::string g_apiConfigDirectory; 1229 extern bool g_servFailOnNoPolicy; 1230 extern bool g_useTCPSinglePipe; 1231 extern uint16_t g_downstreamTCPCleanupInterval; 1232 extern size_t g_udpVectorSize; 1233 extern bool g_allowEmptyResponse; 1234 1235 extern shared_ptr<BPFFilter> g_defaultBPFFilter; 1236 extern std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters; 1237 1238 struct LocalHolders 1239 { LocalHoldersLocalHolders1240 LocalHolders(): acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(g_ruleactions.getLocal()), cacheHitRespRuleactions(g_cachehitrespruleactions.getLocal()), selfAnsweredRespRuleactions(g_selfansweredrespruleactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal()) 1241 { 1242 } 1243 1244 LocalStateHolder<NetmaskGroup> acl; 1245 LocalStateHolder<ServerPolicy> policy; 1246 LocalStateHolder<vector<DNSDistRuleAction> > ruleactions; 1247 LocalStateHolder<vector<DNSDistResponseRuleAction> > cacheHitRespRuleactions; 1248 LocalStateHolder<vector<DNSDistResponseRuleAction> > selfAnsweredRespRuleactions; 1249 LocalStateHolder<servers_t> servers; 1250 LocalStateHolder<NetmaskTree<DynBlock> > dynNMGBlock; 1251 LocalStateHolder<SuffixMatchTree<DynBlock> > dynSMTBlock; 1252 LocalStateHolder<pools_t> pools; 1253 }; 1254 1255 vector<std::function<void(void)>> setupLua(bool client, const std::string& config); 1256 1257 void tcpAcceptorThread(ClientState* p); 1258 void setMaxCachedTCPConnectionsPerDownstream(size_t max); 1259 1260 #ifdef HAVE_DNS_OVER_HTTPS 1261 void dohThread(ClientState* cs); 1262 #endif /* HAVE_DNS_OVER_HTTPS */ 1263 1264 void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects 1265 void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls 1266 bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect 1267 void resetLuaSideEffect(); // reset to indeterminate state 1268 1269 bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength); 1270 bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted); 1271 bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop); 1272 1273 bool checkQueryHeaders(const struct dnsheader* dh); 1274 1275 extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals; 1276 int handleDNSCryptQuery(PacketBuffer& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, PacketBuffer& response); 1277 bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp); 1278 1279 uint16_t getRandomDNSID(); 1280 1281 #include "dnsdist-snmp.hh" 1282 1283 extern bool g_snmpEnabled; 1284 extern bool g_snmpTrapsEnabled; 1285 extern DNSDistSNMPAgent* g_snmpAgent; 1286 extern bool g_addEDNSToSelfGeneratedResponses; 1287 1288 extern std::set<std::string> g_capabilitiesToRetain; 1289 static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value 1290 static const size_t s_maxPacketCacheEntrySize{4096}; // don't cache responses larger than this value 1291 1292 enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend }; 1293 ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend); 1294 1295 DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP); 1296 void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname); 1297 1298 int pickBackendSocketForSending(std::shared_ptr<DownstreamState>& state); 1299 ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck = false); 1300