ref: 7ddda493c0c5370902148e20c579dd2d213f0a69
parent: 679a253931804caf4de436c5cdab8d34f178d779
author: cinap_lenrek <[email protected]>
date: Tue Oct 9 02:02:36 EDT 2018
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.
--- a/sys/man/8/ndb
+++ b/sys/man/8/ndb
@@ -77,7 +77,7 @@
.br
.B ndb/dnstcp
[
-.B -rR
+.B -arR
] [
.B -f
.I dbfile
@@ -664,6 +664,12 @@
.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
--- a/sys/src/cmd/ndb/dnstcp.c
+++ b/sys/src/cmd/ndb/dnstcp.c
@@ -3,6 +3,8 @@
*/
#include <u.h>
#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
#include <ip.h>
#include "dns.h"
@@ -10,6 +12,7 @@
char *caller = "";
char *dbfile;
+int anyone;
int debug;
char *logfile = "dns";
int maxage = 60*60;
@@ -17,13 +20,12 @@
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*);
@@ -30,7 +32,7 @@
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 @@
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 @@
memset(callip, 0, sizeof callip);
parseip(callip, caller);
+ srand(truerand());
db2cache(1);
memset(&req, 0, sizeof req);
@@ -89,6 +94,8 @@
req.isslave = 0;
procsetname("main loop");
+ alarm(10*1000);
+
/* loop on requests */
for(;; putactivity(0)){
now = time(nil);
@@ -135,7 +142,7 @@
/* 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 @@
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 @@
/* 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;