Connect back proxy functionality added

-r and -R options added to support connect back functionality between
two instances of proxy
This commit is contained in:
z3APA3A 2015-09-20 21:01:50 +03:00
parent 6529b9cea1
commit a2b5af6dab
5 changed files with 182 additions and 67 deletions

View File

@ -216,6 +216,24 @@ int ceparseargs(const char *str){
#endif #endif
void parsehost(int family, char *host, struct sockaddr *sa){
char *sp=NULL,*se=NULL;
unsigned short port;
if(*host == '[') se=strchr(host, ']');
if ( (sp = strchr(se?se:host, ':')) ) *sp = 0;
if(se){
*se = 0;
}
if(sp){
port = atoi(sp+1);
}
getip46(family, host + (se!=0), (struct sockaddr *)sa);
if(se) *se = ']';
if(sp) *sp = ':';
*SAPORT(sa) = htons(port);
}
int parsehostname(char *hostname, struct clientparam *param, unsigned short port){ int parsehostname(char *hostname, struct clientparam *param, unsigned short port){
char *sp=NULL,*se=NULL; char *sp=NULL,*se=NULL;

View File

@ -235,10 +235,12 @@ void mschap(const unsigned char *win_password,
struct hashtable; struct hashtable;
void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires); void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires);
void parsehost(int family, char *host, struct sockaddr *sa);
int parsehostname(char *hostname, struct clientparam *param, unsigned short port); int parsehostname(char *hostname, struct clientparam *param, unsigned short port);
int parseusername(char *username, struct clientparam *param, int extpasswd); int parseusername(char *username, struct clientparam *param, int extpasswd);
int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port); int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port);
int ACLmatches(struct ace* acentry, struct clientparam * param); int ACLmatches(struct ace* acentry, struct clientparam * param);
int checkACL(struct clientparam * param);
unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth); unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth);

View File

