ref: f67c4c85232b032f1825de30f4f943789257984e
parent: eb8fe8137b742646e9f3402149596eb8da62cc72
author: cinap_lenrek <[email protected]>
date: Wed Nov 1 17:57:08 EDT 2023
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.
--- a/sys/man/8/ndb
+++ b/sys/man/8/ndb
@@ -57,7 +57,7 @@
.br
.B ndb/dns
[
-.B -FnrR
+.B -FnrLR
] [
.B -a
.I maxage
@@ -400,9 +400,18 @@
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
@@ -409,7 +418,8 @@
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
--- a/sys/src/cmd/ndb/dblookup.c
+++ b/sys/src/cmd/ndb/dblookup.c
@@ -873,6 +873,23 @@
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)
{
--- a/sys/src/cmd/ndb/dns.c
+++ b/sys/src/cmd/ndb/dns.c
@@ -92,7 +92,7 @@
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 @@
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 @@
/* 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);
--- a/sys/src/cmd/ndb/dns.h
+++ b/sys/src/cmd/ndb/dns.h
@@ -376,11 +376,12 @@
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 @@
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 */
--- a/sys/src/cmd/ndb/dnserver.c
+++ b/sys/src/cmd/ndb/dnserver.c
@@ -19,8 +19,6 @@
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 @@
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 @@
setercode(repp, Runimplimented);
return;
}
-
if(repp->qd->owner->class != Cin){
if(debug)
dnslog("%d: server: unsupported class %d from %I",
@@ -62,31 +59,31 @@
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);
+ 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);
- /*
- * get the answer if we can, in *repp
- */
- neg = doextquery(repp, req, recurse? Recurse: Dontrecurse);
+ /* 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);
- /* authority is transitive */
- if(myarea || (repp->an && repp->an->auth))
- repp->flags |= Fauth;
-
- /* 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
*/