From: root Date: Thu, 19 May 2022 20:21:02 +0000 (-0400) Subject: forward EDNS Client Subnet option during ALIAS processing X-Git-Tag: auth-4.9.0-alpha1^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=50e2abc0749983dab472176d6e4e8db80acc6e85;p=thirdparty%2Fpdns.git forward EDNS Client Subnet option during ALIAS processing typo --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index c429ce6831..7c8a7c5dc4 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -660,6 +660,8 @@ stubquery_SOURCES = \ dnsparser.cc \ dnsrecords.cc \ dnswriter.cc \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ iputils.cc \ logger.cc \ misc.cc \ @@ -792,6 +794,8 @@ ixplore_SOURCES = \ dnsrecords.cc \ dnssecinfra.cc \ dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ gss_context.cc gss_context.hh \ iputils.cc \ ixfr.cc ixfr.hh \ diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc index a9ec83529b..a69d9f1edb 100644 --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@ -184,7 +184,6 @@ void DNSPacket::addRecord(DNSZoneRecord&& rr) } d_dedup.insert(hash); } - d_rrs.push_back(std::move(rr)); } @@ -350,9 +349,8 @@ void DNSPacket::wrapup(bool throwsOnTruncation) try { uint8_t maxScopeMask=0; for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) { - // cerr<<"during wrapup, content=["<content<<"]"<scopeMask); - + pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place); pos->dr.getContent()->toPacket(pw); if(pw.size() + optsize > (d_tcp ? 65535 : getMaxReplyLen())) { @@ -374,6 +372,8 @@ void DNSPacket::wrapup(bool throwsOnTruncation) if(d_haveednssubnet) { EDNSSubnetOpts eso = d_eso; + // use the scopeMask from the resolver, if it is greater - issue #5469 + maxScopeMask = max(maxScopeMask, eso.scope.getBits()); eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask); string opt = makeEDNSSubnetOptsString(eso); @@ -598,9 +598,9 @@ try */ d_ednsRawPacketSizeLimit=edo.d_packetsize; d_maxreplylen=std::min(std::max(static_cast(512), edo.d_packetsize), s_udpTruncationThreshold); -// cerr< d_rrs; // 8 std::unordered_set d_dedup; string d_rawpacket; // this is where everything lives 8 - EDNSSubnetOpts d_eso; EDNSCookiesOpt d_eco; int d_maxreplylen{0}; diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc index a25691c916..3c5c07636c 100644 --- a/pdns/dnsproxy.cc +++ b/pdns/dnsproxy.cc @@ -37,6 +37,8 @@ #include "stubresolver.hh" #include "arguments.hh" #include "threadname.hh" +#include "ednsoptions.hh" +#include "ednssubnet.hh" extern StatBag S; @@ -91,14 +93,23 @@ void DNSProxy::go() //! look up qname target with r->qtype, plonk it in the answer section of 'r' with name aname bool DNSProxy::completePacket(std::unique_ptr& r, const DNSName& target,const DNSName& aname, const uint8_t scopeMask) { + string ECSOptionStr; + + if (r->hasEDNSSubnet()) + { + DLOG(g_log<<"dnsproxy::completePacket: Parsed edns source: "<d_eso.source.toString()<<", scope: "<d_eso.scope.toString()<<", family = "<d_eso.scope.getNetwork().sin4.sin_family<d_eso); + DLOG(g_log<<"from dnsproxy::completePacket: Creating ECS option string "<d_tcp) { vector ips; int ret1 = 0, ret2 = 0; - + // rip out edns info here, pass it to the stubDoResolve if(r->qtype == QType::A || r->qtype == QType::ANY) - ret1 = stubDoResolve(target, QType::A, ips); + ret1 = stubDoResolve(target, QType::A, ips, r->hasEDNSSubnet() ? &r->d_eso : nullptr); if(r->qtype == QType::AAAA || r->qtype == QType::ANY) - ret2 = stubDoResolve(target, QType::AAAA, ips); + ret2 = stubDoResolve(target, QType::AAAA, ips, r->hasEDNSSubnet() ? &r->d_eso : nullptr); if(ret1 != RCode::NoError || ret2 != RCode::NoError) { g_log<& r, const DNSName& targ DNSPacketWriter pw(packet, target, qtype); pw.getHeader()->rd=true; pw.getHeader()->id=id ^ d_xor; + // Add EDNS Subnet if the client sent one - issue #5469 + if (!ECSOptionStr.empty()) { + DLOG(g_log<<"from dnsproxy::completePacket: adding ECS option string to packet options "<second.id; memcpy(buffer,&d,sizeof(d)); // commit spoofed id - DNSPacket p(false),q(false); + DNSPacket p(false); p.parse(buffer,(size_t)len); - q.parse(buffer,(size_t)len); if(p.qtype.getCode() != i->second.qtype || p.qdomain != i->second.qname) { g_log<second.complete->d_eso = p.d_eso; + DLOG(g_log<<"from dnsproxy::mainLoop: updated EDNS options from resolver EDNS source: "<second.complete->d_eso.source.toString()<<" EDNS scope: "<second.complete->d_eso.scope.toString()<first.d_place-1<<" "<first.d_label<<" " << DNSRecordContent::NumberToType(j->first.d_type)<<" "<first.d_content->getZoneRepresentation()<second.qtype || (i->second.qtype == QType::ANY && (answer.first.d_type == QType::A || answer.first.d_type == QType::AAAA))) { @@ -267,6 +289,7 @@ void DNSProxy::mainloop() } } } + i->second.complete->setRcode(mdp.d_header.rcode); } else { g_log<second.aname<<" ALIAS "<second.qname<<" over UDP, "<second.qtype).toString()<<"-record query returned "<source = Netmask(address, esow.sourceMask); /* 'address' has more bits set (potentially) than scopeMask. This leads to odd looking netmasks that promise more precision than they have. For this reason we truncate the address to scopeMask bits */ diff --git a/pdns/iputils.hh b/pdns/iputils.hh index ade4c82a30..5810bf1f0a 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -261,6 +261,16 @@ union ComboAddress { return ret; } + bool isValid() const + { + char host[1024]; + int retval = 0; + if(sin4.sin_family && !(retval = getnameinfo(reinterpret_cast(this), getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST))) + return true; + else + return false; + } + string toString() const { char host[1024]; @@ -595,6 +605,11 @@ public: return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr)); } + bool isValid() + { + return d_network.isValid(); + } + string toString() const { return d_network.toStringNoInterface()+"/"+std::to_string((unsigned int)d_bits); diff --git a/pdns/stubresolver.cc b/pdns/stubresolver.cc index af5f2ea096..fc45b599f2 100644 --- a/pdns/stubresolver.cc +++ b/pdns/stubresolver.cc @@ -15,6 +15,8 @@ #include "namespaces.hh" #include "statbag.hh" #include "stubresolver.hh" +#include "ednsoptions.hh" +#include "ednssubnet.hh" #define LOCAL_RESOLV_CONF_PATH "/etc/resolv.conf" // don't stat() for local resolv.conf more than once every INTERVAL secs. @@ -103,7 +105,7 @@ void stubParseResolveConf() } // s_resolversForStub contains the ComboAddresses that are used to resolve the -int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret) +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, EDNSSubnetOpts* d_eso) { // ensure resolver gets always configured if (!s_stubResolvConfigured) { @@ -122,6 +124,16 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r DNSPacketWriter pw(packet, qname, qtype); pw.getHeader()->id=dns_random_uint16(); pw.getHeader()->rd=1; + + if(d_eso != nullptr) + { + // pass along EDNS subnet from client if given - issue #5469 + string origECSOptionStr = makeEDNSSubnetOptsString(*d_eso); + DNSPacketWriter::optvect_t opts; + opts.emplace_back(EDNSOptionCode::ECS, origECSOptionStr); + pw.addOpt(512, 0, 0, opts); + pw.commit(); + } string queryNameType = qname.toString() + "|" + QType(qtype).toString(); string msg ="Doing stub resolving for '" + queryNameType + "', using resolvers: "; @@ -171,9 +183,9 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r return RCode::ServFail; } -int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret) { +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, EDNSSubnetOpts* d_eso) { vector ret2; - int res = stubDoResolve(qname, qtype, ret2); + int res = stubDoResolve(qname, qtype, ret2, d_eso); for (const auto &r : ret2) { ret.push_back(r.dr); } diff --git a/pdns/stubresolver.hh b/pdns/stubresolver.hh index 1cb94c8d42..88f79f4cdf 100644 --- a/pdns/stubresolver.hh +++ b/pdns/stubresolver.hh @@ -22,8 +22,9 @@ #pragma once #include "namespaces.hh" #include "dnsparser.hh" +#include "ednssubnet.hh" void stubParseResolveConf(); bool resolversDefined(); -int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret); -int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret); +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, EDNSSubnetOpts* d_eso = nullptr); +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, EDNSSubnetOpts* d_eso = nullptr);