@ -9,8 +9,46 @@
#include "proxy.h" #include "proxy.h"
#define param ((struct clientparam *) p)
#ifdef _WIN32
DWORD WINAPI threadfunc(LPVOID p) {
#else
void * threadfunc (void *p) {
#endif
if(param->srv->cbsock != INVALID_SOCKET){
SASIZETYPE size = sizeof(param->sinsr);
param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)&param->sinsr, &size);
if(param->remsock == INVALID_SOCKET) {
param->res = 13;
param->srv->logfunc(param, "Connect back accept() failed");
#ifdef _WIN32
return 0;
#else
return NULL;
#endif
}
#ifndef WITHMAIN
memcpy(&param->req, &param->sinsr, size);
if(param->srv->acl) param->res = checkACL(param);
if(param->res){
param->srv->logfunc(param, "Connect back ACL failed");
}
#ifdef _WIN32
return 0;
#else
return NULL;
#endif
#endif
}
((struct clientparam *) p)->srv->pf((struct clientparam *)p);
#ifdef _WIN32
return 0;
#else
return NULL;
#endif
}
#undef param
@ -42,7 +80,7 @@ int MODULEMAINFUNC (int argc, char** argv){
SOCKET sock = INVALID_SOCKET; SOCKET sock = INVALID_SOCKET, new_sock = INVALID_SOCKET;
int i=0; int i=0;
SASIZETYPE size; SASIZETYPE size;
pthread_t thread; pthread_t thread;
@ -53,8 +91,15 @@ int MODULEMAINFUNC (int argc, char** argv){
unsigned sleeptime; unsigned sleeptime;
unsigned char buf[256]; unsigned char buf[256];
char *hostname=NULL; char *hostname=NULL;
int opt = 1, isudp; int opt = 1, isudp = 0, iscbl = 0, iscbc = 0;
unsigned char *cbc_string = NULL, *cbl_string = NULL;
#ifndef NOIPV6
struct sockaddr_in6 cbsa;
#else
struct sockaddr_in cbsa;
#endif
FILE *fp = NULL; FILE *fp = NULL;
struct linger lg;
int nlog = 5000; int nlog = 5000;
char loghelp[] = char loghelp[] =
#ifdef STDMAIN #ifdef STDMAIN
@ -73,6 +118,8 @@ int MODULEMAINFUNC (int argc, char** argv){
" -t be silent (do not log service start/stop)\n" " -t be silent (do not log service start/stop)\n"
" -iIP ip address or internal interface (clients are expected to connect)\n" " -iIP ip address or internal interface (clients are expected to connect)\n"
" -eIP ip address or external interface (outgoing connection will have this)\n" " -eIP ip address or external interface (outgoing connection will have this)\n"
" -rIP:PORT Use IP:port for connect back proxy instead of listen port\n"
" -RPORT Use PORT to listen connect back proxy connection to pass data to\n"
" -4 Use IPv4 for outgoing connections\n" " -4 Use IPv4 for outgoing connections\n"
" -6 Use IPv6 for outgoing connections\n" " -6 Use IPv6 for outgoing connections\n"
" -46 Prefer IPv4 for outgoing connections, use both IPv4 and IPv6\n" " -46 Prefer IPv4 for outgoing connections, use both IPv4 and IPv6\n"
@ -85,8 +132,6 @@ int MODULEMAINFUNC (int argc, char** argv){
int inetd = 0; int inetd = 0;
#endif #endif
#endif #endif
SOCKET new_sock = INVALID_SOCKET;
struct linger lg;
#ifdef _WIN32 #ifdef _WIN32
HANDLE h; HANDLE h;
#endif #endif
@ -222,6 +267,14 @@ int MODULEMAINFUNC (int argc, char** argv){
case 'h': case 'h':
hostname = argv[i] + 2; hostname = argv[i] + 2;
break; break;
case 'r':
cbc_string = mystrdup(argv[i] + 2);
iscbc = 1;
break;
case 'R':
cbl_string = mystrdup(argv[i] + 2);
iscbl = 1;
break;
case 'u': case 'u':
srv.nouser = 1; srv.nouser = 1;
break; break;
@ -255,6 +308,8 @@ int MODULEMAINFUNC (int argc, char** argv){
"Available options are:\n" "Available options are:\n"
"%s" "%s"
" -pPORT - service port to accept connections\n" " -pPORT - service port to accept connections\n"
" -RIP:PORT - connect back IP:PORT to listen and accept connections\n"
" -rIP:PORT - connect back IP:PORT to establish connect back connection\n"
"%s" "%s"
"\tExample: %s -i127.0.0.1\n\n" "\tExample: %s -i127.0.0.1\n\n"
"%s", "%s",
@ -284,6 +339,8 @@ int MODULEMAINFUNC (int argc, char** argv){
" [-e<external_ip>] <port_to_bind>" " [-e<external_ip>] <port_to_bind>"
" <target_hostname> <target_port>\n" " <target_hostname> <target_port>\n"
"Available options are:\n" "Available options are:\n"
" -RIP:PORT - connect back IP:PORT to listen and accept connections\n"
" -rIP:PORT - connect back IP:PORT to establish connect back connection\n"
"%s" "%s"
"%s" "%s"
"\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n" "\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n"
@ -343,56 +400,7 @@ int MODULEMAINFUNC (int argc, char** argv){
#endif #endif
if(srv.srvsock == INVALID_SOCKET){
if(!isudp){
lg.l_onoff = 1;
lg.l_linger = conf.timeouts[STRING_L];
sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP);
}
else {
sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
if( sock == INVALID_SOCKET) {
perror("socket()");
return -2;
}
#ifdef _WIN32
ioctlsocket(sock, FIONBIO, &ul);
#else
fcntl(sock,F_SETFL,O_NONBLOCK);
#endif
srv.srvsock = sock;
if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()");
#ifdef SO_REUSEPORT
so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
#endif
}
size = sizeof(srv.intsa);
for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, size)==-1; usleep(sleeptime)) {
sprintf((char *)buf, "bind(): %s", strerror(errno));
if(!srv.silent)(*srv.logfunc)(&defparam, buf);
sleeptime = (sleeptime<<1);
if(!sleeptime) {
so._closesocket(sock);
return -3;
}
}
if(!isudp){
if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) {
sprintf((char *)buf, "listen(): %s", strerror(errno));
if(!srv.silent)(*srv.logfunc)(&defparam, buf);
return -4;
}
}
else
defparam.clisock = sock;
if(!srv.silent){
sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
(*srv.logfunc)(&defparam, buf);
}
memset(&defparam.sincr, 0, sizeof(defparam.sincr)); memset(&defparam.sincr, 0, sizeof(defparam.sincr));
memset(&defparam.sincl, 0, sizeof(defparam.sincl)); memset(&defparam.sincl, 0, sizeof(defparam.sincl));
memset(&defparam.sinsl, 0, sizeof(defparam.sinsl)); memset(&defparam.sinsl, 0, sizeof(defparam.sinsl));
@ -404,6 +412,76 @@ int MODULEMAINFUNC (int argc, char** argv){
*SAFAMILY(&defparam.sinsr) = AF_INET; *SAFAMILY(&defparam.sinsr) = AF_INET;
*SAFAMILY(&defparam.req) = AF_INET; *SAFAMILY(&defparam.req) = AF_INET;
if (!iscbc) {
if(srv.srvsock == INVALID_SOCKET){
if(!isudp){
lg.l_onoff = 1;
lg.l_linger = conf.timeouts[STRING_L];
sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP);
}
else {
sock=so._socket(SASOCK(&srv.intsa), SOCK_DGRAM, IPPROTO_UDP);
}
if( sock == INVALID_SOCKET) {
perror("socket()");
return -2;
}
#ifdef _WIN32
ioctlsocket(sock, FIONBIO, &ul);
#else
fcntl(sock,F_SETFL,O_NONBLOCK);
#endif
srv.srvsock = sock;
if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()");
#ifdef SO_REUSEPORT
so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
#endif
}
size = sizeof(srv.intsa);
for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, size)==-1; usleep(sleeptime)) {
sprintf((char *)buf, "bind(): %s", strerror(errno));
if(!srv.silent)(*srv.logfunc)(&defparam, buf);
sleeptime = (sleeptime<<1);
if(!sleeptime) {
so._closesocket(sock);
return -3;
}
}
if(!isudp){
if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) {
sprintf((char *)buf, "listen(): %s", strerror(errno));
if(!srv.silent)(*srv.logfunc)(&defparam, buf);
return -4;
}
}
else
defparam.clisock = sock;
if(!srv.silent && !iscbc){
sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
(*srv.logfunc)(&defparam, buf);
}
}
else {
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
}
if(iscbl){
parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa);
if((srv.cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) {
(*srv.logfunc)(&defparam, "Failed to allocate connect back socket");
return -6;
}
if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, sizeof(cbsa))==-1) {
(*srv.logfunc)(&defparam, "Failed to bind connect back socket");
return -7;
}
if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) {
(*srv.logfunc)(&defparam, "Failed to listen connect back socket");
return -8;
}
}
srv.fds.fd = sock; srv.fds.fd = sock;
srv.fds.events = POLLIN; srv.fds.events = POLLIN;
@ -419,6 +497,7 @@ int MODULEMAINFUNC (int argc, char** argv){
} }
usleep(SLEEPTIME); usleep(SLEEPTIME);
} }
if (iscbc) break;
if (conf.paused != srv.version) break; if (conf.paused != srv.version) break;
if (srv.fds.events & POLLIN) { if (srv.fds.events & POLLIN) {
error = so._poll(&srv.fds, 1, 1000); error = so._poll(&srv.fds, 1, 1000);
@ -439,11 +518,23 @@ int MODULEMAINFUNC (int argc, char** argv){
if((conf.paused != srv.version) || (error < 0)) break; if((conf.paused != srv.version) || (error < 0)) break;
if(!isudp){ if(!isudp){
size = sizeof(defparam.sincr); size = sizeof(defparam.sincr);
new_sock = so._accept(sock, (struct sockaddr*)&defparam.sincr, &size); if(iscbc){
if(new_sock == INVALID_SOCKET){ new_sock=so._socket(SASOCK(&defparam.sincr), SOCK_STREAM, IPPROTO_TCP);
sprintf((char *)buf, "accept(): %s", strerror(errno)); if(new_sock != INVALID_SOCKET){
if(!srv.silent)(*srv.logfunc)(&defparam, buf); if(so._connect(new_sock,(struct sockaddr *)&defparam.sincr,sizeof(defparam.sincr))) {
continue; so._closesocket(new_sock);
new_sock = INVALID_SOCKET;
continue;
}
}
}
else {
new_sock = so._accept(sock, (struct sockaddr*)&defparam.sincr, &size);
if(new_sock == INVALID_SOCKET){
sprintf((char *)buf, "accept(): %s", strerror(errno));
if(!srv.silent)(*srv.logfunc)(&defparam, buf);
continue;
}
} }
size = sizeof(defparam.sincl); size = sizeof(defparam.sincl);
if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){ if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){
@ -490,9 +581,9 @@ int MODULEMAINFUNC (int argc, char** argv){
} }
#ifdef _WIN32 #ifdef _WIN32
#ifndef _WINCE #ifndef _WINCE
h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread); h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, threadfunc, (void *) newparam, 0, &thread);
#else #else
h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)32768, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread); h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)32768, threadfunc, (void *) newparam, 0, &thread);
#endif #endif
srv.childcount++; srv.childcount++;
if (h) { if (h) {
@ -506,7 +597,7 @@ int MODULEMAINFUNC (int argc, char** argv){
} }
#else #else
error = pthread_create(&thread, &pa, (PTHREADFUNC)srv.pf, (void *)newparam); error = pthread_create(&thread, &pa, threadfunc, (void *)newparam);
srv.childcount++; srv.childcount++;
if(error){ if(error){
sprintf((char *)buf, "pthread_create(): %s", strerror(error)); sprintf((char *)buf, "pthread_create(): %s", strerror(error));
@ -527,6 +618,8 @@ int MODULEMAINFUNC (int argc, char** argv){
if(fp) fclose(fp); if(fp) fclose(fp);
srvfree(&srv); srvfree(&srv);
if(defparam.hostname)myfree(defparam.hostname); if(defparam.hostname)myfree(defparam.hostname);
if(cbc_string)myfree(cbc_string);
if(cbl_string)myfree(cbc_string);
#ifndef STDMAIN #ifndef STDMAIN
if(srv.next)srv.next->prev = srv.prev; if(srv.next)srv.next->prev = srv.prev;
@ -553,6 +646,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
srv->srvsock = INVALID_SOCKET; srv->srvsock = INVALID_SOCKET;
srv->logdumpsrv = conf.logdumpsrv; srv->logdumpsrv = conf.logdumpsrv;
srv->logdumpcli = conf.logdumpcli; srv->logdumpcli = conf.logdumpcli;
srv->cbsock = INVALID_SOCKET;
memset(param, 0, sizeof(struct clientparam)); memset(param, 0, sizeof(struct clientparam));
param->srv = srv; param->srv = srv;
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET; param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
@ -588,6 +682,7 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){
void srvfree(struct srvparam * srv){ void srvfree(struct srvparam * srv){
if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock); if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock);
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->cbsock);
srv->srvsock = INVALID_SOCKET; srv->srvsock = INVALID_SOCKET;
srv->service = S_ZOMBIE; srv->service = S_ZOMBIE;
while(srv->child) usleep(SLEEPTIME * 100); while(srv->child) usleep(SLEEPTIME * 100);

View File

@ -34,7 +34,6 @@ extern "C" {
#define pthread_mutex_lock(x) EnterCriticalSection(x) #define pthread_mutex_lock(x) EnterCriticalSection(x)
#define pthread_mutex_unlock(x) LeaveCriticalSection(x) #define pthread_mutex_unlock(x) LeaveCriticalSection(x)
#define pthread_mutex_destroy(x) DeleteCriticalSection(x) #define pthread_mutex_destroy(x) DeleteCriticalSection(x)
typedef unsigned (__stdcall *BEGINTHREADFUNC)(void *);
#ifdef MSVC #ifdef MSVC
#pragma warning (disable : 4996) #pragma warning (disable : 4996)
#endif #endif
@ -140,6 +139,8 @@ typedef enum {
S_FTPPR, S_FTPPR,
S_SMTPP, S_SMTPP,
S_ICQPR, S_ICQPR,
S_REVLI,
S_REVCO,
/* /*
S_MSNPR, S_MSNPR,
*/ */
@ -162,7 +163,6 @@ typedef void * (*EXTENDFUNC) (struct node *node);
typedef void (*CBFUNC)(void *cb, char * buf, int inbuf); typedef void (*CBFUNC)(void *cb, char * buf, int inbuf);
typedef void (*PRINTFUNC) (struct node *node, CBFUNC cbf, void*cb); typedef void (*PRINTFUNC) (struct node *node, CBFUNC cbf, void*cb);
typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv); typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv);
typedef void * (*PTHREADFUNC)(void *);
struct auth { struct auth {
struct auth *next; struct auth *next;
@ -360,7 +360,7 @@ struct srvparam {
LOGFUNC logfunc; LOGFUNC logfunc;
AUTHFUNC authfunc; AUTHFUNC authfunc;
PROXYFUNC pf; PROXYFUNC pf;
SOCKET srvsock; SOCKET srvsock, cbsock;
int childcount; int childcount;
int maxchild; int maxchild;
int version; int version;

View File

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