Просмотр исходного кода

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).
z3APA3A 11 лет назад
Родитель
Сommit
15f9f24f04
9 измененных файлов с 96 добавлено и 37 удалено
  1. 9 2
      src/3proxy.c
  2. 45 13
      src/auth.c
  3. 1 1
      src/common.c
  4. 30 15
      src/dnspr.c
  5. 1 1
      src/proxy.h
  6. 1 1
      src/socks.c
  7. 6 1
      src/structures.h
  8. 2 2
      src/udppm.c
  9. 1 1
      src/version.h

+ 9 - 2
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;

+ 45 - 13
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,34 +965,53 @@ 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(&param->sinsr) == AF_INET)? (struct sockaddr_in *)&param->sinsr : &sin;
+		buf = b+2;
+
+		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_port = htons(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._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;
 		}

+ 1 - 1
src/common.c

@@ -617,7 +617,7 @@ int doconnect(struct clientparam * param){
 		memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&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));
 #ifndef NOIPV6
 	if(*SAFAMILY(&param->sinsr) == AF_INET6) memcpy(&param->sinsl, &param->srv->extsa6, sizeof(param->srv->extsa6));

+ 30 - 15
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 *)&param->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 *)&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._bind(param->clisock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {
+	if(so._bind(param->clisock,(struct sockaddr *)&param->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(&param->sinsl) = AF_INET;
 	*SAPORT(&param->sinsl) = htons(0);
 	*(unsigned long*)SAADDR(&param->sinsl) = htonl(0);
@@ -143,8 +140,22 @@ void * dnsprchild(struct clientparam* param) {
 		RETURN(819);
 	}
 	*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);
+	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){
 		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 *)&param->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 *)&param->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;

+ 1 - 1
src/proxy.h

@@ -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);

+ 1 - 1
src/socks.c

@@ -160,7 +160,7 @@ void * sockschild(struct clientparam* param) {
 	 memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req)); 
 #endif
 	 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;
 	 break;
 

+ 6 - 1
src/structures.h

@@ -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;

+ 2 - 2
src/udppm.c

@@ -57,7 +57,7 @@ void * udppmchild(struct clientparam* param) {
  param->cliinbuf = i;
 
 #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);
 	}
 	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));
 #endif
  *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);}
 #ifdef _WIN32
 	ioctlsocket(param->remsock, FIONBIO, &ul);

+ 1 - 1
src/version.h

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