Fix UDP parent for SOCKSv5
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run

This commit is contained in:
Vladimir Dubrovin 2026-05-02 00:00:45 +03:00
parent 07c1dc1462
commit 4068a6955f
12 changed files with 128 additions and 72 deletions

View File

@ -10,10 +10,10 @@ CRYPT_PREFIX ?= $(PREFIX)
MANDIR ?= /usr/share/man MANDIR ?= /usr/share/man
CC ?= cc CC ?= cc
CFLAGS := -c -fno-strict-aliasing -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN $(CFLAGS) CFLAGS := -c -O3 -fno-strict-aliasing -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN $(CFLAGS)
COUT = -o COUT = -o
LN ?= ${CC} LN ?= ${CC}
LDFLAGS += -pthread -fno-strict-aliasing LDFLAGS += -g -flto -pthread -fno-strict-aliasing
# -lpthreads may be reuiured on some platforms instead of -pthreads # -lpthreads may be reuiured on some platforms instead of -pthreads
# -ldl or -lld may be required for some platforms # -ldl or -lld may be required for some platforms
DCFLAGS ?= -fPIC DCFLAGS ?= -fPIC

View File

@ -9,11 +9,11 @@ PREFIX ?= 3proxy_
CRYPT_PREFIX ?= $(PREFIX) CRYPT_PREFIX ?= $(PREFIX)
CC ?= gcc CC ?= gcc
CFLAGS := -g -fPIC -O2 -fno-strict-aliasing -c -pthread -DWITHSPLICE -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN $(CFLAGS) CFLAGS := -g -fPIC -O3 -fno-strict-aliasing -c -pthread -DWITHSPLICE -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN $(CFLAGS)
COUT = -o COUT = -o
LN ?= ${CC} LN ?= ${CC}
DCFLAGS ?= DCFLAGS ?=
LDFLAGS := -fPIC -O2 -fno-strict-aliasing -pthread $(LDFLAGS) LDFLAGS := -fPIC -O3 -fno-strict-aliasing -pthread $(LDFLAGS)
DLFLAGS ?= -shared DLFLAGS ?= -shared
DLSUFFICS = .ld.so DLSUFFICS = .ld.so
# -lpthreads may be reuqired on some platforms instead of -pthreads # -lpthreads may be reuqired on some platforms instead of -pthreads

View File

@ -45,7 +45,7 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
} }
if(!ipentry) return 0; if(!ipentry) return 0;
} }
if((acentry->dst && (!SAISNULL(&param->req) || param->operation == UDPASSOC || param->operation==BIND)) || (acentry->dstnames && param->hostname)) { if((acentry->dst && (!SAISNULL(&param->req) || param->operation==BIND)) || (acentry->dstnames && param->hostname)) {
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next) for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->req, ipentry)) { if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
break; break;
@ -93,7 +93,7 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
} }
if(!ipentry && !hstentry) return 0; if(!ipentry && !hstentry) return 0;
} }
if(acentry->ports && (*SAPORT(&param->req) || param->operation == UDPASSOC || param->operation == BIND)) { if(acentry->ports && (*SAPORT(&param->req) || param->operation == BIND)) {
for (portentry = acentry->ports; portentry; portentry = portentry->next) for (portentry = acentry->ports; portentry; portentry = portentry->next)
if(ntohs(*SAPORT(&param->req)) >= portentry->startport && if(ntohs(*SAPORT(&param->req)) >= portentry->startport &&
ntohs(*SAPORT(&param->req)) <= portentry->endport) { ntohs(*SAPORT(&param->req)) <= portentry->endport) {
@ -143,13 +143,14 @@ int checkACL(struct clientparam * param){
struct ace dup; struct ace dup;
int res=60,i=0; int res=60,i=0;
if(param->operation < 256 && !(param->operation & CONNECT)){
if(param->operation < 256 && !(param->operation & (CONNECT|UDPASSOC))){
continue; continue;
} }
if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) { if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) {
continue; continue;
} }
if(param->remsock != INVALID_SOCKET) { if(param->remsock != INVALID_SOCKET && (param->operation != UDPASSOC || param->ctrlsocksrv != INVALID_SOCKET)) {
return 0; return 0;
} }
for(; i < conf.parentretries; i++){ for(; i < conf.parentretries; i++){

View File

@ -557,9 +557,10 @@ int doconnect(struct clientparam * param){
if (*SAFAMILY(&param->sincl) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincl), SAADDR(&param->req), SAADDRLEN(&param->req)) && if (*SAFAMILY(&param->sincl) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincl), SAADDR(&param->req), SAADDRLEN(&param->req)) &&
*SAPORT(&param->sincl) == *SAPORT(&param->req)) return 519; *SAPORT(&param->sincl) == *SAPORT(&param->req)) return 519;
if (param->operation == ADMIN || param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC) if (param->operation == ADMIN || (( param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC) && !param->redirected))
return 0; return 0;
if (param->remsock != INVALID_SOCKET){ if (param->remsock != INVALID_SOCKET){
if(param->operation == UDPASSOC) return 0;
size = sizeof(param->sinsr); size = sizeof(param->sinsr);
if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);} if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);}
} }
@ -632,7 +633,7 @@ int doconnect(struct clientparam * param){
return 12; return 12;
} }
if(param->operation >= 256 || (param->operation & CONNECT)){ if(param->operation >= 256 || (param->operation & CONNECT) || param->redirected){
if(connectwithpoll(param, param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),conf.timeouts[CONNECT_TO])) { if(connectwithpoll(param, param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),conf.timeouts[CONNECT_TO])) {
return 13; return 13;
} }
@ -646,7 +647,6 @@ int doconnect(struct clientparam * param){
action = handleconnectflt(param); action = handleconnectflt(param);
if(action != PASS) return 19; if(action != PASS) return 19;
} }
return 0; return 0;
} }

