Name resolution via TCP support

Supports _real_ name resolution via parent proxy over TCP in nserver /
dnspr.
Can be used to create UDP->TCP name proxy, e.g.

nserver 127.0.0.1/tcp
nscache 65535
auth none
dnspr
auth iponly
tcppm 53 77.88.8.8 53

now, all names are resolved via TCP connection to 77.88.8.8
(dns.yandex.ru).
This commit is contained in:
z3APA3A 2014-12-11 03:06:34 +03:00
parent e3645ee971
commit 15f9f24f04
9 changed files with 96 additions and 37 deletions

View File

@ -1003,10 +1003,17 @@ static int h_flushusers(int argc, unsigned char **argv){
static int h_nserver(int argc, unsigned char **argv){ static int h_nserver(int argc, unsigned char **argv){
int res; int res;
char *str;
for(res = 0; nservers[res] && res < MAXNSERVERS; res++); for(res = 0; nservers[res].ip && res < MAXNSERVERS; res++);
if(res < MAXNSERVERS) { if(res < MAXNSERVERS) {
nservers[res] = getip(argv[1]); if((str = strchr((char *)argv[1], '/')))
*str = 0;
nservers[res].ip = getip(argv[1]);
if(str) {
nservers[res].usetcp = strstr(str + 1, "tcp")? 1:0;
*str = '/';
}
} }
resolvfunc = myresolver; resolvfunc = myresolver;
return 0; return 0;

View File

@ -950,7 +950,8 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign
return 0; return 0;
} }
unsigned long nservers[MAXNSERVERS] = {0, 0, 0, 0, 0}; struct nserver nservers[MAXNSERVERS] = {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}};
int tcpresolve = 0;
unsigned long authnserver; unsigned long authnserver;
@ -964,34 +965,53 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
return retval; return retval;
} }
for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i]); i++){ for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i].ip); i++){
unsigned short nquery, nq, na; unsigned short nquery, nq, na;
unsigned char buf[4096], *s1, *s2; unsigned char b[4098], *buf, *s1, *s2;
int j, k, len, flen; int j, k, len, flen;
SOCKET sock; SOCKET sock;
unsigned ttl; unsigned ttl;
time_t t; time_t t;
struct sockaddr_in sin, *sinsp; struct sockaddr_in sin, *sinsp;
int usetcp = 0;
memset(&sin, 0, sizeof(sin)); buf = b+2;
sinsp = (param && !makeauth && *SAFAMILY(&param->sinsr) == AF_INET)? (struct sockaddr_in *)&param->sinsr : &sin;
sinsp = (param && !makeauth)? (struct sockaddr_in *)&param->sinsr : &sin;
memset(sinsp, 0, sizeof(struct sockaddr_in));
if((sock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break; if(makeauth && authnserver){
if((sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break;
}
else {
usetcp = nservers[i].usetcp;
if((sock=so._socket(PF_INET, usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break;
}
sinsp->sin_family = AF_INET; sinsp->sin_family = AF_INET;
sinsp->sin_port = htons(0); sinsp->sin_port = htons(0);
sinsp->sin_addr.s_addr = htonl(0); sinsp->sin_addr.s_addr = htonl(0);
if(so._bind(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))) { if(so._bind(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))){
so._shutdown(sock, SHUT_RDWR); so._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
break; break;
} }
sinsp->sin_addr.s_addr = (makeauth && authnserver)?authnserver : nservers[i]; if(makeauth && authnserver){
sinsp->sin_addr.s_addr = authnserver;
}
else {
sinsp->sin_addr.s_addr = nservers[i].ip;
}
sinsp->sin_port = htons(53); sinsp->sin_port = htons(53);
if(usetcp){
if(so._connect(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))) {
so._shutdown(sock, SHUT_RDWR);
so._closesocket(sock);
break;
}
}
len = (int)strlen((char *)name); len = (int)strlen((char *)name);
nquery = myrand(name, len); *(unsigned short*)buf = htons(i+1); /* query id */
*(unsigned short*)buf = nquery; /* query id */
buf[2] = 1; /* recursive */ buf[2] = 1; /* recursive */
buf[3] = 0; buf[3] = 0;
buf[4] = 0; buf[4] = 0;
@ -1012,6 +1032,12 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
buf[len++] = (makeauth == 1)? 0x0c : 0x01; /* PTR:host address */ buf[len++] = (makeauth == 1)? 0x0c : 0x01; /* PTR:host address */
buf[len++] = 0; buf[len++] = 0;
buf[len++] = 1; /* INET */ buf[len++] = 1; /* INET */
if(usetcp){
buf-=2;
*(unsigned short*)buf = htons(len);
len+=2;
}
if(socksendto(sock, (struct sockaddr *)sinsp, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ if(socksendto(sock, (struct sockaddr *)sinsp, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
so._shutdown(sock, SHUT_RDWR); so._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
@ -1021,9 +1047,15 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
len = sockrecvfrom(sock, (struct sockaddr *) sinsp, buf, 4096, 15000); len = sockrecvfrom(sock, (struct sockaddr *) sinsp, buf, 4096, 15000);
so._shutdown(sock, SHUT_RDWR); so._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
if(len <= 13) continue; if(len <= 13) {
continue;
}
if(param) param->statssrv64 += len; if(param) param->statssrv64 += len;
if(*(unsigned short *)buf != nquery)continue; if(usetcp){
buf+=2;
len-=2;
}
if(*(unsigned short *)buf != htons(i+1))continue;
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) { if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
return 0; return 0;
} }

View File

@ -617,7 +617,7 @@ int doconnect(struct clientparam * param){
memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req)); memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req));
} }
if(!*SAPORT(&param->sinsr))*SAPORT(&param->sinsr) = *SAPORT(&param->req); if(!*SAPORT(&param->sinsr))*SAPORT(&param->sinsr) = *SAPORT(&param->req);
if ((param->remsock=so._socket(*SAFAMILY(&param->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);} if ((param->remsock=so._socket(SASOCK(&param->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
#ifndef NOIPV6 #ifndef NOIPV6
if(*SAFAMILY(&param->sinsr) == AF_INET6) memcpy(&param->sinsl, &param->srv->extsa6, sizeof(param->srv->extsa6)); if(*SAFAMILY(&param->sinsr) == AF_INET6) memcpy(&param->sinsl, &param->srv->extsa6, sizeof(param->srv->extsa6));

View File

@ -14,11 +14,12 @@
#endif #endif
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#define BUFSIZE 4096 #define BUFSIZE 16384
void * dnsprchild(struct clientparam* param) { void * dnsprchild(struct clientparam* param) {
unsigned long ip = 0; unsigned long ip = 0;
unsigned char *bbuf;
unsigned char *buf, *s1, *s2; unsigned char *buf, *s1, *s2;
char * host = NULL; char * host = NULL;
unsigned char c; unsigned char c;
@ -32,10 +33,11 @@ void * dnsprchild(struct clientparam* param) {
#endif #endif
if(!(buf = myalloc(BUFSIZE))){ if(!(bbuf = myalloc(BUFSIZE+2))){
param->srv->fds.events = POLLIN; param->srv->fds.events = POLLIN;
RETURN (21); RETURN (21);
} }
buf = bbuf+2;
size = sizeof(param->sincr); size = sizeof(param->sincr);
i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size); i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size);
#ifdef _WIN32 #ifdef _WIN32
@ -44,9 +46,9 @@ void * dnsprchild(struct clientparam* param) {
} }
ioctlsocket(param->clisock, FIONBIO, &ul); ioctlsocket(param->clisock, FIONBIO, &ul);
size = sizeof(param->sinsl); size = sizeof(param->sinsl);
if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sinsl, &size)) {RETURN(21);}; if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size)) {RETURN(21);};
if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
if(so._bind(param->clisock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) { if(so._bind(param->clisock,(struct sockaddr *)&param->sincl,sizeof(param->sincl))) {
RETURN(822); RETURN(822);
} }
@ -103,7 +105,7 @@ void * dnsprchild(struct clientparam* param) {
memcpy(buf+len+12,(void *)&ip,4); memcpy(buf+len+12,(void *)&ip,4);
len+=16; len+=16;
} }
if(type == 0x0c) { else if(type == 0x0c) {
unsigned a, b, c, d; unsigned a, b, c, d;
sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a);
@ -127,15 +129,10 @@ void * dnsprchild(struct clientparam* param) {
} }
else ip = 0; else ip = 0;
} }
if(!ip && nservers[0] && type!=1){ if(!ip && nservers[0].ip && type!=1){
if((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { if((param->remsock=so._socket(PF_INET, nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818); RETURN(818);
} }
#ifdef _WIN32
ioctlsocket(param->remsock, FIONBIO, &ul);
#else
fcntl(param->remsock,F_SETFL,O_NONBLOCK);
#endif
*SAFAMILY(&param->sinsl) = AF_INET; *SAFAMILY(&param->sinsl) = AF_INET;
*SAPORT(&param->sinsl) = htons(0); *SAPORT(&param->sinsl) = htons(0);
*(unsigned long*)SAADDR(&param->sinsl) = htonl(0); *(unsigned long*)SAADDR(&param->sinsl) = htonl(0);
@ -143,8 +140,22 @@ void * dnsprchild(struct clientparam* param) {
RETURN(819); RETURN(819);
} }
*SAFAMILY(&param->sinsr) = AF_INET; *SAFAMILY(&param->sinsr) = AF_INET;
*(unsigned long*)SAADDR(&param->sinsr) = nservers[0]; *(unsigned long*)SAADDR(&param->sinsr) = nservers[0].ip;
*SAPORT(&param->sinsr) = htons(53); *SAPORT(&param->sinsr) = htons(53);
if(nservers[0].usetcp) {
if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) RETURN(830);
buf-=2;
*(unsigned short*)buf = htons(i);
i+=2;
}
else {
#ifdef _WIN32
/* ioctlsocket(param->remsock, FIONBIO, &ul); */
#else
/* fcntl(param->remsock,F_SETFL,O_NONBLOCK); */
#endif
}
if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){ if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
RETURN(820); RETURN(820);
} }
@ -156,6 +167,10 @@ void * dnsprchild(struct clientparam* param) {
} }
param->statssrv64 += len; param->statssrv64 += len;
param->nreads++; param->nreads++;
if(nservers[0].usetcp) {
buf += 2;
len -= 2;
}
if(buf[6] || buf[7]){ if(buf[6] || buf[7]){
if(socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ if(socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
RETURN(822); RETURN(822);
@ -168,7 +183,7 @@ void * dnsprchild(struct clientparam* param) {
buf[2] = 0x85; buf[2] = 0x85;
buf[3] = 0x83; buf[3] = 0x83;
} }
usleep(SLEEPTIME); /* usleep(SLEEPTIME); */
res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000);
if(res != len){RETURN(819);} if(res != len){RETURN(819);}
if(!ip) {RETURN(888);} if(!ip) {RETURN(888);}
@ -186,7 +201,7 @@ CLEANRET:
); );
(*param->srv->logfunc)(param, buf); (*param->srv->logfunc)(param, buf);
} }
if(buf)myfree(buf); if(bbuf)myfree(bbuf);
if(host)myfree(host); if(host)myfree(host);
#ifndef _WIN32 #ifndef _WIN32
param->clisock = INVALID_SOCKET; param->clisock = INVALID_SOCKET;

