From 0d5f0a9f318a94d9ea11cd72d83ea53d15c0ca64 Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Fri, 14 Apr 2006 12:35:19 +0000 Subject: [PATCH] make anti-spoofing measures question and not ip address specific, make them tunable git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@700 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- pdns/dnspbench.cc | 2 +- pdns/lwres.cc | 2 +- pdns/lwres.hh | 2 +- pdns/pdns_recursor.cc | 37 ++++++++++++++++++++++++++++++++----- pdns/rec_channel_rec.cc | 2 ++ pdns/syncres.hh | 13 ++++++++++--- 6 files changed, 47 insertions(+), 11 deletions(-) diff --git a/pdns/dnspbench.cc b/pdns/dnspbench.cc index bf164dc35..b81030602 100644 --- a/pdns/dnspbench.cc +++ b/pdns/dnspbench.cc @@ -46,7 +46,7 @@ try Socket s(InterNetwork, Datagram); - IPEndpoint rem("127.0.0.1",1232), loc("213.156.2.1", 53); + IPEndpoint rem("10.0.1.6",35515), loc("213.156.2.1", 53); s.bind(loc); vector vpacket; diff --git a/pdns/lwres.cc b/pdns/lwres.cc index bddda1d2b..93a18b042 100644 --- a/pdns/lwres.cc +++ b/pdns/lwres.cc @@ -88,7 +88,7 @@ int LWRes::asyncresolve(uint32_t ip, const string& domain, int type, bool doTCP, // sleep until we see an answer to this, interface to mtasker - ret=arecvfrom(reinterpret_cast(d_buf), d_bufsize-1,0,(struct sockaddr*)(&toaddr), &addrlen, &d_len, pw.getHeader()->id); + ret=arecvfrom(reinterpret_cast(d_buf), d_bufsize-1,0,(struct sockaddr*)(&toaddr), &addrlen, &d_len, pw.getHeader()->id, domain); } else { Socket s(InterNetwork, Stream); diff --git a/pdns/lwres.hh b/pdns/lwres.hh index 1514c9e9a..66d999072 100644 --- a/pdns/lwres.hh +++ b/pdns/lwres.hh @@ -44,7 +44,7 @@ using namespace std; int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int addrlen, int id); -int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id); +int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id, const string& domain); class LWResException : public AhuException { diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 95cde0532..418d51afe 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -172,10 +172,15 @@ int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int a } // -1 is error, 0 is timeout, 1 is success -int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id) +int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id, const string& domain) { + static optional nearMissLimit; + if(!nearMissLimit) + nearMissLimit=::arg().asNum("spoof-nearmiss-max"); + PacketID pident; pident.id=id; + pident.domain=domain; memcpy(&pident.remote, toaddr, sizeof(pident.remote)); string packet; @@ -183,8 +188,9 @@ int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility:: if(ret > 0) { *d_len=packet.size(); memcpy(data,packet.c_str(),min(len,*d_len)); - if(pident.nearMisses > 100) { - L< *nearMissLimit) { + L< "<<*nearMissLimit<<") bogus answers for '"< end) + break; + ret.append(pos, labellen); + ret.append(1,'.'); + pos+=labellen; + } + if(ret.empty()) + ret="."; + return ret; +} + int main(int argc, char **argv) { reportBasicTypes(); @@ -778,6 +803,7 @@ int main(int argc, char **argv) ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12"; ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0"; ::arg().set("fork", "If set, fork the daemon for possible double performance")="no"; + ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20"; ::arg().setCmd("help","Provide a helpful message"); L.toConsole(Logger::Warning); @@ -998,15 +1024,16 @@ int main(int argc, char **argv) if(dh.qr && dh.qdcount) { pident.remote=fromaddr; pident.id=dh.id; + pident.domain=questionExpand(data, d_len); string packet; packet.assign(data, d_len); if(!MT->sendEvent(pident, &packet)) { if(logCommonErrors) - L<d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) { - if(!memcmp(&mthread->key.remote.sin_addr, &pident.remote.sin_addr, sizeof(pident.remote.sin_addr))) { + if(!memcmp(&mthread->key.remote.sin_addr, &pident.remote.sin_addr, sizeof(pident.remote.sin_addr)) && !strcasecmp(pident.domain.c_str(), mthread->key.domain.c_str())) { mthread->key.nearMisses++; } } diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index c1d675e26..a9f1a8d12 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -153,6 +153,8 @@ RecursorControlParser::RecursorControlParser() addGetStat("answers-slow", &g_stats.answersSlow); addGetStat("qa-latency", &g_stats.avgLatencyUsec); + addGetStat("unexpected-packets", &g_stats.unexpectedCount); + addGetStat("spoof-prevents", &g_stats.spoofCount); addGetStat("negcache-entries", boost::bind(&SyncRes::negcache_t::size, ref(SyncRes::s_negcache))); addGetStat("throttle-entries", boost::bind(&SyncRes::throttle_t::size, ref(SyncRes::s_throttle))); diff --git a/pdns/syncres.hh b/pdns/syncres.hh index e224db358..07ae33468 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -322,6 +322,7 @@ struct PacketID uint16_t id; // wait for a specific id/remote pair struct sockaddr_in remote; // this is the remote + string domain; // this is the question Socket* sock; // or wait for an event on a TCP fd int inNeeded; // if this is set, we'll read until inNeeded bytes are read @@ -336,9 +337,14 @@ struct PacketID { int ourSock= sock ? sock->getHandle() : 0; int bSock = b.sock ? b.sock->getHandle() : 0; - return - tie(id, remote.sin_addr.s_addr, remote.sin_port, ourSock) < - tie(b.id, b.remote.sin_addr.s_addr, b.remote.sin_port, bSock); + if( tie(id, remote.sin_addr.s_addr, remote.sin_port, ourSock) < + tie(b.id, b.remote.sin_addr.s_addr, b.remote.sin_port, bSock)) + return true; + if( tie(id, remote.sin_addr.s_addr, remote.sin_port, ourSock) > + tie(b.id, b.remote.sin_addr.s_addr, b.remote.sin_port, bSock)) + return false; + + return strcasecmp(domain.c_str(), b.domain.c_str()) < 0; } }; @@ -361,6 +367,7 @@ struct RecursorStats uint64_t clientParseError; uint64_t serverParseError; uint64_t unexpectedCount; + uint64_t spoofCount; }; extern RecursorStats g_stats; -- 2.40.0