View File

@ -35,7 +35,6 @@
#define _PASSWORD_LEN 256 #define _PASSWORD_LEN 256
#define MAXNSERVERS 5 #define MAXNSERVERS 5
#define UDPBUFSIZE 16384
#define TCPBUFSIZE 65536 #define TCPBUFSIZE 65536
#define SRVBUFSIZE (param->srv->bufsize?param->srv->bufsize:((param->service == S_UDPPM)?UDPBUFSIZE:TCPBUFSIZE)) #define SRVBUFSIZE (param->srv->bufsize?param->srv->bufsize:((param->service == S_UDPPM)?UDPBUFSIZE:TCPBUFSIZE))
@ -231,7 +230,7 @@ void dumpcounters(struct trafcount *tl, int counterd);
int startconnlims (struct clientparam *param); int startconnlims (struct clientparam *param);
void stopconnlims (struct clientparam *param); void stopconnlims (struct clientparam *param);
int socks5_udp_build_hdr(unsigned char *buf, PROXYSOCKADDRTYPE *addr);
extern struct auth authfuncs[]; extern struct auth authfuncs[];

View File

@ -251,10 +251,6 @@ int MODULEMAINFUNC (int argc, char** argv){
unsigned char buf[256]; unsigned char buf[256];
char *hostname=NULL; char *hostname=NULL;
int opt = 1, isudp = 0, iscbl = 0, iscbc = 0; int opt = 1, isudp = 0, iscbl = 0, iscbc = 0;
#ifndef NOUDPMAIN
unsigned char *udpbuf = NULL;
int udplen = 0;
#endif
unsigned char *cbc_string = NULL, *cbl_string = NULL; unsigned char *cbc_string = NULL, *cbl_string = NULL;
PROXYSOCKADDRTYPE cbsa; PROXYSOCKADDRTYPE cbsa;
FILE *fp = NULL; FILE *fp = NULL;
@ -343,7 +339,6 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef NOUDPMAIN #ifndef NOUDPMAIN
if(isudp) { if(isudp) {
if(!udp_table.ihashtable)inithashtable(&udp_table, 64, 256, 65536); if(!udp_table.ihashtable)inithashtable(&udp_table, 64, 256, 65536);
if(!(udpbuf = myalloc(UDPBUFSIZE))) return 21;
} }
#endif #endif
srv.service = defparam.service = childdef.service; srv.service = defparam.service = childdef.service;
@ -926,14 +921,25 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef NOUDPMAIN #ifndef NOUDPMAIN
else { else {
struct clientparam *toparam; struct clientparam *toparam;
udplen = sockrecvfrom(NULL, srv.srvsock, (struct sockaddr *)&defparam.sincr, udpbuf, UDPBUFSIZE, 0);
if(udplen <= 0) continue; srv.udplen = sockrecvfrom(NULL, srv.srvsock, (struct sockaddr *)&defparam.sincr, srv.udpbuf, UDPBUFSIZE, 0);
if(srv.udplen <= 0) continue;
_3proxy_sem_lock(udpinit); _3proxy_sem_lock(udpinit);
if(hashresolv(&udp_table, &defparam, &toparam, NULL)) { if(hashresolv(&udp_table, &defparam, &toparam, NULL)) {
srv.so._sendto(toparam->sostate, toparam->remsock, (char *)udpbuf, udplen, 0, (struct sockaddr *)&toparam->sinsr, SASIZE(&toparam->sinsr)); int i, len=0;
_3proxy_sem_unlock(udpinit);
toparam->statscli64 += udplen; if(toparam->udp_nhops - 1){
for(i=1; i < toparam->udp_nhops - 1; i++){
len+=socks5_udp_build_hdr(srv.udpbuf2+len, &toparam->udp_relay[i-1]);
}
len += socks5_udp_build_hdr(srv.udpbuf2+len, &toparam->req);
}
memcpy(srv.udpbuf2+len, srv.udpbuf, srv.udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : srv.udplen);
len += srv.udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : srv.udplen;
srv.so._sendto(toparam->sostate, toparam->remsock, (char *)srv.udpbuf2, len, 0, (struct sockaddr *)&toparam->sinsr, SASIZE(&toparam->sinsr));
toparam->statscli64 += srv.udplen;
toparam->nwrites++; toparam->nwrites++;
_3proxy_sem_unlock(udpinit);
continue; continue;
} }
} }
@ -964,18 +970,6 @@ int MODULEMAINFUNC (int argc, char** argv){
#endif #endif
continue; continue;
} }
#endif
#ifndef NOUDPMAIN
if(isudp) {
if(!(newparam->srvbuf = myalloc(UDPBUFSIZE))){
freeparam(newparam);
_3proxy_sem_unlock(udpinit);
continue;
}
newparam->srvbufsize = UDPBUFSIZE;
newparam->srvinbuf = udplen;
memcpy(newparam->srvbuf, udpbuf, udplen);
}
#endif #endif
newparam->prev = newparam->next = NULL; newparam->prev = newparam->next = NULL;
error = 0; error = 0;
@ -1047,9 +1041,6 @@ int MODULEMAINFUNC (int argc, char** argv){
if(cbc_string)myfree(cbc_string); if(cbc_string)myfree(cbc_string);
if(cbl_string)myfree(cbl_string); if(cbl_string)myfree(cbl_string);
if(fp) fclose(fp); if(fp) fclose(fp);
#ifndef NOUDPMAIN
myfree(udpbuf);
#endif
return 0; return 0;
} }