View File

@ -184,7 +184,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask); int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask);
int myinet_ntop(int af, void *src, char *dst, socklen_t size); int myinet_ntop(int af, void *src, char *dst, socklen_t size);
extern unsigned long nservers[MAXNSERVERS]; extern struct nserver nservers[MAXNSERVERS];
extern unsigned long authnserver; extern unsigned long authnserver;
unsigned long getip(unsigned char *name); unsigned long getip(unsigned char *name);
unsigned long getip46(int family, unsigned char *name, struct sockaddr *sa); unsigned long getip46(int family, unsigned char *name, struct sockaddr *sa);

View File

@ -160,7 +160,7 @@ void * sockschild(struct clientparam* param) {
memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req)); memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req));
#endif #endif
if(!*SAPORT(&param->sinsl))*SAPORT(&param->sinsl) = port; if(!*SAPORT(&param->sinsl))*SAPORT(&param->sinsl) = port;
if ((param->remsock=so._socket(*SAFAMILY(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} if ((param->remsock=so._socket(SASOCK(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
param->operation = command == 2?BIND:UDPASSOC; param->operation = command == 2?BIND:UDPASSOC;
break; break;

View File

@ -297,6 +297,11 @@ struct trafcount {
time_t updated; time_t updated;
}; };
struct nserver {
unsigned long ip;
int usetcp;
};
typedef void * (* PROXYFUNC)(struct clientparam *); typedef void * (* PROXYFUNC)(struct clientparam *);
typedef enum { typedef enum {
@ -623,7 +628,7 @@ extern struct sockfuncs so;
struct pluginlink { struct pluginlink {
struct symbol symbols; struct symbol symbols;
struct extparam *conf; struct extparam *conf;
unsigned long *nservers; struct nserver *nservers;
int * linenum; int * linenum;
struct auth *authfuncs; struct auth *authfuncs;
struct commands * commandhandlers; struct commands * commandhandlers;

View File

@ -57,7 +57,7 @@ void * udppmchild(struct clientparam* param) {
param->cliinbuf = i; param->cliinbuf = i;
#ifdef _WIN32 #ifdef _WIN32
if((param->clisock=so._socket(*SAFAMILY(&param->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { if((param->clisock=so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818); RETURN(818);
} }
if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
@ -77,7 +77,7 @@ void * udppmchild(struct clientparam* param) {
memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req)); memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req));
#endif #endif
*SAPORT(&param->sinsl) = 0; *SAPORT(&param->sinsl) = 0;
if ((param->remsock=so._socket(*SAFAMILY(&param->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} if ((param->remsock=so._socket(SASOCK(&param->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {RETURN (12);} if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {RETURN (12);}
#ifdef _WIN32 #ifdef _WIN32
ioctlsocket(param->remsock, FIONBIO, &ul); ioctlsocket(param->remsock, FIONBIO, &ul);

View File

@ -1,2 +1,2 @@
#define VERSION "3proxy-0.8b-devel" #define VERSION "3proxy-0.8b-devel"
#define BUILDDATE "141210181747" #define BUILDDATE "141211025611"