mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
resolver: per service, defaultresolve, fakeresolve or sysresolve
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Each service resolves names the way the last of defaultresolve (the name servers in force, configured or the system's with the hosts file), fakeresolve (127.0.0.2) and sysresolve (the C library) read before it says; the last one in the configuration also applies outside services. defaultresolve is the new command, and the default. The name servers and the hosts file no longer depend on the mode: nserver lines, or the system's, are always in force, so dnspr keeps forwarding; with fakeresolve it does not, as before. fakeresolver moves to common.c, which the standalone services link without resolve.c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
994526dbc4
commit
3d20e1104e
@ -498,14 +498,6 @@ user), Reply-Message. Use <b>authcache</b> to speedup
|
||||
authentication. RADIUS feature is currently
|
||||
experimental.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>sysresolve</b>
|
||||
<br>
|
||||
Names are resolved by the system routines for name
|
||||
resolution (the C library), as without <b>nserver</b> before
|
||||
the system's name servers became the default; the hosts file
|
||||
is not imported. <b>nserver</b> lines, if any, are still used
|
||||
by <b>dnspr</b> to forward queries. Of <b>sysresolve</b> and
|
||||
<b>fakeresolve</b> the last one given applies.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>nserver</b>
|
||||
<i><ipaddr></i>[:<i>port</i>][/<i>tcp</i>] <br>
|
||||
@ -516,9 +508,7 @@ has to be enclosed in square brackets: <br>
|
||||
<b>nserver 1.1.1.1</b> <br>
|
||||
<b>nserver [2001:4860:4860::8844]</b> <br>
|
||||
<b>nserver [2001:4860:4860::8844]:5353/tcp</b> <br>
|
||||
If none is specified (and there is no <b>fakeresolve</b> or
|
||||
<b>sysresolve</b>),
|
||||
the system's name servers are used: up to 3 from
|
||||
If none is specified, the system's name servers are used: up to 3 from
|
||||
<i>/etc/resolv.conf</i>, on Windows from the registry (those
|
||||
set for the system, those set for an interface, then those
|
||||
DHCP gave). Names in the hosts file (<i>/etc/hosts</i>, on
|
||||
@ -567,12 +557,39 @@ together with <b>dialer</b> command to set up UDL for
|
||||
dialing.</p>
|
||||
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>defaultresolve</b>
|
||||
<br>
|
||||
Names are resolved by the name servers in force: those of
|
||||
<b>nserver</b> lines, or the system's ones with the hosts file
|
||||
by default (see <b>nserver</b>). This is the default.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>sysresolve</b>
|
||||
<br>
|
||||
Names are resolved by the system routines for name
|
||||
resolution (the C library), as without <b>nserver</b> before
|
||||
the system's name servers became the default: <b>nsrecord</b>
|
||||
is not consulted. <b>dnspr</b> still forwards queries to the
|
||||
name servers in force.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>fakeresolve</b>
|
||||
<br>
|
||||
All names are resolved to the 127.0.0.2 address. Useful if
|
||||
all requests are redirected to a parent proxy with
|
||||
<b>http</b>, <b>socks4+</b>, <b>connect+</b> or
|
||||
<b>socks5+</b>.</p>
|
||||
<b>socks5+</b>. <b>dnspr</b> does not forward queries.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em">Of
|
||||
<b>defaultresolve</b>, <b>sysresolve</b> and
|
||||
<b>fakeresolve</b>, the last one given before a service
|
||||
applies to it, so services can resolve names differently:
|
||||
<br>
|
||||
<b>fakeresolve</b> <br>
|
||||
<b>proxy -p3128</b> <br>
|
||||
<b>defaultresolve</b> <br>
|
||||
<b>socks -p1080</b> <br>
|
||||
The last one in the configuration also applies to names
|
||||
resolved outside a service, such as those in the
|
||||
configuration itself, once it is loaded.</p>
|
||||
|
||||
<p style="margin-left:9%; margin-top: 1em"><b>dialer</b>
|
||||
<i><progname></i> <br>
|
||||
|
||||
@ -555,7 +555,7 @@ An IPv6 address has to be enclosed in square brackets:
|
||||
.br
|
||||
\fBnserver [2001:4860:4860::8844]:5353/tcp\fR
|
||||
.br
|
||||
If none is specified (and there is no \fBfakeresolve\fR or \fBsysresolve\fR), the system's name
|
||||
If none is specified, the system's name
|
||||
servers are used: up to 3 from \fI/etc/resolv.conf\fR, on Windows from the
|
||||
registry (those set for the system, those set for an interface, then those
|
||||
DHCP gave). Names in the hosts file (\fI/etc/hosts\fR, on Windows
|
||||
@ -600,20 +600,43 @@ are never consulted. A static record takes precedence over the hosts file. If 0.
|
||||
is used as a hostaddr host will never resolve, it can be used to
|
||||
blacklist something.
|
||||
|
||||
.br
|
||||
.B defaultresolve
|
||||
.br
|
||||
Names are resolved by the name servers in force: those of \fBnserver\fR
|
||||
lines, or the system's ones with the hosts file by default (see
|
||||
\fBnserver\fR). This is the default.
|
||||
|
||||
.br
|
||||
.B sysresolve
|
||||
.br
|
||||
Names are resolved by the system routines for name resolution (the C
|
||||
library), as without \fBnserver\fR before the system's name servers became
|
||||
the default; the hosts file is not imported. \fBnserver\fR lines, if any, are
|
||||
still used by \fBdnspr\fR to forward queries. Of \fBsysresolve\fR and
|
||||
\fBfakeresolve\fR the last one given applies.
|
||||
the default: \fBnsrecord\fR is not consulted. \fBdnspr\fR still forwards
|
||||
queries to the name servers in force.
|
||||
|
||||
.br
|
||||
.B fakeresolve
|
||||
.br
|
||||
All names are resolved to the 127.0.0.2 address. Useful if all requests are
|
||||
redirected to a parent proxy with \fBhttp\fR, \fBsocks4+\fR, \fBconnect+\fR or \fBsocks5+\fR.
|
||||
\fBdnspr\fR does not forward queries.
|
||||
|
||||
.br
|
||||
Of \fBdefaultresolve\fR, \fBsysresolve\fR and \fBfakeresolve\fR, the last
|
||||
one given before a service applies to it, so services can resolve names
|
||||
differently:
|
||||
.br
|
||||
\fBfakeresolve\fR
|
||||
.br
|
||||
\fBproxy -p3128\fR
|
||||
.br
|
||||
\fBdefaultresolve\fR
|
||||
.br
|
||||
\fBsocks -p1080\fR
|
||||
.br
|
||||
The last one in the configuration also applies to names resolved outside
|
||||
a service, such as those in the configuration itself, once it is loaded.
|
||||
|
||||
.br
|
||||
.BR dialer
|
||||
|
||||
@ -594,8 +594,8 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
|
||||
/* numbered before it is read, as a reload numbers the new one */
|
||||
conf->version++;
|
||||
res = readconfig(fp);
|
||||
if(!res) confdnscommit(conf);
|
||||
resolvfunc = conf->resolvfunc;
|
||||
if(!res) confdnscommit();
|
||||
resolvmode = conf->resolvmode;
|
||||
|
||||
/* readconfig() names the failing line, which an exit status would cut
|
||||
to 8 bits: a failed configuration exits with 1 */
|
||||
|
||||
50
src/common.c
50
src/common.c
@ -570,7 +570,7 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
|
||||
if(sp){
|
||||
port = atoi(sp+1);
|
||||
}
|
||||
ret = !getip46(param->srv->family, param->hostname, (struct sockaddr *)¶m->req);
|
||||
ret = !getip46m(param->srv->resolvmode, param->srv->family, param->hostname, (struct sockaddr *)¶m->req);
|
||||
if(se) *se = ']';
|
||||
if(sp) *sp = ':';
|
||||
*SAPORT(¶m->req) = htons(port);
|
||||
@ -863,7 +863,36 @@ int scanaddr(const unsigned char *s, uint32_t * ip, uint32_t * mask) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The default resolver: name servers, configured or the system's, or NULL
|
||||
for the system routines. resolvmode is the configuration's, for names
|
||||
resolved outside a service; each service has its own. */
|
||||
RESOLVFUNC resolvfunc = NULL;
|
||||
int resolvmode = RESOLVE_DEFAULT;
|
||||
|
||||
uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){
|
||||
if(af == AF_INET6){
|
||||
memset(value, 0, 16);
|
||||
value[15] = 2;
|
||||
}
|
||||
else {
|
||||
value[0] = 127;
|
||||
value[1] = 0;
|
||||
value[2] = 0;
|
||||
value[3] = 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The resolver of a mode, NULL for the system routines */
|
||||
static RESOLVFUNC moderesolver(int mode){
|
||||
switch(mode){
|
||||
case RESOLVE_FAKE:
|
||||
return fakeresolver;
|
||||
case RESOLVE_SYSTEM:
|
||||
return NULL;
|
||||
}
|
||||
return resolvfunc;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
_3proxy_mutex_t gethostbyname_mutex;
|
||||
int ghbn_init = 0;
|
||||
@ -887,7 +916,7 @@ struct hostent * my_gethostbyname(char *name, char *buf, struct hostent *hp){
|
||||
#endif
|
||||
|
||||
#ifdef NOIPV6
|
||||
uint32_t getip(unsigned char *name){
|
||||
static uint32_t getipm(int mode, unsigned char *name){
|
||||
uint32_t retval;
|
||||
int i;
|
||||
int ndots = 0;
|
||||
@ -913,7 +942,7 @@ uint32_t getip(unsigned char *name){
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
if((tmpresolv=resolvfunc)){
|
||||
if((tmpresolv=moderesolver(mode))){
|
||||
return (*tmpresolv)(AF_INET, name, (unsigned char *)&retval)?retval:0;
|
||||
}
|
||||
#ifndef NOSTDRESOLVE
|
||||
@ -937,6 +966,10 @@ uint32_t getip(unsigned char *name){
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint32_t getip(unsigned char *name){
|
||||
return getipm(resolvmode, name);
|
||||
}
|
||||
#endif
|
||||
|
||||
int afdetect(unsigned char *name){
|
||||
@ -971,7 +1004,8 @@ int afdetect(unsigned char *name){
|
||||
|
||||
}
|
||||
|
||||
uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
|
||||
/* A name resolved the way a mode says: a service's names with its own */
|
||||
uint32_t getip46m(int mode, int family, unsigned char *name, struct sockaddr *sa){
|
||||
#ifndef NOIPV6
|
||||
int detect;
|
||||
#ifndef NOSTDRESOLVE
|
||||
@ -984,7 +1018,7 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
|
||||
family = 4;
|
||||
#else
|
||||
((struct sockaddr_in *)sa)->sin_family = AF_INET;
|
||||
return (((struct sockaddr_in *)sa)->sin_addr.s_addr = getip(name))? AF_INET:0;
|
||||
return (((struct sockaddr_in *)sa)->sin_addr.s_addr = getipm(mode, name))? AF_INET:0;
|
||||
#endif
|
||||
#ifndef NOIPV6
|
||||
}
|
||||
@ -996,7 +1030,7 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
|
||||
return inet_pton(*SAFAMILY(sa), (char *)name, SAADDR(sa))>0? *SAFAMILY(sa) : 0;
|
||||
}
|
||||
|
||||
if((tmpresolv = resolvfunc)){
|
||||
if((tmpresolv = moderesolver(mode))){
|
||||
int f = (family == 6 || family == 64)?AF_INET6:AF_INET;
|
||||
*SAFAMILY(sa) = f;
|
||||
if(tmpresolv(f, name, SAADDR(sa))) return f;
|
||||
@ -1030,6 +1064,10 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
|
||||
return getip46m(resolvmode, family, name, sa);
|
||||
}
|
||||
|
||||
int hascap(const unsigned char *line, const char *cap){
|
||||
int len = (int)strlen(cap);
|
||||
for(; *line; line++) if(!strncasecmp((char *)line, cap, len)) return 1;
|
||||
|
||||
32
src/conf.c
32
src/conf.c
@ -376,7 +376,7 @@ static int h_proxy(int argc, unsigned char ** argv){
|
||||
childdef.service = S_DNSPR;
|
||||
childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n -Fip - fake: answer all A queries with this IP\n";
|
||||
#ifndef NOIPV6
|
||||
if(noresolver() || conf->resolvfunc == fakeresolver){
|
||||
if(noresolver() || conf->resolvmode == RESOLVE_FAKE){
|
||||
fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
|
||||
}
|
||||
#endif
|
||||
@ -741,8 +741,6 @@ static int h_flushusers(int argc, unsigned char **argv){
|
||||
force (the process has one list) once it is committed */
|
||||
static struct nserver cfgns[MAXNSERVERS];
|
||||
static int cfgnsn = 0;
|
||||
/* sysresolve: names resolved by the system routines */
|
||||
static int cfgsysresolve = 0;
|
||||
|
||||
static int h_nserver(int argc, unsigned char **argv){
|
||||
char *str;
|
||||
@ -760,20 +758,20 @@ static int h_nserver(int argc, unsigned char **argv){
|
||||
cfgnsn++;
|
||||
}
|
||||
else fprintf(stderr, "[line %d] Warning: only %d name servers are used, nserver ignored\n", linenum, MAXNSERVERS);
|
||||
conf->resolvfunc = myresolver;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The configuration's name servers, or the system's in their place */
|
||||
void confdnscommit(struct extparam *c){
|
||||
sysdnsapply(c, cfgns, cfgnsn, cfgsysresolve);
|
||||
void confdnscommit(void){
|
||||
sysdnsapply(cfgns, cfgnsn);
|
||||
}
|
||||
|
||||
/* Whether names would be resolved slowly: by the C library, or by name
|
||||
servers, the system's taken by default, without a cache */
|
||||
static int noresolver(void){
|
||||
if(cfgsysresolve || (!conf->resolvfunc && !sysdnscount())) return 1;
|
||||
return (!conf->resolvfunc || conf->resolvfunc == myresolver) && !dns_table.poolsize;
|
||||
if(conf->resolvmode == RESOLVE_FAKE) return 0;
|
||||
if(conf->resolvmode == RESOLVE_SYSTEM || (!cfgnsn && !sysdnscount())) return 1;
|
||||
return !dns_table.poolsize;
|
||||
}
|
||||
|
||||
static int h_authnserver(int argc, unsigned char **argv){
|
||||
@ -790,14 +788,20 @@ static int h_authnserver(int argc, unsigned char **argv){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* defaultresolve, fakeresolve, sysresolve: for the services after it,
|
||||
and, the last one, for names resolved outside a service */
|
||||
static int h_defaultresolve(int argc, unsigned char **argv){
|
||||
conf->resolvmode = RESOLVE_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h_fakeresolve(int argc, unsigned char **argv){
|
||||
conf->resolvfunc = fakeresolver;
|
||||
cfgsysresolve = 0;
|
||||
conf->resolvmode = RESOLVE_FAKE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h_sysresolve(int argc, unsigned char **argv){
|
||||
cfgsysresolve = 1;
|
||||
conf->resolvmode = RESOLVE_SYSTEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2153,6 +2157,7 @@ struct commands commandhandlers[]={
|
||||
{NULL, "maxconn", h_maxconn, 2, 2},
|
||||
{NULL, "flush", h_flush, 1, 1},
|
||||
{NULL, "nserver", h_nserver, 2, 2},
|
||||
{NULL, "defaultresolve", h_defaultresolve, 1, 1},
|
||||
{NULL, "fakeresolve", h_fakeresolve, 1, 1},
|
||||
{NULL, "sysresolve", h_sysresolve, 1, 1},
|
||||
{NULL, "nscache", h_nscache, 2, 2},
|
||||
@ -2543,7 +2548,6 @@ void confbegin(void){
|
||||
char * args[] = {"auth", "iponly", NULL};
|
||||
|
||||
cfgnsn = 0;
|
||||
cfgsysresolve = 0;
|
||||
|
||||
h_auth(2, (unsigned char **)args);
|
||||
}
|
||||
@ -2675,8 +2679,8 @@ int reload (void){
|
||||
_3proxy_mutex_lock(&confref_mutex);
|
||||
runconf = new;
|
||||
_3proxy_mutex_unlock(&confref_mutex);
|
||||
confdnscommit(new);
|
||||
resolvfunc = new->resolvfunc;
|
||||
confdnscommit();
|
||||
resolvmode = new->resolvmode;
|
||||
/* the new services take over the listening sockets of the old ones on
|
||||
the same addresses, which then stop accepting, and start */
|
||||
for(d = deferred; d; d = d->next) mainclaim(d->service);
|
||||
|
||||
@ -296,7 +296,7 @@ static int dnsprfirst(struct udploop *u, struct udpsession *ss, unsigned char *q
|
||||
}
|
||||
}
|
||||
q->ip = ip;
|
||||
if(ip || !numservers){
|
||||
if(ip || !numservers || param->srv->resolvmode == RESOLVE_FAKE){
|
||||
param->res = dnsanswer(u, param, q, buf, len);
|
||||
free(buf);
|
||||
return 1;
|
||||
|
||||
@ -712,6 +712,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
||||
srv->backlog = conf->backlog;
|
||||
srv->stacksize = conf->stacksize;
|
||||
srv->config = conf;
|
||||
srv->resolvmode = conf->resolvmode;
|
||||
memcpy(srv->timeouts, conf->timeouts, sizeof(srv->timeouts));
|
||||
srv->filtermaxsize = conf->filtermaxsize;
|
||||
srv->parentretries = conf->parentretries;
|
||||
|
||||
@ -205,6 +205,7 @@ size_t threadstacksize(int extra);
|
||||
#endif
|
||||
|
||||
extern RESOLVFUNC resolvfunc;
|
||||
extern int resolvmode;
|
||||
|
||||
extern int wday;
|
||||
extern time_t basetime;
|
||||
@ -351,6 +352,7 @@ int scanaddr(const unsigned char *s, uint32_t * ip, uint32_t * mask);
|
||||
int myinet_ntop(int af, void *src, char *dst, socklen_t size);
|
||||
uint32_t getip(unsigned char *name);
|
||||
uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa);
|
||||
uint32_t getip46m(int mode, int family, unsigned char *name, struct sockaddr *sa);
|
||||
int afdetect(unsigned char *name);
|
||||
uint32_t myresolver(int, unsigned char *, unsigned char *);
|
||||
uint32_t fakeresolver (int, unsigned char *, unsigned char*);
|
||||
@ -435,9 +437,9 @@ int nscacheresolv(int af, unsigned char *name, unsigned char *value, uint32_t *t
|
||||
void setnservers(const struct nserver *ns, int n);
|
||||
void sysdnsinit(void);
|
||||
int sysdnscount(void);
|
||||
void sysdnsapply(struct extparam *c, const struct nserver *ns, int n, int sysresolve);
|
||||
void sysdnsapply(const struct nserver *ns, int n);
|
||||
void sysdnscheck(void);
|
||||
void confdnscommit(struct extparam *c);
|
||||
void confdnscommit(void);
|
||||
uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth);
|
||||
|
||||
struct ace * copyacl (struct ace *ac);
|
||||
|
||||
@ -268,18 +268,18 @@ void applyportranges(struct clientparam * param, struct ace * acentry){
|
||||
}
|
||||
}
|
||||
|
||||
static void chainaddr(struct chain * cur, PROXYSOCKADDRTYPE * sa){
|
||||
static void chainaddr(struct clientparam * param, struct chain * cur, PROXYSOCKADDRTYPE * sa){
|
||||
PROXYSOCKADDRTYPE fresh;
|
||||
|
||||
*sa = cur->addr;
|
||||
if(resolvfunc != myresolver) return;
|
||||
if(param->srv->resolvmode != RESOLVE_DEFAULT || resolvfunc != myresolver) return;
|
||||
if(!cur->exthost || SAISNULL(&cur->addr)) return;
|
||||
#ifdef WITH_UN
|
||||
if(*SAFAMILY(&cur->addr) == AF_UNIX) return;
|
||||
#endif
|
||||
if(afdetect(cur->exthost) != -1) return;
|
||||
memset(&fresh, 0, sizeof(fresh));
|
||||
if(!getip46(46, cur->exthost, (struct sockaddr *)&fresh)) return;
|
||||
if(!getip46m(RESOLVE_DEFAULT, 46, cur->exthost, (struct sockaddr *)&fresh)) return;
|
||||
*SAPORT(&fresh) = *SAPORT(&cur->addr);
|
||||
*sa = fresh;
|
||||
}
|
||||
@ -430,12 +430,12 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
}
|
||||
else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) {
|
||||
uint16_t port = *SAPORT(¶m->sinsr);
|
||||
chainaddr(cur, ¶m->sinsr);
|
||||
chainaddr(param, cur, ¶m->sinsr);
|
||||
*SAPORT(¶m->sinsr) = port;
|
||||
}
|
||||
else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(¶m->sinsr) = *SAPORT(&cur->addr);
|
||||
else {
|
||||
chainaddr(cur, ¶m->sinsr);
|
||||
chainaddr(param, cur, ¶m->sinsr);
|
||||
}
|
||||
if(param->operation == UDPASSOC){
|
||||
SOCKET s;
|
||||
@ -468,7 +468,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
else {
|
||||
PROXYSOCKADDRTYPE next;
|
||||
|
||||
chainaddr(cur, &next);
|
||||
chainaddr(param, cur, &next);
|
||||
res = (redir)?clientnegotiate(redir, param, (struct sockaddr *)&next, cur->exthost):0;
|
||||
if(res) {
|
||||
parentfail(param, cur);
|
||||
|
||||
@ -255,23 +255,8 @@ uint32_t myresolver(int af, unsigned char * name, unsigned char * value){
|
||||
return udpresolve(af, name, value, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){
|
||||
memset(value, 0, af == AF_INET6? 16 : 4);
|
||||
if(af == AF_INET6){
|
||||
memset(value, 0, 16);
|
||||
value[15] = 2;
|
||||
}
|
||||
else {
|
||||
value[0] = 127;
|
||||
value[1] = 0;
|
||||
value[2] = 0;
|
||||
value[3] = 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The system's name servers and hosts file, the default for a configuration
|
||||
without nserver (or fakeresolve): read at start, before a chroot can hide
|
||||
without nserver: read at start, before a chroot can hide
|
||||
them, and checked from the main loop for changes, which apply while the
|
||||
default is in force. Hosts entries have tables of their own, emptied when
|
||||
the default is not in force. Only the main thread works on this. */
|
||||
@ -583,34 +568,26 @@ int sysdnscount(void){
|
||||
return sysdns.n;
|
||||
}
|
||||
|
||||
/* A configuration committed: the name servers of its nserver lines, else,
|
||||
with nothing else to resolve names, the system's and its hosts file, read
|
||||
again. Until then those in force stay. With sysresolve the system
|
||||
routines resolve names, nserver lines left to dnspr. */
|
||||
void sysdnsapply(struct extparam *c, const struct nserver *ns, int n, int sysresolve){
|
||||
/* A configuration committed: the name servers of its nserver lines, else
|
||||
the system's and its hosts file, read again; with none the system
|
||||
routines are the default. Until then those in force stay. */
|
||||
void sysdnsapply(const struct nserver *ns, int n){
|
||||
sysdns.active = 0;
|
||||
if(sysresolve){
|
||||
c->resolvfunc = NULL;
|
||||
setnservers(ns, n);
|
||||
hostsremove();
|
||||
return;
|
||||
}
|
||||
if(n){
|
||||
setnservers(ns, n);
|
||||
hostsremove();
|
||||
return;
|
||||
}
|
||||
if(c->resolvfunc){
|
||||
setnservers(NULL, 0);
|
||||
hostsremove();
|
||||
resolvfunc = myresolver;
|
||||
return;
|
||||
}
|
||||
sysdnsread();
|
||||
sysdns.checked = curtime;
|
||||
sysdns.active = 1;
|
||||
setnservers(sysdns.ns, sysdns.n);
|
||||
if(!sysdns.n) return; /* the C library, as before */
|
||||
c->resolvfunc = myresolver;
|
||||
if(!sysdns.n){ /* the C library, as before */
|
||||
resolvfunc = NULL;
|
||||
return;
|
||||
}
|
||||
resolvfunc = myresolver;
|
||||
hostsimport();
|
||||
}
|
||||
|
||||
@ -627,7 +604,7 @@ void sysdnscheck(void){
|
||||
setnservers(sysdns.ns, sysdns.n);
|
||||
dolog(NULL, (unsigned char *)"System name servers changed");
|
||||
/* none before: the C library resolved until now */
|
||||
if(!was) conf->resolvfunc = resolvfunc = myresolver;
|
||||
if(!was) resolvfunc = myresolver;
|
||||
}
|
||||
if(resolvfunc == myresolver && ((res & 2) || !was)) hostsimport();
|
||||
if(res & 2) dolog(NULL, (unsigned char *)"Hosts file changed");
|
||||
|
||||
@ -132,7 +132,7 @@ void * sockschild(struct clientparam* param) {
|
||||
}
|
||||
buf[i] = 0;
|
||||
if(command == 2 && param->srv->family != 6 && (!strcmp((char *)buf, "0.0.0.0") || !strcmp((char *)buf, "0"))) param->req = param->srv->extsa;
|
||||
else if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||
else if(!getip46m(param->srv->resolvmode, param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||
param->sinsr = param->req;
|
||||
break;
|
||||
default:
|
||||
@ -158,7 +158,7 @@ void * sockschild(struct clientparam* param) {
|
||||
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, param->srv->timeouts[STRING_S]) < 0) {RETURN(441);}
|
||||
buf[127] = 0;
|
||||
if(PARAMSTR(param, hostname, buf)){RETURN(21);}
|
||||
if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||
if(!getip46m(param->srv->resolvmode, param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||
param->sinsr = param->req;
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,6 +503,11 @@ struct nserver {
|
||||
};
|
||||
|
||||
#define MAXNSERVERS 3
|
||||
/* how a service resolves names: defaultresolve (the name servers in force,
|
||||
configured or the system's), fakeresolve, sysresolve (the C library) */
|
||||
#define RESOLVE_DEFAULT 0
|
||||
#define RESOLVE_FAKE 1
|
||||
#define RESOLVE_SYSTEM 2
|
||||
#define MAXRADIUS 5
|
||||
|
||||
struct radserver {
|
||||
@ -644,6 +649,7 @@ struct srvparam {
|
||||
int transparent;
|
||||
int nfilters, nreqfilters, nconnectfilters, nafterauthfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv;
|
||||
int family;
|
||||
int resolvmode; /* RESOLVE_* */
|
||||
int stacksize;
|
||||
struct extparam *config; /* the configuration it was started with */
|
||||
int timeouts[12]; /* conf.timeouts as they were when the service started */
|
||||
@ -928,7 +934,7 @@ struct extparam {
|
||||
int refs;
|
||||
struct hashtable pwl_table; /* users */
|
||||
int havelog; /* log was configured */
|
||||
RESOLVFUNC resolvfunc; /* nserver or fakeresolve, in force once committed */
|
||||
int resolvmode; /* RESOLVE_*: the last read, each service taking the one read before it */
|
||||
};
|
||||
|
||||
struct property {
|
||||
|
||||
@ -273,7 +273,7 @@ int udpsockmap(struct clientparam *param, int timeo)
|
||||
dstnamebuf[sz] = 0;
|
||||
dstname = dstnamebuf;
|
||||
i = 5 + sz;
|
||||
if (!getip46(param->srv->family, (unsigned char *)dstnamebuf,
|
||||
if (!getip46m(param->srv->resolvmode, param->srv->family, (unsigned char *)dstnamebuf,
|
||||
(struct sockaddr *)&dst)) {
|
||||
if (!nhops) return 100;
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
"""The system's name servers and hosts file as the default resolver: with
|
||||
no nserver in a configuration, names in the hosts file are answered from
|
||||
it; with nserver lines, or sysresolve (the system routines), it is not."""
|
||||
it; with nserver lines it is not. Each service resolves names the way the
|
||||
last of defaultresolve, sysresolve and fakeresolve before it says."""
|
||||
|
||||
import os
|
||||
import re
|
||||
@ -82,25 +83,36 @@ def run(t):
|
||||
t.ne(["127.0.0.1"], t.dns_query(other, "localhost") or [],
|
||||
"with nserver, the hosts file is not used")
|
||||
|
||||
# sysresolve: the system routines resolve names, and nothing is imported
|
||||
# for dnspr to answer from
|
||||
sysport, proxy, srv = t.free_port(), t.free_port(), t.free_port()
|
||||
t.start("sysdns_sysresolve", f"""
|
||||
# each service resolves the way the command before it says: fake (to
|
||||
# 127.0.0.2, where the server is not), the system routines (no
|
||||
# nsrecord) or the default (the system's name servers, and nsrecord)
|
||||
fake, system, default, srv = t.free_port(), t.free_port(), t.free_port(), t.free_port()
|
||||
t.start("sysdns_modes", f"""
|
||||
log
|
||||
nscache 1024
|
||||
nsrecord only3proxy.test 127.0.0.1
|
||||
flush
|
||||
sysresolve
|
||||
auth iponly
|
||||
allow *
|
||||
dnspr -p{sysport}
|
||||
proxy -p{proxy}
|
||||
fakeresolve
|
||||
proxy -p{fake}
|
||||
sysresolve
|
||||
proxy -p{system}
|
||||
defaultresolve
|
||||
proxy -p{default}
|
||||
flush
|
||||
auth iponly
|
||||
allow *
|
||||
http echo * /echo**
|
||||
httpsrv -p{srv}
|
||||
""", ports=[proxy, srv])
|
||||
wait(t, sysport, "localhost")
|
||||
t.ne(["127.0.0.1"], t.dns_query(sysport, "localhost") or [],
|
||||
"with sysresolve, dnspr has no hosts file names")
|
||||
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{proxy}").status,
|
||||
"and names resolve through the system routines")
|
||||
httpsrv -i127.0.0.1 -p{srv}
|
||||
""", ports=[fake, system, default, srv])
|
||||
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{default}").status,
|
||||
"defaultresolve: a name of the hosts file resolves")
|
||||
t.eq(200, t.http(f"http://only3proxy.test:{srv}/echo", proxy=f"127.0.0.1:{default}").status,
|
||||
"and an nsrecord name")
|
||||
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{system}").status,
|
||||
"sysresolve: names resolve through the system routines")
|
||||
t.ne(200, t.http(f"http://only3proxy.test:{srv}/echo", proxy=f"127.0.0.1:{system}").status,
|
||||
"which know no nsrecord name")
|
||||
t.ne(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{fake}").status,
|
||||
"fakeresolve: every name is 127.0.0.2, in a service before the others")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user