View File

@ -24,7 +24,6 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
int len=0; int len=0;
unsigned char * user, *pass; unsigned char * user, *pass;
user = redir->extuser; user = redir->extuser;
pass = redir->extpass; pass = redir->extpass;
if (!param->srvbufsize){ if (!param->srvbufsize){
@ -135,9 +134,9 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
int atyp; int atyp;
int skip_port = 0; int skip_port = 0;
buf[0] = 5; buf[0] = 5;
buf[1] = 1; buf[1] = user? 1 : 0;
buf[2] = user? 2 : 0; buf[2] = 2;
if(socksend(param, param->remsock, buf, 3, conf.timeouts[CHAIN_TO]) != 3){ if(socksend(param, param->remsock, buf, user?3:2, conf.timeouts[CHAIN_TO]) < 2){
return 51; return 51;
} }
param->statssrv64+=3; param->statssrv64+=3;
@ -172,9 +171,9 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
} }
} }
buf[0] = 5; buf[0] = 5;
buf[1] = (param->operation == UDPASSOC && redir->type != R_SOCKS5B) ? 3 : 1; buf[1] = (param->operation == UDPASSOC) ? 3 : 1;
buf[2] = 0; buf[2] = 0;
if (param->operation == UDPASSOC && redir->type != R_SOCKS5B) { if (param->operation == UDPASSOC) {
buf[3] = 1; buf[3] = 1;
memset(buf + 4, 0, 6); memset(buf + 4, 0, 6);
len = 10; len = 10;
@ -219,7 +218,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
return 59; return 59;
case 3: case 3:
if (sockgetlinebuf(param, SERVER, buf, 1, EOF, conf.timeouts[CHAIN_TO]) != 1) return 59; if (sockgetlinebuf(param, SERVER, buf, 1, EOF, conf.timeouts[CHAIN_TO]) != 1) return 59;
len = (unsigned char)buf[0]; len = (unsigned char)buf[4];
if (sockgetlinebuf(param, SERVER, buf, len + 2, EOF, conf.timeouts[CHAIN_TO]) != len + 2) return 59; if (sockgetlinebuf(param, SERVER, buf, len + 2, EOF, conf.timeouts[CHAIN_TO]) != len + 2) return 59;
break; break;
case 4: case 4:
@ -233,15 +232,17 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
PROXYSOCKADDRTYPE *relay = &param->udp_relay[param->udp_nhops]; PROXYSOCKADDRTYPE *relay = &param->udp_relay[param->udp_nhops];
memset(relay, 0, sizeof(*relay)); memset(relay, 0, sizeof(*relay));
if (atyp == 1) { if (atyp == 1) {
((struct sockaddr_in *)relay)->sin_family = AF_INET; *SAFAMILY(relay) = AF_INET;
memcpy(&((struct sockaddr_in *)relay)->sin_addr, buf, 4); memcpy(SAADDR(relay), buf, 4);
memcpy(&((struct sockaddr_in *)relay)->sin_port, buf + 4, 2); memcpy(SAPORT(relay), buf + 4, 2);
if (param->udp_nhops == 0) param->sinsr = *relay; if (param->udp_nhops == 0) {
param->sinsr = *relay;
}
param->udp_nhops++; param->udp_nhops++;
} else if (atyp == 4) { } else if (atyp == 4) {
((struct sockaddr_in6 *)relay)->sin6_family = AF_INET6; *SAFAMILY(relay) = AF_INET6;
memcpy(&((struct sockaddr_in6 *)relay)->sin6_addr, buf, 16); memcpy(SAADDR(relay), buf, 16);
memcpy(&((struct sockaddr_in6 *)relay)->sin6_port, buf + 16, 2); memcpy(SAPORT(relay), buf + 16, 2);
if (param->udp_nhops == 0) param->sinsr = *relay; if (param->udp_nhops == 0) param->sinsr = *relay;
param->udp_nhops++; param->udp_nhops++;
} }
@ -265,9 +266,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
struct chain * cur; struct chain * cur;
struct chain * redir = NULL; struct chain * redir = NULL;
int r2; int r2;
int saved = 0;
if(param->remsock != INVALID_SOCKET) { if(param->remsock != INVALID_SOCKET && param->operation != UDPASSOC) {
return 0;
} }
if((SAISNULL(&param->req) || !*SAPORT(&param->req)) && param->operation != UDPASSOC) { if((SAISNULL(&param->req) || !*SAPORT(&param->req)) && param->operation != UDPASSOC) {
return 100; return 100;
@ -352,7 +353,13 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
else { else {
param->sinsr = cur->addr; param->sinsr = cur->addr;
} }
if(param->operation == UDPASSOC){
SOCKET s;
s = param->remsock;
param->remsock = INVALID_SOCKET;
param->ctrlsocksrv = s;
saved = 1;
}
if((res = alwaysauth(param))){ if((res = alwaysauth(param))){
return (res >= 10)? res : 60+res; return (res >= 10)? res : 60+res;
} }
@ -397,5 +404,15 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
} }
if(!connected || !redir) return 0; if(!connected || !redir) return 0;
return clientnegotiate(redir, param, (struct sockaddr *)&param->req, param->hostname); res = clientnegotiate(redir, param, (struct sockaddr *)&param->req, param->hostname);
if(saved){
SOCKET s;
s = param->ctrlsocksrv;
param->ctrlsocksrv = param->remsock;
param->remsock = s;
param->operation = UDPASSOC;
}
return res;
} }

View File

@ -314,6 +314,11 @@ log(logbuf);
} }
else { else {
FROMCLIENTPIPE = TOSERVER = 0; FROMCLIENTPIPE = TOSERVER = 0;
if(errno && errno != EINTR && errno != EAGAIN) {
SERVERTERMREAD = 1;
SERVERTERMWRITE = 1;
HASERROR |= 2;
}
} }
} }
if(inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){ if(inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){
@ -339,6 +344,11 @@ log(logbuf);
} }
else { else {
FROMSERVERPIPE = TOCLIENT = 0; FROMSERVERPIPE = TOCLIENT = 0;
if(errno && errno != EINTR && errno != EAGAIN) {
CLIENTTERMREAD = 1;
CLIENTTERMWRITE = 1;
HASERROR |= 1;
}
} }
} }
if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE){ if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE){
@ -364,6 +374,11 @@ log(logbuf);
CLIENTTERMREAD = 1; CLIENTTERMREAD = 1;
continue; continue;
} }
if(errno && errno != EINTR && errno != EAGAIN) {
CLIENTTERMREAD = 1;
CLIENTTERMWRITE = 1;
continue;
}
} }
else { else {
#ifdef WITHLOG #ifdef WITHLOG
@ -401,6 +416,11 @@ log(logbuf);
SERVERTERMREAD = 1; SERVERTERMREAD = 1;
continue; continue;
} }
if(errno && errno != EINTR && errno != EAGAIN) {
SERVERTERMREAD = 1;
SERVERTERMWRITE = 1;
continue;
}
} }
else { else {
#ifdef WITHLOG #ifdef WITHLOG
@ -499,11 +519,19 @@ log("done read from server to buf");
} }
} }
} }
if (CLIENTTERMREAD && !inclientbuf && !SERVERTERMWRITE) { if (CLIENTTERMREAD && !inclientbuf
#ifdef WITHSPLICE
&& !inclientpipe
#endif
&& !SERVERTERMWRITE) {
SERVERTERMWRITE = 1; SERVERTERMWRITE = 1;
param->srv->so._shutdown(param->sostate, param->remsock, SHUT_WR); param->srv->so._shutdown(param->sostate, param->remsock, SHUT_WR);
} }
if (SERVERTERMREAD && !inserverbuf && !CLIENTTERMWRITE) { if (SERVERTERMREAD && !inserverbuf
#ifdef WITHSPLICE
&& !inserverpipe
#endif
&& !CLIENTTERMWRITE) {
CLIENTTERMWRITE = 1; CLIENTTERMWRITE = 1;
param->srv->so._shutdown(param->sostate, param->clisock, SHUT_WR); param->srv->so._shutdown(param->sostate, param->clisock, SHUT_WR);
} }

