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:
parent
679a253931
commit
7ddda493c0
2 changed files with 56 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue