From 7ddda493c0c5370902148e20c579dd2d213f0a69 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 9 Oct 2018 06:02:36 +0200 Subject: [PATCH] ndb/dnstcp: restrict DNS zone transfers to clients listed as dnsslave= initial idea from Steve Simon, but doesnt require reverse lookup of the callers ip address. --- sys/man/8/ndb | 8 +++++- sys/src/cmd/ndb/dnstcp.c | 56 +++++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/sys/man/8/ndb b/sys/man/8/ndb index c80e13f19..af4df056d 100644 --- a/sys/man/8/ndb +++ b/sys/man/8/ndb @@ -77,7 +77,7 @@ query, ipquery, mkhash, mkdb, mkhosts, cs, csquery, dns, dnstcp, dnsquery, dnsde .br .B ndb/dnstcp [ -.B -rR +.B -arR ] [ .B -f .I dbfile @@ -664,6 +664,12 @@ Recursion is disabled by .BR -R ; acting as a pure resolver is enabled by .BR -r . +Unless the +.B -a +flag is provided, clients requesting DNS zone transfer must be listed +with a +.B dnsslave +attribute for the relevant domain. If .I conn-dir is provided, it is assumed to be a directory within diff --git a/sys/src/cmd/ndb/dnstcp.c b/sys/src/cmd/ndb/dnstcp.c index 4ba125983..3db74e155 100644 --- a/sys/src/cmd/ndb/dnstcp.c +++ b/sys/src/cmd/ndb/dnstcp.c @@ -3,6 +3,8 @@ */ #include #include +#include +#include #include #include "dns.h" @@ -10,6 +12,7 @@ Cfg cfg; char *caller = ""; char *dbfile; +int anyone; int debug; char *logfile = "dns"; int maxage = 60*60; @@ -17,20 +20,19 @@ char mntpt[Maxpath]; int needrefresh; ulong now; vlong nowns; -int testing; int traceactivity; char *zonerefreshprogram; static int readmsg(int, uchar*, int); static void reply(int, DNSmsg*, Request*); -static void dnzone(DNSmsg*, DNSmsg*, Request*); +static void dnzone(DNSmsg*, DNSmsg*, Request*, uchar*); static void getcaller(char*); static void refreshmain(char*); void usage(void) { - fprint(2, "usage: %s [-rR] [-f ndb-file] [-x netmtpt] [conndir]\n", argv0); + fprint(2, "usage: %s [-adrR] [-f ndbfile] [-x netmtpt] [conndir]\n", argv0); exits("usage"); } @@ -44,9 +46,11 @@ main(int argc, char *argv[]) volatile DNSmsg reqmsg, repmsg; volatile Request req; - alarm(2*60*1000); cfg.cachedb = 1; ARGBEGIN{ + case 'a': + anyone++; + break; case 'd': debug++; break; @@ -82,6 +86,7 @@ main(int argc, char *argv[]) memset(callip, 0, sizeof callip); parseip(callip, caller); + srand(truerand()); db2cache(1); memset(&req, 0, sizeof req); @@ -89,6 +94,8 @@ main(int argc, char *argv[]) req.isslave = 0; procsetname("main loop"); + alarm(10*1000); + /* loop on requests */ for(;; putactivity(0)){ now = time(nil); @@ -135,7 +142,7 @@ main(int argc, char *argv[]) /* loop through each question */ while(reqmsg.qd) if(reqmsg.qd->type == Taxfr) - dnzone(&reqmsg, &repmsg, &req); + dnzone(&reqmsg, &repmsg, &req, callip); else { dnserver(&reqmsg, &repmsg, &req, callip, rcode); reply(1, &repmsg, &req); @@ -244,8 +251,37 @@ inzone(DN *dp, char *name, int namelen, int depth) return 1; } +static Server* +findserver(uchar *srcip, Server *servers, Request *req) +{ + uchar ip[IPaddrlen]; + RR *list, *rp; + + for(; servers != nil; servers = servers->next){ + if(strcmp(ipattr(servers->name), "ip") == 0){ + if(parseip(ip, servers->name) == -1) + continue; + if(ipcmp(srcip, ip) == 0) + return servers; + continue; + } + list = dnresolve(servers->name, Cin, Ta, req, nil, 0, 1, 1, nil); + rrcat(&list, dnresolve(servers->name, Cin, Taaaa, req, nil, 0, 1, 1, nil)); + for(rp = list; rp != nil; rp = rp->next){ + if(parseip(ip, rp->ip->name) == -1) + continue; + if(ipcmp(srcip, ip) == 0) + break; + } + rrfreelist(list); + if(rp != nil) + return servers; + } + return nil; +} + static void -dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req) +dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip) { DN *dp, *ndp; RR r, *rp; @@ -264,8 +300,14 @@ dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req) /* send the soa */ repp->an = rrlookup(dp, Tsoa, NOneg); reply(1, repp, req); - if(repp->an == 0) + if(repp->an == nil) goto out; + if(!anyone && !myip(srcip) && findserver(srcip, repp->an->soa->slaves, req) == nil){ + dnslog("dnstcp: %I axfr %s - not a dnsslave", srcip, dp->name); + rrfreelist(repp->an); + repp->an = nil; + goto out; + } rrfreelist(repp->an); repp->an = nil;