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.
This commit is contained in:
cinap_lenrek 2018-10-09 06:02:36 +02:00
parent 679a253931
commit 7ddda493c0
2 changed files with 56 additions and 8 deletions

View file

@ -77,7 +77,7 @@ query, ipquery, mkhash, mkdb, mkhosts, cs, csquery, dns, dnstcp, dnsquery, dnsde
.br .br
.B ndb/dnstcp .B ndb/dnstcp
[ [
.B -rR .B -arR
] [ ] [
.B -f .B -f
.I dbfile .I dbfile
@ -664,6 +664,12 @@ Recursion is disabled by
.BR -R ; .BR -R ;
acting as a pure resolver is enabled by acting as a pure resolver is enabled by
.BR -r . .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 If
.I conn-dir .I conn-dir
is provided, it is assumed to be a directory within is provided, it is assumed to be a directory within

View file

@ -3,6 +3,8 @@
*/ */
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include <bio.h>
#include <ndb.h>
#include <ip.h> #include <ip.h>
#include "dns.h" #include "dns.h"
@ -10,6 +12,7 @@ Cfg cfg;
char *caller = ""; char *caller = "";
char *dbfile; char *dbfile;
int anyone;
int debug; int debug;
char *logfile = "dns"; char *logfile = "dns";
int maxage = 60*60; int maxage = 60*60;
@ -17,20 +20,19 @@ char mntpt[Maxpath];
int needrefresh; int needrefresh;
ulong now; ulong now;
vlong nowns; vlong nowns;
int testing;
int traceactivity; int traceactivity;
char *zonerefreshprogram; char *zonerefreshprogram;
static int readmsg(int, uchar*, int); static int readmsg(int, uchar*, int);
static void reply(int, DNSmsg*, Request*); 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 getcaller(char*);
static void refreshmain(char*); static void refreshmain(char*);
void void
usage(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"); exits("usage");
} }
@ -44,9 +46,11 @@ main(int argc, char *argv[])
volatile DNSmsg reqmsg, repmsg; volatile DNSmsg reqmsg, repmsg;
volatile Request req; volatile Request req;
alarm(2*60*1000);
cfg.cachedb = 1; cfg.cachedb = 1;
ARGBEGIN{ ARGBEGIN{
case 'a':
anyone++;
break;
case 'd': case 'd':
debug++; debug++;
break; break;
@ -82,6 +86,7 @@ main(int argc, char *argv[])
memset(callip, 0, sizeof callip); memset(callip, 0, sizeof callip);
parseip(callip, caller); parseip(callip, caller);
srand(truerand());
db2cache(1); db2cache(1);
memset(&req, 0, sizeof req); memset(&req, 0, sizeof req);
@ -89,6 +94,8 @@ main(int argc, char *argv[])
req.isslave = 0; req.isslave = 0;
procsetname("main loop"); procsetname("main loop");
alarm(10*1000);
/* loop on requests */ /* loop on requests */
for(;; putactivity(0)){ for(;; putactivity(0)){
now = time(nil); now = time(nil);
@ -135,7 +142,7 @@ main(int argc, char *argv[])
/* loop through each question */ /* loop through each question */
while(reqmsg.qd) while(reqmsg.qd)
if(reqmsg.qd->type == Taxfr) if(reqmsg.qd->type == Taxfr)
dnzone(&reqmsg, &repmsg, &req); dnzone(&reqmsg, &repmsg, &req, callip);
else { else {
dnserver(&reqmsg, &repmsg, &req, callip, rcode); dnserver(&reqmsg, &repmsg, &req, callip, rcode);
reply(1, &repmsg, &req); reply(1, &repmsg, &req);
@ -244,8 +251,37 @@ inzone(DN *dp, char *name, int namelen, int depth)
return 1; 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 static void
dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req) dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip)
{ {
DN *dp, *ndp; DN *dp, *ndp;
RR r, *rp; RR r, *rp;
@ -264,8 +300,14 @@ dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req)
/* send the soa */ /* send the soa */
repp->an = rrlookup(dp, Tsoa, NOneg); repp->an = rrlookup(dp, Tsoa, NOneg);
reply(1, repp, req); reply(1, repp, req);
if(repp->an == 0) if(repp->an == nil)
goto out; 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); rrfreelist(repp->an);
repp->an = nil; repp->an = nil;