From eb09ae7c586653fb3a8d3d5e5763a7f7a67161cb Mon Sep 17 00:00:00 2001 From: z3APA3A <3APA3A@3proxy.ru> Date: Sat, 5 May 2018 17:16:51 +0300 Subject: [PATCH] Support socket options for connback sockets and connection timeouts --- man/3proxy.cfg.3 | 9 +++++---- src/auth.c | 2 +- src/common.c | 8 ++++---- src/dnspr.c | 2 +- src/ftppr.c | 2 +- src/proxy.h | 2 +- src/proxymain.c | 39 ++++++++++++++++++++++++++------------- src/structures.h | 8 +++++--- 8 files changed, 44 insertions(+), 28 deletions(-) diff --git a/man/3proxy.cfg.3 b/man/3proxy.cfg.3 index 11bc13f..72eeadf 100644 --- a/man/3proxy.cfg.3 +++ b/man/3proxy.cfg.3 @@ -152,8 +152,9 @@ listen on given local HOST:port for incoming connections instead of making remot .B -rHOST:port connect to given remote HOST:port instead of listening local connection on -p or default port. Can be used with another 3proxy service running -R option for connect back functionality. Most commonly used with proxy or socks. HOST can be given as IP or hostname, useful in case of dynamic DNS. .br -.B -ocOPTIONS, -osOPTIONS, -olOPTIONS -options for client (oc), server (os) or listening (ol) socket. Options like TCP_CORK, TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS, USE_TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT, SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be supported depending on OS. +.B -ocOPTIONS, -osOPTIONS, -olOPTIONS, -orOPTIONS, -oROPTIONS +options for proxy-to-client (oc), proxy-to-server (os), proxy listening (ol), connect back client (or), connect back listening (oR) sockets. +Options like TCP_CORK, TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS, USE_TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT, SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be supported depending on OS. .br .B -DiINTERFACE, -DeINTERFACE bind internal interface / external inteface to given INTERFACE (e.g. eth0) if SO_BINDTODEVICE supported by system @@ -350,9 +351,9 @@ can use %A as produced archive name and %F as filename. .br .B timeouts - + .br - Sets timeout values + Sets timeout values, defaults 1, 5, 30, 60, 180, 1800, 15, 60, 15, 5. .br BYTE_SHORT - short timeout for single byte, is usually used for receiving single byte from stream. .br diff --git a/src/auth.c b/src/auth.c index 381eef4..5e7c430 100644 --- a/src/auth.c +++ b/src/auth.c @@ -1154,7 +1154,7 @@ unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, un *sinsr = nservers[i].addr; } if(usetcp){ - if(connectwithpoll(sock,(struct sockaddr *)sinsr,SASIZE(sinsr))) { + if(connectwithpoll(sock,(struct sockaddr *)sinsr,SASIZE(sinsr),CONNECT_TO)) { so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); break; diff --git a/src/common.c b/src/common.c index 4594237..98d8cfa 100644 --- a/src/common.c +++ b/src/common.c @@ -65,7 +65,7 @@ char *rotations[] = { struct extparam conf = { - {1, 5, 30, 60, 180, 1800, 15, 60, 0, 0}, + {1, 5, 30, 60, 180, 1800, 15, 60, 15, 5, 0, 0}, NULL, NULL, NULL, NULL, @@ -649,7 +649,7 @@ void logsyslog(struct clientparam * param, const unsigned char *s) { } #endif -int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size){ +int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){ struct pollfd fds[1]; #ifdef _WIN32 unsigned long ul = 1; @@ -663,7 +663,7 @@ int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size){ memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLOUT; - if(so._poll(fds, 1, conf.timeouts[STRING_S]*1000) <= 0) { + if(so._poll(fds, 1, to*1000) <= 0) { return (13); } return 0; @@ -728,7 +728,7 @@ int doconnect(struct clientparam * param){ } if(param->operation >= 256 || (param->operation & CONNECT)){ - if(connectwithpoll(param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr))) { + if(connectwithpoll(param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr),CONNECT_TO)) { return 13; } } diff --git a/src/dnspr.c b/src/dnspr.c index 4e44e23..041e0e2 100644 --- a/src/dnspr.c +++ b/src/dnspr.c @@ -140,7 +140,7 @@ void * dnsprchild(struct clientparam* param) { } param->sinsr = nservers[0].addr; if(nservers[0].usetcp) { - if(connectwithpoll(param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr))) RETURN(830); + if(connectwithpoll(param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr),CONNECT_TO)) RETURN(830); buf-=2; *(unsigned short*)buf = htons(i); i+=2; diff --git a/src/ftppr.c b/src/ftppr.c index 845c7c4..e22e66a 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -153,7 +153,7 @@ void * ftpprchild(struct clientparam* param) { if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);} *SAPORT(¶m->sincr) = htons((unsigned short)((b5<<8)^b6)); - if(connectwithpoll(clidatasock, (struct sockaddr *)¶m->sincr, SASIZE(¶m->sincr))) { + if(connectwithpoll(clidatasock, (struct sockaddr *)¶m->sincr, SASIZE(¶m->sincr),CONNECT_TO)) { so._closesocket(clidatasock); clidatasock = INVALID_SOCKET; RETURN(826); diff --git a/src/proxy.h b/src/proxy.h index 6dab439..33bff34 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -268,7 +268,7 @@ void srvinit2(struct srvparam * srv, struct clientparam *param); void srvfree(struct srvparam * srv); unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t); int readconfig(FILE * fp); -int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size); +int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to); int myrand(void * entropy, int len); diff --git a/src/proxymain.c b/src/proxymain.c index 2df82eb..4b740d5 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -16,14 +16,12 @@ DWORD WINAPI threadfunc(LPVOID p) { #else void * threadfunc (void *p) { #endif - int i = 0; + int i = -1; if(param->srv->cbsock != INVALID_SOCKET){ SASIZETYPE size = sizeof(param->sinsr); - for(i=0; i<3; i++){ + for(i=5+(param->srv->maxchild>>10); i; i--){ param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size); if(param->remsock == INVALID_SOCKET) { - param->res = 13; - param->srv->logfunc(param, (unsigned char *)"Connect back accept() failed"); continue; } #ifndef WITHMAIN @@ -46,7 +44,9 @@ void * threadfunc (void *p) { break; } } - if(i == 3){ + if(!i){ + param->res = 13; + param->srv->logfunc(param, (unsigned char *)"Connect back accept() repeatedly failed"); freeparam(param); } else { @@ -214,7 +214,9 @@ int MODULEMAINFUNC (int argc, char** argv){ " -6 Use IPv6 for outgoing connections\n" " -46 Prefer IPv4 for outgoing connections, use both IPv4 and IPv6\n" " -64 Prefer IPv6 for outgoing connections, use both IPv4 and IPv6\n" - " -ocOPTIONS, -osOPTIONS, -olOPTIONS - options for client (oc), server (os) or listening (ol) socket," + " -ocOPTIONS, -osOPTIONS, -olOPTIONS, -orOPTIONS -oROPTIONS - options for\n" + " to-client (oc), to-server (os), listening (ol) socket, connect back client\n" + " (or) socket, connect back server (oR) listening socket\n" " where possible options are: "; #ifdef _WIN32 @@ -401,18 +403,25 @@ int MODULEMAINFUNC (int argc, char** argv){ #endif break; case 'o': - if(argv[i][2] == 's'){ + switch(argv[i][2]){ + case 's': srv.srvsockopts = getopts(argv[i]+3); break; - } - else if(argv[i][2] == 'c'){ + case 'c': srv.clisockopts = getopts(argv[i]+3); break; - } - else if(argv[i][2] == 'l'){ + case 'l': srv.lissockopts = getopts(argv[i]+3); break; - } + case 'r': + srv.cbcsockopts = getopts(argv[i]+3); + break; + case 'R': + srv.cbcsockopts = getopts(argv[i]+3); + break; + default: + error = 1; + } default: error = 1; break; @@ -602,6 +611,8 @@ int MODULEMAINFUNC (int argc, char** argv){ so._setsockopt(srv.cbsock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int)); #endif + setopts(srv.cbsock, srv.cbssockopts); + if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) { (*srv.logfunc)(&defparam, (unsigned char *)"Failed to bind connect back socket"); return -7; @@ -656,8 +667,10 @@ int MODULEMAINFUNC (int argc, char** argv){ if(iscbc){ new_sock=so._socket(SASOCK(&defparam.sincr), SOCK_STREAM, IPPROTO_TCP); if(new_sock != INVALID_SOCKET){ + setopts(new_sock, srv.cbcsockopts); + parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr); - if(connectwithpoll(new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr))) { + if(connectwithpoll(new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) { so._closesocket(new_sock); new_sock = INVALID_SOCKET; usleep(SLEEPTIME); diff --git a/src/structures.h b/src/structures.h index cb6abe2..a9284d7 100644 --- a/src/structures.h +++ b/src/structures.h @@ -418,7 +418,7 @@ struct srvparam { int stacksize; int noforce; int anonymous; - int clisockopts, srvsockopts, lissockopts; + int clisockopts, srvsockopts, lissockopts, cbcsockopts, cbssockopts; #ifdef WITHSPLICE int usesplice; #endif @@ -543,7 +543,7 @@ struct filemon { struct extparam { - int timeouts[10]; + int timeouts[12]; struct ace * acl; char * conffile; struct bandlim * bandlimiter, *bandlimiterout; @@ -774,7 +774,9 @@ typedef enum { CONNECTION_S, CONNECTION_L, DNS_TO, - CHAIN_TO + CHAIN_TO, + CONNECT_TO, + CONNBACK_TO }TIMEOUT; typedef enum {