mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 18:45:40 +08:00
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:
parent
e3645ee971
commit
15f9f24f04
11
src/3proxy.c
11
src/3proxy.c
@ -1003,10 +1003,17 @@ static int h_flushusers(int argc, unsigned char **argv){
|
||||
|
||||
static int h_nserver(int argc, unsigned char **argv){
|
||||
int res;
|
||||
char *str;
|
||||
|
||||
for(res = 0; nservers[res] && res < MAXNSERVERS; res++);
|
||||
for(res = 0; nservers[res].ip && res < MAXNSERVERS; res++);
|
||||
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;
|
||||
return 0;
|
||||
|
56
src/auth.c
56
src/auth.c
@ -950,7 +950,8 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign
|
||||
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;
|
||||
|
||||
@ -964,20 +965,29 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
|
||||
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 char buf[4096], *s1, *s2;
|
||||
unsigned char b[4098], *buf, *s1, *s2;
|
||||
int j, k, len, flen;
|
||||
SOCKET sock;
|
||||
unsigned ttl;
|
||||
time_t t;
|
||||
struct sockaddr_in sin, *sinsp;
|
||||
int usetcp = 0;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sinsp = (param && !makeauth && *SAFAMILY(¶m->sinsr) == AF_INET)? (struct sockaddr_in *)¶m->sinsr : &sin;
|
||||
buf = b+2;
|
||||
|
||||
sinsp = (param && !makeauth)? (struct sockaddr_in *)¶m->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_port = htons(0);
|
||||
sinsp->sin_addr.s_addr = htonl(0);
|
||||
@ -986,12 +996,22 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
|
||||
so._closesocket(sock);
|
||||
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);
|
||||
|
||||
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);
|
||||
nquery = myrand(name, len);
|
||||
*(unsigned short*)buf = nquery; /* query id */
|
||||
*(unsigned short*)buf = htons(i+1); /* query id */
|
||||
buf[2] = 1; /* recursive */
|
||||
buf[3] = 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++] = 0;
|
||||
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){
|
||||
so._shutdown(sock, SHUT_RDWR);
|
||||
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);
|
||||
so._shutdown(sock, SHUT_RDWR);
|
||||
so._closesocket(sock);
|
||||
if(len <= 13) continue;
|
||||
if(len <= 13) {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -617,7 +617,7 @@ int doconnect(struct clientparam * param){
|
||||
memcpy(SAADDR(¶m->sinsr), SAADDR(¶m->req), SAADDRLEN(¶m->req));
|
||||
}
|
||||
if(!*SAPORT(¶m->sinsr))*SAPORT(¶m->sinsr) = *SAPORT(¶m->req);
|
||||
if ((param->remsock=so._socket(*SAFAMILY(¶m->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
|
||||
if ((param->remsock=so._socket(SASOCK(¶m->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
|
||||
so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
|
||||
#ifndef NOIPV6
|
||||
if(*SAFAMILY(¶m->sinsr) == AF_INET6) memcpy(¶m->sinsl, ¶m->srv->extsa6, sizeof(param->srv->extsa6));
|
||||
|
45
src/dnspr.c
45
src/dnspr.c
@ -14,11 +14,12 @@
|
||||
#endif
|
||||
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
|
||||
|
||||
#define BUFSIZE 4096
|
||||
#define BUFSIZE 16384
|
||||
|
||||
|
||||
void * dnsprchild(struct clientparam* param) {
|
||||
unsigned long ip = 0;
|
||||
unsigned char *bbuf;
|
||||
unsigned char *buf, *s1, *s2;
|
||||
char * host = NULL;
|
||||
unsigned char c;
|
||||
@ -32,10 +33,11 @@ void * dnsprchild(struct clientparam* param) {
|
||||
#endif
|
||||
|
||||
|
||||
if(!(buf = myalloc(BUFSIZE))){
|
||||
if(!(bbuf = myalloc(BUFSIZE+2))){
|
||||
param->srv->fds.events = POLLIN;
|
||||
RETURN (21);
|
||||
}
|
||||
buf = bbuf+2;
|
||||
size = sizeof(param->sincr);
|
||||
i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size);
|
||||
#ifdef _WIN32
|
||||
@ -44,9 +46,9 @@ void * dnsprchild(struct clientparam* param) {
|
||||
}
|
||||
ioctlsocket(param->clisock, FIONBIO, &ul);
|
||||
size = sizeof(param->sinsl);
|
||||
if(so._getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sinsl, &size)) {RETURN(21);};
|
||||
if(so._getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size)) {RETURN(21);};
|
||||
if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
|
||||
if(so._bind(param->clisock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) {
|
||||
if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,sizeof(param->sincl))) {
|
||||
RETURN(822);
|
||||
}
|
||||
|
||||
@ -103,7 +105,7 @@ void * dnsprchild(struct clientparam* param) {
|
||||
memcpy(buf+len+12,(void *)&ip,4);
|
||||
len+=16;
|
||||
}
|
||||
if(type == 0x0c) {
|
||||
else if(type == 0x0c) {
|
||||
unsigned a, b, c, d;
|
||||
sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
|
||||
ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a);
|
||||
@ -127,15 +129,10 @@ void * dnsprchild(struct clientparam* param) {
|
||||
}
|
||||
else ip = 0;
|
||||
}
|
||||
if(!ip && nservers[0] && type!=1){
|
||||
if((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
|
||||
if(!ip && nservers[0].ip && type!=1){
|
||||
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);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
ioctlsocket(param->remsock, FIONBIO, &ul);
|
||||
#else
|
||||
fcntl(param->remsock,F_SETFL,O_NONBLOCK);
|
||||
#endif
|
||||
*SAFAMILY(¶m->sinsl) = AF_INET;
|
||||
*SAPORT(¶m->sinsl) = htons(0);
|
||||
*(unsigned long*)SAADDR(¶m->sinsl) = htonl(0);
|
||||
@ -143,8 +140,22 @@ void * dnsprchild(struct clientparam* param) {
|
||||
RETURN(819);
|
||||
}
|
||||
*SAFAMILY(¶m->sinsr) = AF_INET;
|
||||
*(unsigned long*)SAADDR(¶m->sinsr) = nservers[0];
|
||||
*(unsigned long*)SAADDR(¶m->sinsr) = nservers[0].ip;
|
||||
*SAPORT(¶m->sinsr) = htons(53);
|
||||
if(nservers[0].usetcp) {
|
||||
if(so._connect(param->remsock,(struct sockaddr *)¶m->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 *)¶m->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
|
||||
RETURN(820);
|
||||
}
|
||||
@ -156,6 +167,10 @@ void * dnsprchild(struct clientparam* param) {
|
||||
}
|
||||
param->statssrv64 += len;
|
||||
param->nreads++;
|
||||
if(nservers[0].usetcp) {
|
||||
buf += 2;
|
||||
len -= 2;
|
||||
}
|
||||
if(buf[6] || buf[7]){
|
||||
if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
|
||||
RETURN(822);
|
||||
@ -168,7 +183,7 @@ void * dnsprchild(struct clientparam* param) {
|
||||
buf[2] = 0x85;
|
||||
buf[3] = 0x83;
|
||||
}
|
||||
usleep(SLEEPTIME);
|
||||
/* usleep(SLEEPTIME); */
|
||||
res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000);
|
||||
if(res != len){RETURN(819);}
|
||||
if(!ip) {RETURN(888);}
|
||||
@ -186,7 +201,7 @@ CLEANRET:
|
||||
);
|
||||
(*param->srv->logfunc)(param, buf);
|
||||
}
|
||||
if(buf)myfree(buf);
|
||||
if(bbuf)myfree(bbuf);
|
||||
if(host)myfree(host);
|
||||
#ifndef _WIN32
|
||||
param->clisock = INVALID_SOCKET;
|
||||
|
@ -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 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;
|
||||
unsigned long getip(unsigned char *name);
|
||||
unsigned long getip46(int family, unsigned char *name, struct sockaddr *sa);
|
||||
|
@ -160,7 +160,7 @@ void * sockschild(struct clientparam* param) {
|
||||
memcpy(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req));
|
||||
#endif
|
||||
if(!*SAPORT(¶m->sinsl))*SAPORT(¶m->sinsl) = port;
|
||||
if ((param->remsock=so._socket(*SAFAMILY(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
|
||||
if ((param->remsock=so._socket(SASOCK(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
|
||||
param->operation = command == 2?BIND:UDPASSOC;
|
||||
break;
|
||||
|
||||
|
@ -297,6 +297,11 @@ struct trafcount {
|
||||
time_t updated;
|
||||
};
|
||||
|
||||
struct nserver {
|
||||
unsigned long ip;
|
||||
int usetcp;
|
||||
};
|
||||
|
||||
typedef void * (* PROXYFUNC)(struct clientparam *);
|
||||
|
||||
typedef enum {
|
||||
@ -623,7 +628,7 @@ extern struct sockfuncs so;
|
||||
struct pluginlink {
|
||||
struct symbol symbols;
|
||||
struct extparam *conf;
|
||||
unsigned long *nservers;
|
||||
struct nserver *nservers;
|
||||
int * linenum;
|
||||
struct auth *authfuncs;
|
||||
struct commands * commandhandlers;
|
||||
|
@ -57,7 +57,7 @@ void * udppmchild(struct clientparam* param) {
|
||||
param->cliinbuf = i;
|
||||
|
||||
#ifdef _WIN32
|
||||
if((param->clisock=so._socket(*SAFAMILY(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
|
||||
if((param->clisock=so._socket(SASOCK(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
|
||||
RETURN(818);
|
||||
}
|
||||
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(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req));
|
||||
#endif
|
||||
*SAPORT(¶m->sinsl) = 0;
|
||||
if ((param->remsock=so._socket(*SAFAMILY(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
|
||||
if ((param->remsock=so._socket(SASOCK(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
|
||||
if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) {RETURN (12);}
|
||||
#ifdef _WIN32
|
||||
ioctlsocket(param->remsock, FIONBIO, &ul);
|
||||
|
@ -1,2 +1,2 @@
|
||||
#define VERSION "3proxy-0.8b-devel"
|
||||
#define BUILDDATE "141210181747"
|
||||
#define BUILDDATE "141211025611"
|
||||
|
Loading…
Reference in New Issue
Block a user