diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-11-01 21:57:08 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-11-01 21:57:08 +0000 |
commit | f67c4c85232b032f1825de30f4f943789257984e (patch) | |
tree | 91832ab797c16d3ed4d395aaf68af65c1453a3e1 | |
parent | eb8fe8137b742646e9f3402149596eb8da62cc72 (diff) |
ndb/dns: add -L flag for local-recursive server
One might think that specifying the listen address
is enougth to prevent running a open resolver,
but this does not work for global IPv6 addresses.
The -L flag allows answering recursive queries
ONLY for IP addresses that are directly reachable
on a interface.
-rw-r--r-- | sys/man/8/ndb | 16 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dblookup.c | 17 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dns.c | 10 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dns.h | 14 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnserver.c | 47 |
5 files changed, 68 insertions, 36 deletions
diff --git a/sys/man/8/ndb b/sys/man/8/ndb index e2b6826ec..5b1524c98 100644 --- a/sys/man/8/ndb +++ b/sys/man/8/ndb @@ -57,7 +57,7 @@ query, ipquery, mkhash, mkdb, mkhosts, cs, csquery, dns, dnsquery, dnsdebug, dns .br .B ndb/dns [ -.B -FnrR +.B -FnrLR ] [ .B -a .I maxage @@ -400,16 +400,26 @@ otherwise optional attributes name DNS servers to forward queries to. .TP .B -R -ignore the `recursive' bit on incoming requests. +ignore the `recursive' bit on all incoming requests. Do not complete lookups on behalf of remote systems. .TP +.B -L +ignore the `recursive' bit on incoming requests +from non-local IP addresses. +IP addresses are local when they are contained +within the network prefix of an interface. +This allows running as a authoritative server +while also serving recursive queries for systems +on local networks. +.TP .B -s also answer domain requests sent to IP .I addrs on UDP/TCP port 53. If no IP .I addrs -are given, listen on any interface on network mount point +are given, +listen on any interface on network mount point .IR netmtpt . .TP .B -x diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index 16edcb252..258ccd1a1 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -873,6 +873,23 @@ myip(uchar *ip) return 0; } +int +localip(uchar *ip) +{ + Ipifc *ifc; + + qlock(&ipifclock); + for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ + if(ipremoteonifc(ifc, ip) != nil){ + qunlock(&ipifclock); + return 1; + } + } + qunlock(&ipifclock); + + return 0; +} + static void addlocaldnsserver(DN *dp, int class, char *addr, int i) { diff --git a/sys/src/cmd/ndb/dns.c b/sys/src/cmd/ndb/dns.c index 66a1cc651..65e1ab846 100644 --- a/sys/src/cmd/ndb/dns.c +++ b/sys/src/cmd/ndb/dns.c @@ -92,7 +92,7 @@ static char *respond(Job*, Mfile*, RR*, char*, int, int); void usage(void) { - fprint(2, "usage: %s [-FnrR] [-a maxage] [-f ndb-file] [-N target] " + fprint(2, "usage: %s [-FnrLR] [-a maxage] [-f ndb-file] [-N target] " "[-x netmtpt] [-s [addrs...]]\n", argv0); exits("usage"); } @@ -129,8 +129,13 @@ main(int argc, char *argv[]) case 'r': cfg.resolver = 1; break; + case 'L': + cfg.localrecursive = 1; + cfg.nonrecursive = 0; + break; case 'R': cfg.nonrecursive = 1; + cfg.localrecursive = 0; break; case 's': cfg.serve = 1; /* serve network */ @@ -151,9 +156,10 @@ main(int argc, char *argv[]) /* start syslog before we fork */ fmtinstall('F', fcallfmt); dninit(); - dnslog("starting %s%s%sdns %s%son %s", + dnslog("starting %s%s%s%sdns %s%son %s", (cfg.cachedb? "caching ": ""), (cfg.nonrecursive? "non-recursive ": ""), + (cfg.localrecursive? "local-recursive ": ""), (cfg.serve? "server ": ""), (cfg.justforw? "forwarding-only ": ""), (cfg.resolver? "resolver ": ""), mntpt); diff --git a/sys/src/cmd/ndb/dns.h b/sys/src/cmd/ndb/dns.h index 5dad56b05..e6fbc7e8d 100644 --- a/sys/src/cmd/ndb/dns.h +++ b/sys/src/cmd/ndb/dns.h @@ -376,11 +376,12 @@ struct Area typedef struct Cfg Cfg; struct Cfg { - int cachedb; - int resolver; - int justforw; /* flag: pure resolver, just forward queries */ - int serve; /* flag: serve tcp udp queries */ - int nonrecursive; + char cachedb; + char resolver; + char justforw; /* flag: pure resolver, just forward queries */ + char serve; /* flag: serve tcp udp queries */ + char nonrecursive; /* flag: never serve recursive queries */ + char localrecursive; /* flag: serve recursive queries for local ip's */ }; /* query stats */ @@ -496,7 +497,8 @@ int baddelegation(RR*, RR*, uchar*); RR* dblookup(char*, int, int, int, int); RR* dnsservers(int); RR* domainlist(int); -int myip(uchar *ip); +int myip(uchar *); +int localip(uchar *); int opendatabase(void); /* dns.c */ diff --git a/sys/src/cmd/ndb/dnserver.c b/sys/src/cmd/ndb/dnserver.c index 630825792..f55d38af1 100644 --- a/sys/src/cmd/ndb/dnserver.c +++ b/sys/src/cmd/ndb/dnserver.c @@ -19,8 +19,6 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) repp->id = reqp->id; repp->flags = Fresp | (reqp->flags & Omask); - if(!cfg.nonrecursive && (reqp->flags & Omask) == Oquery) - repp->flags |= Fcanrec; setercode(repp, Rok); /* move one question from reqp to repp */ @@ -29,7 +27,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) rp->next = nil; repp->qd = rp; - if(rcode){ + if(rcode != Rok || (reqp->flags & Omask) != Oquery){ dnslog("%d: server: response code %d %s, req from %I", req->id, rcode, rcname(rcode), srcip); /* provide feedback to clients who send us trash */ @@ -43,7 +41,6 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) setercode(repp, Runimplimented); return; } - if(repp->qd->owner->class != Cin){ if(debug) dnslog("%d: server: unsupported class %d from %I", @@ -62,31 +59,31 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode) setercode(repp, Runimplimented); return; } - } - if(myarea == nil && cfg.nonrecursive) { - /* we don't recurse and we're not authoritative */ - repp->flags &= ~(Fauth|Fcanrec); - neg = nil; + repp->flags |= Fauth; + neg = doextquery(repp, req, Dontrecurse); } else { - int recurse = (reqp->flags & Frecurse) && (repp->flags & Fcanrec); - - /* - * get the answer if we can, in *repp - */ - neg = doextquery(repp, req, recurse? Recurse: Dontrecurse); - - /* authority is transitive */ - if(myarea || (repp->an && repp->an->auth)) - repp->flags |= Fauth; + if(cfg.nonrecursive + || cfg.localrecursive && !localip(srcip)){ + /* we don't recurse and we're not authoritative */ + neg = nil; + } else { + repp->flags |= Fcanrec; + if(reqp->flags & Frecurse){ + neg = doextquery(repp, req, Recurse); + + /* pass on error codes */ + if(repp->an == nil && repp->qd->owner->rr == nil){ + repp->flags |= Fauth; + setercode(repp, repp->qd->owner->respcode); + } + } else + neg = doextquery(repp, req, Dontrecurse); - /* pass on error codes */ - if(recurse && repp->an == nil && repp->qd->owner->rr == nil){ - repp->flags |= Fauth; - setercode(repp, repp->qd->owner->respcode); + /* authority is transitive */ + if(repp->an && repp->an->auth) + repp->flags |= Fauth; } - } - if(myarea == nil){ /* * add name server if we know */ |