From 6faae6d0c1a6d691b83bc74204b446e8c63597b5 Mon Sep 17 00:00:00 2001 From: VasiliPupkin256 <27725951+VasiliPupkin256@users.noreply.github.com> Date: Mon, 3 Aug 2020 23:48:54 +0300 Subject: [PATCH] An attempt to fix UDP ASSOCIATE mode --- src/socks.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/socks.c b/src/socks.c index 899790a..ddf3e8d 100644 --- a/src/socks.c +++ b/src/socks.c @@ -348,23 +348,34 @@ fflush(stderr); break; } if (fds[1].revents) { + // if we cant relay packet forward (can't resolve address or whatever) + // there is no way to report this individual error to the client + // so we silently drop it instead of closing the ASSOCIATION sasize = sizeof(sin); - if((len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { + if((len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) < 0) { param->res = 464; break; } if(SAADDRLEN(&sin) != SAADDRLEN(¶m->sincr) || memcmp(SAADDR(&sin), SAADDR(¶m->sincr), SAADDRLEN(&sin))){ - param->res = 465; - break; + // dropping packet recieved from an address that not belong to client + continue; } + // we remember the client port on each relay + // it is not perfect, some packets may come from a previously connected client + // or being a miliciously formed by a hacker + // ideally we should build an association table between local and remote addresses + // but well... + *SAPORT(¶m->sincr) = *SAPORT(&sin); if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } size = 4; + if(len <= 10) continue; switch(buf[3]) { case 4: size = 16; + if(len <= 10 + 16 - 4) continue; case 1: i = 4+size; memcpy(SAADDR(¶m->sinsr), buf+4, size); @@ -372,11 +383,12 @@ fflush(stderr); break; case 3: size = buf[4]; + if(len <= 10 + size - 4) continue; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; - if(!getip46(param->srv->family, buf+4, (struct sockaddr *) ¶m->sinsr)) RETURN(100); + if(!getip46(param->srv->family, buf+4, (struct sockaddr *) ¶m->sinsr)) continue; break; default: RETURN(997); @@ -388,8 +400,7 @@ fflush(stderr); sasize = sizeof(param->sinsr); if(len > (int)i){ if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ - param->res = 467; - break; + continue; } param->statscli64+=(len - i); param->nwrites++; @@ -413,7 +424,7 @@ fflush(stderr); sasize = sizeof(param->sinsr); buf[0]=buf[1]=buf[2]=0; buf[3]=(*SAFAMILY(¶m->sinsl) == AF_INET)?1:4; - if((len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(¶m->sinsl), 65535 - 10, 0, (struct sockaddr *)¶m->sinsr, &sasize)) <= 0) { + if((len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(¶m->sinsl), 65535 - 10, 0, (struct sockaddr *)¶m->sinsr, &sasize)) < 0) { param->res = 468; break; } @@ -421,10 +432,16 @@ fflush(stderr); param->nreads++; memcpy(buf+4, SAADDR(¶m->sinsr), SAADDRLEN(¶m->sinsr)); memcpy(buf+4+SAADDRLEN(¶m->sinsr), SAPORT(¶m->sinsr), 2); - sasize = sizeof(sin); - if(socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(¶m->sinsr), conf.timeouts[SINGLEBYTE_L]*1000) <=0){ - param->res = 469; - break; + + if(*SAPORT(¶m->sincr) == 0 || *(uint32_t*)SAADDR(¶m->sincr) == 0){ + // client hasn't connected yet so we don't know his address + // dropping incoming packet + continue; + } + + sasize = sizeof(param->sincr); + if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len + 6 + SAADDRLEN(¶m->sinsr), conf.timeouts[SINGLEBYTE_L]*1000) <=0){ + continue; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",