View File

@ -85,7 +85,7 @@ void * sockschild(struct clientparam* param) {
} }
if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
RETURN(421); RETURN(421);
} /* version */ }
} }
if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
if(ver == 5){ if(ver == 5){

View File

@ -183,7 +183,7 @@ int
#endif #endif
#define MAX_HASH_SIZE (16) #define MAX_HASH_SIZE (16)
#define UDPBUFSIZE 16384
extern char* NULLADDR; extern char* NULLADDR;
typedef enum { typedef enum {
@ -517,6 +517,11 @@ struct srvparam {
AUTHFUNC authfunc; AUTHFUNC authfunc;
PROXYFUNC pf; PROXYFUNC pf;
SOCKET srvsock, cbsock; SOCKET srvsock, cbsock;
#ifndef NOUDPMAIN
unsigned char udpbuf[UDPBUFSIZE];
unsigned char udpbuf2[UDPBUFSIZE];
int udplen;
#endif
int childcount; int childcount;
int maxchild; int maxchild;
int backlog; int backlog;

View File

@ -29,11 +29,15 @@ static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash
} }
struct hashtable udp_table = {udpparam2hash, udpparam2hash, sizeof(struct clientparam *), 8}; struct hashtable udp_table = {udpparam2hash, udpparam2hash, sizeof(struct clientparam *), 8};
int socks5_udp_build_hdr(unsigned char *buf, PROXYSOCKADDRTYPE *addr);
void * udppmchild(struct clientparam* param) { void * udppmchild(struct clientparam* param) {
int authres; int authres;
int i;
int len = 0;
if(parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) { RETURN(201) } if(parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) { RETURN(201) }
#ifndef NOIPV6 #ifndef NOIPV6
memcpy(&param->sinsl, *SAFAMILY(&param->req) == AF_INET6 ? (struct sockaddr *)&param->srv->extsa6 : (struct sockaddr *)&param->srv->extsa, SASIZE(&param->req)); memcpy(&param->sinsl, *SAFAMILY(&param->req) == AF_INET6 ? (struct sockaddr *)&param->srv->extsa6 : (struct sockaddr *)&param->srv->extsa, SASIZE(&param->req));
#else #else
@ -53,13 +57,25 @@ void * udppmchild(struct clientparam* param) {
authres = (*param->srv->authfunc)(param); authres = (*param->srv->authfunc)(param);
if(authres) { RETURN(authres); } if(authres) { RETURN(authres); }
if(!param->srv->singlepacket)hashadd(&udp_table, param, &param, MAX_COUNTER_TIME); if(!param->srv->singlepacket)hashadd(&udp_table, param, &param, MAX_COUNTER_TIME);
param->srv->so._sendto(param->sostate, param->remsock, (char *)param->srvbuf, param->srvinbuf, 0, (struct sockaddr *)&param->sinsr, SASIZE(&param->sinsr)); if(!param->srvbuf){
if(!(param->srvbuf = myalloc(UDPBUFSIZE)))RETURN(11);
param->srvbufsize = UDPBUFSIZE;
}
if(param->udp_nhops){
for(i=1; i < param->udp_nhops; i++){
len+=socks5_udp_build_hdr(param->srvbuf+len, &param->udp_relay[i-1]);
}
len += socks5_udp_build_hdr(param->srvbuf+len, &param->req);
}
memcpy(param->srvbuf+len, param->srv->udpbuf, param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen);
len += param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen;
param->srv->so._sendto(param->sostate, param->remsock, (char *)param->srvbuf, len, 0, (struct sockaddr *)&param->sinsr, SASIZE(&param->sinsr));
_3proxy_sem_unlock(udpinit); _3proxy_sem_unlock(udpinit);
param->statscli64 += param->srvinbuf; param->statscli64 += param->srvinbuf;
param->srvinbuf = 0; param->srvinbuf = 0;
param->nwrites++; param->nwrites++;
param->clisock = param->srv->srvsock; param->clisock = param->srv->srvsock;
param->udp_nhops = 1; param->udp_nhops++;
param->waitserver64 = 0x7fffffffffffffff; param->waitserver64 = 0x7fffffffffffffff;
param->res = udpsockmap(param, conf.timeouts[STRING_L]); param->res = udpsockmap(param, conf.timeouts[STRING_L]);
_3proxy_sem_lock(udpinit); _3proxy_sem_lock(udpinit);

View File

@ -8,7 +8,7 @@
#include "proxy.h" #include "proxy.h"
static int socks5_udp_build_hdr(unsigned char *buf, PROXYSOCKADDRTYPE *addr) int socks5_udp_build_hdr(unsigned char *buf, PROXYSOCKADDRTYPE *addr)
{ {
buf[0] = buf[1] = buf[2] = 0; buf[0] = buf[1] = buf[2] = 0;
buf[3] = (*SAFAMILY(addr) == AF_INET) ? 1 : 4; buf[3] = (*SAFAMILY(addr) == AF_INET) ? 1 : 4;
@ -57,7 +57,6 @@ int udpsockmap(struct clientparam *param, int timeo)
int nhops = param->udp_nhops; int nhops = param->udp_nhops;
int clisock_idx = -1, ctrlsock_idx = -1, ctrlsocksrv_idx = -1; int clisock_idx = -1, ctrlsock_idx = -1, ctrlsocksrv_idx = -1;
int firstpacket = 1; int firstpacket = 1;
if (param->srvbufsize < UDPBUFSIZE) { if (param->srvbufsize < UDPBUFSIZE) {
unsigned char *newbuf = myrealloc(param->srvbuf, UDPBUFSIZE); unsigned char *newbuf = myrealloc(param->srvbuf, UDPBUFSIZE);
if (!newbuf) return 21; if (!newbuf) return 21;
@ -92,7 +91,7 @@ int udpsockmap(struct clientparam *param, int timeo)
for (;;) { for (;;) {
res = param->srv->so._poll(param->sostate, fds, nfds, timeo * 1000); res = param->srv->so._poll(param->sostate, fds, nfds, timeo * 1000);
if (res < 0) return 463; if (res < 0) return 481;
if (res == 0) return 92; if (res == 0) return 92;
/* datagram from client */ /* datagram from client */
@ -104,7 +103,7 @@ int udpsockmap(struct clientparam *param, int timeo)
len = param->srv->so._recvfrom(param->sostate, param->clisock, len = param->srv->so._recvfrom(param->sostate, param->clisock,
(char *)param->srvbuf + recvoff, UDPBUFSIZE - recvoff, (char *)param->srvbuf + recvoff, UDPBUFSIZE - recvoff,
0, (struct sockaddr *)&sin, &sasize); 0, (struct sockaddr *)&sin, &sasize);
if (len <= 0) return 464; if (len <= 0) return 482;
if (SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || if (SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) ||
memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))) memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin)))
@ -119,7 +118,7 @@ int udpsockmap(struct clientparam *param, int timeo)
if (nhops == 0) { if (nhops == 0) {
int i; int i;
if (len < 10 || param->srvbuf[0] || param->srvbuf[1] || param->srvbuf[2]) if (len < 10 || param->srvbuf[0] || param->srvbuf[1] || param->srvbuf[2])
return 466; return 483;
switch (param->srvbuf[3]) { switch (param->srvbuf[3]) {
case 1: case 1:
*SAFAMILY(&param->sinsr) = AF_INET; *SAFAMILY(&param->sinsr) = AF_INET;
@ -127,14 +126,14 @@ int udpsockmap(struct clientparam *param, int timeo)
i = 8; i = 8;
break; break;
case 4: case 4:
if (len < 22) return 466; if (len < 22) return 484;
*SAFAMILY(&param->sinsr) = AF_INET6; *SAFAMILY(&param->sinsr) = AF_INET6;
memcpy(SAADDR(&param->sinsr), param->srvbuf + 4, 16); memcpy(SAADDR(&param->sinsr), param->srvbuf + 4, 16);
i = 20; i = 20;
break; break;
case 3: { case 3: {
int sz = param->srvbuf[4], j; int sz = param->srvbuf[4], j;
if (len < 7 + sz) return 466; if (len < 7 + sz) return 485;
for (j = 4; j < 4 + sz; j++) param->srvbuf[j] = param->srvbuf[j + 1]; for (j = 4; j < 4 + sz; j++) param->srvbuf[j] = param->srvbuf[j + 1];
param->srvbuf[4 + sz] = 0; param->srvbuf[4 + sz] = 0;
i = 5 + sz; i = 5 + sz;
@ -175,7 +174,7 @@ int udpsockmap(struct clientparam *param, int timeo)
len = param->srv->so._recvfrom(param->sostate, param->remsock, len = param->srv->so._recvfrom(param->sostate, param->remsock,
(char *)param->srvbuf + hdrsize, UDPBUFSIZE - hdrsize, 0, (char *)param->srvbuf + hdrsize, UDPBUFSIZE - hdrsize, 0,
(struct sockaddr *)&from, &sasize); (struct sockaddr *)&from, &sasize);
if (len <= 0) return 468; if (len <= 0) return 486;
if (nhops >= 1) { if (nhops >= 1) {
if (!SAISNULL(&param->sinsr) && *SAPORT(&param->sinsr)) { if (!SAISNULL(&param->sinsr) && *SAPORT(&param->sinsr)) {
if (SAADDRLEN(&from) != SAADDRLEN(&param->sinsr) || if (SAADDRLEN(&from) != SAADDRLEN(&param->sinsr) ||