2014-04-08 17:03:21 +08:00
|
|
|
/*
|
|
|
|
3APA3A simpliest proxy server
|
2021-07-02 16:50:33 +08:00
|
|
|
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org>
|
2014-04-08 17:03:21 +08:00
|
|
|
|
|
|
|
please read License Agreement
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "proxy.h"
|
|
|
|
|
|
|
|
#ifndef UDP
|
|
|
|
#define UDP
|
|
|
|
#endif
|
|
|
|
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
|
|
|
|
|
2014-12-11 08:06:34 +08:00
|
|
|
#define BUFSIZE 16384
|
2014-04-08 17:03:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
void * dnsprchild(struct clientparam* param) {
|
|
|
|
unsigned long ip = 0;
|
2014-12-11 08:06:34 +08:00
|
|
|
unsigned char *bbuf;
|
2014-04-08 17:03:21 +08:00
|
|
|
unsigned char *buf, *s1, *s2;
|
|
|
|
char * host = NULL;
|
|
|
|
unsigned char c;
|
|
|
|
SASIZETYPE size;
|
|
|
|
int res, i;
|
|
|
|
int len;
|
|
|
|
unsigned type=0;
|
|
|
|
unsigned ttl;
|
2014-12-14 10:33:08 +08:00
|
|
|
unsigned char addr[16];
|
2014-04-08 17:03:21 +08:00
|
|
|
#ifdef _WIN32
|
|
|
|
unsigned long ul = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2014-12-11 08:06:34 +08:00
|
|
|
if(!(bbuf = myalloc(BUFSIZE+2))){
|
2014-04-08 17:03:21 +08:00
|
|
|
param->srv->fds.events = POLLIN;
|
|
|
|
RETURN (21);
|
|
|
|
}
|
2014-12-11 08:06:34 +08:00
|
|
|
buf = bbuf+2;
|
2014-05-11 09:04:04 +08:00
|
|
|
size = sizeof(param->sincr);
|
2016-02-16 20:29:51 +08:00
|
|
|
i = so._recvfrom(param->srv->srvsock, (char *)buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size);
|
2014-12-13 08:56:01 +08:00
|
|
|
size = sizeof(param->sinsl);
|
|
|
|
getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size);
|
2014-04-08 17:03:21 +08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
|
|
|
|
RETURN(818);
|
|
|
|
}
|
|
|
|
ioctlsocket(param->clisock, FIONBIO, &ul);
|
2016-02-16 20:29:51 +08:00
|
|
|
if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (char *)&ul, sizeof(int))) {RETURN(820);};
|
2016-01-22 20:59:40 +08:00
|
|
|
if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,SASIZE(¶m->sincl))) {
|
2014-04-08 17:03:21 +08:00
|
|
|
RETURN(822);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
param->clisock = param->srv->srvsock;
|
|
|
|
#endif
|
|
|
|
param->srv->fds.events = POLLIN;
|
|
|
|
|
|
|
|
if(i < 0) {
|
|
|
|
RETURN(813);
|
|
|
|
}
|
|
|
|
buf[BUFSIZE - 1] = 0;
|
|
|
|
if(i<=13 || i>1000){
|
|
|
|
RETURN (814);
|
|
|
|
}
|
|
|
|
param->operation = DNSRESOLVE;
|
|
|
|
if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
|
|
|
|
|
|
|
|
if(buf[4]!=0 || buf[5]!=1) RETURN(816);
|
|
|
|
for(len = 12; len<i; len+=(c+1)){
|
|
|
|
c = buf[len];
|
|
|
|
if(!c)break;
|
|
|
|
buf[len] = '.';
|
|
|
|
}
|
|
|
|
if(len > (i-4)) {RETURN(817);}
|
|
|
|
|
|
|
|
host = mystrdup((char *)buf+13);
|
|
|
|
if(!host) {RETURN(21);}
|
|
|
|
|
|
|
|
for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1);
|
|
|
|
*s2 = (len - (int)(s2 - buf)) - 1;
|
|
|
|
|
|
|
|
type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
|
2014-12-14 10:33:08 +08:00
|
|
|
if((type==0x01 || type==0x1c) && !param->srv->singlepacket){
|
|
|
|
ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
|
2014-04-08 17:03:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
len+=5;
|
|
|
|
|
|
|
|
if(ip){
|
|
|
|
buf[2] = 0x85;
|
|
|
|
buf[3] = 0x80;
|
|
|
|
buf[6] = 0;
|
|
|
|
buf[7] = 1;
|
|
|
|
buf[8] = buf[9] = buf[10] = buf[11] = 0;
|
|
|
|
memset(buf+len, 0, 16);
|
|
|
|
buf[len] = 0xc0;
|
|
|
|
buf[len+1] = 0x0c;
|
2014-12-14 10:33:08 +08:00
|
|
|
buf[len+3] = type;
|
2014-04-08 17:03:21 +08:00
|
|
|
buf[len+5] = 1;
|
|
|
|
ttl = htonl(ttl);
|
|
|
|
memcpy(buf + len + 6, &ttl, 4);
|
2014-12-14 10:33:08 +08:00
|
|
|
buf[len+11] = type==1? 4:16;
|
|
|
|
memcpy(buf+len+12,(void *)&addr,type==1? 4:16);
|
|
|
|
len+=(type==1?16:28);
|
2014-04-08 17:03:21 +08:00
|
|
|
}
|
2014-12-11 08:06:34 +08:00
|
|
|
else if(type == 0x0c) {
|
2014-04-08 17:03:21 +08:00
|
|
|
unsigned a, b, c, d;
|
|
|
|
sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
|
|
|
|
ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a);
|
2014-12-13 08:56:01 +08:00
|
|
|
if(*SAFAMILY(¶m->sincl) == AF_INET && ip == *(unsigned long*)SAADDR(¶m->sincl)){
|
2014-04-08 17:03:21 +08:00
|
|
|
buf[2] = 0x85;
|
|
|
|
buf[3] = 0x80;
|
|
|
|
buf[6] = 0;
|
|
|
|
buf[7] = 1;
|
|
|
|
buf[8] = buf[9] = buf[10] = buf[11] = 0;
|
|
|
|
memset(buf+len, 0, 20);
|
|
|
|
buf[len] = 0xc0;
|
|
|
|
buf[len+1] = 0x0c;
|
|
|
|
buf[len+3] = 0x0c;
|
|
|
|
buf[len+5] = 1;
|
|
|
|
ttl = htonl(3600);
|
|
|
|
memcpy(buf + len + 6, &ttl, 4);
|
|
|
|
buf[len+11] = 7;
|
|
|
|
buf[len+12] = 6;
|
|
|
|
memcpy(buf+len+13,(void *)"3proxy",6);
|
|
|
|
len+=20;
|
|
|
|
}
|
|
|
|
else ip = 0;
|
|
|
|
}
|
2014-12-13 08:56:01 +08:00
|
|
|
if(!ip && numservers){
|
|
|
|
if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
|
2014-04-08 17:03:21 +08:00
|
|
|
RETURN(818);
|
|
|
|
}
|
2014-12-13 08:56:01 +08:00
|
|
|
memset(¶m->sinsl, 0, sizeof(param->sinsl));
|
|
|
|
*SAFAMILY(¶m->sinsl) = *SAFAMILY(&nservers[0].addr);
|
2016-01-22 20:59:40 +08:00
|
|
|
if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) {
|
2014-04-08 17:03:21 +08:00
|
|
|
RETURN(819);
|
|
|
|
}
|
2016-02-05 23:31:17 +08:00
|
|
|
param->sinsr = nservers[0].addr;
|
2014-12-11 08:06:34 +08:00
|
|
|
if(nservers[0].usetcp) {
|
2018-05-05 22:16:51 +08:00
|
|
|
if(connectwithpoll(param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr),CONNECT_TO)) RETURN(830);
|
2014-12-11 08:06:34 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2014-10-21 10:00:56 +08:00
|
|
|
if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
|
2014-04-08 17:03:21 +08:00
|
|
|
RETURN(820);
|
|
|
|
}
|
2014-04-10 07:34:59 +08:00
|
|
|
param->statscli64 += i;
|
2014-04-08 17:03:21 +08:00
|
|
|
param->nwrites++;
|
2016-01-17 07:13:17 +08:00
|
|
|
len = sockrecvfrom(param->remsock, (struct sockaddr *)¶m->sinsr, buf, BUFSIZE, conf.timeouts[DNS_TO]*1000);
|
2014-04-08 17:03:21 +08:00
|
|
|
if(len <= 13) {
|
|
|
|
RETURN(821);
|
|
|
|
}
|
2014-04-10 07:34:59 +08:00
|
|
|
param->statssrv64 += len;
|
2014-04-08 17:03:21 +08:00
|
|
|
param->nreads++;
|
2014-12-11 08:06:34 +08:00
|
|
|
if(nservers[0].usetcp) {
|
2014-12-13 08:56:01 +08:00
|
|
|
unsigned short us;
|
|
|
|
us = ntohs(*(unsigned short *)buf);
|
|
|
|
if(us > 4096) RETURN(833);
|
2014-12-11 08:06:34 +08:00
|
|
|
buf += 2;
|
|
|
|
len -= 2;
|
2014-12-13 08:56:01 +08:00
|
|
|
if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]);
|
|
|
|
if(len != us) RETURN(832);
|
2014-12-11 08:06:34 +08:00
|
|
|
}
|
2014-04-08 17:03:21 +08:00
|
|
|
if(buf[6] || buf[7]){
|
2014-05-11 09:04:04 +08:00
|
|
|
if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
|
2014-04-08 17:03:21 +08:00
|
|
|
RETURN(822);
|
|
|
|
}
|
|
|
|
RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if(!ip) {
|
|
|
|
buf[2] = 0x85;
|
|
|
|
buf[3] = 0x83;
|
|
|
|
}
|
2014-05-11 09:04:04 +08:00
|
|
|
res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000);
|
2014-04-08 17:03:21 +08:00
|
|
|
if(res != len){RETURN(819);}
|
|
|
|
if(!ip) {RETURN(888);}
|
|
|
|
|
|
|
|
CLEANRET:
|
|
|
|
|
|
|
|
if(param->res!=813){
|
2014-12-14 10:33:08 +08:00
|
|
|
sprintf((char *)buf, "%04x/%s/",
|
2014-04-08 17:03:21 +08:00
|
|
|
(unsigned)type,
|
2014-12-14 10:33:08 +08:00
|
|
|
host?host:"");
|
2016-02-16 20:29:51 +08:00
|
|
|
if((ip && type == 0x01) || type == 0x1c){
|
|
|
|
myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, (char *)buf+strlen((char *)buf), 64);
|
2014-12-14 10:33:08 +08:00
|
|
|
}
|
2020-10-09 20:42:34 +08:00
|
|
|
dolog(param, buf);
|
2014-04-08 17:03:21 +08:00
|
|
|
}
|
2014-12-11 08:06:34 +08:00
|
|
|
if(bbuf)myfree(bbuf);
|
2014-04-08 17:03:21 +08:00
|
|
|
if(host)myfree(host);
|
|
|
|
#ifndef _WIN32
|
|
|
|
param->clisock = INVALID_SOCKET;
|
|
|
|
#endif
|
|
|
|
freeparam(param);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|