Compare commits

...

3 Commits

Author SHA1 Message Date
Vladimir Dubrovin
4fb5c95704 Print error on non-zero local redirection in conf
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
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-08-12 17:08:09 +03:00
Vladimir Dubrovin
13a57812e5 Fix: -Ne/-Ni, -4 / -6 handling for udp mapping in socks, mixed family support in udp 2026-08-12 16:25:12 +03:00
Vladimir Dubrovin
a43c95023d Check DNS reply source in udpresolve 2026-08-12 15:32:30 +03:00
7 changed files with 108 additions and 43 deletions

View File

@ -9,6 +9,39 @@
#include "proxy.h"
/* returns 0 on success, 1 if atyp is not supported for family, 2 if the
address is null. The address is set in both the 0 and the 2 case. */
int socks5_setaddr(int family, int atyp, const unsigned char *addr, PROXYSOCKADDRTYPE *sa){
int i, len = 4;
memset(sa, 0, sizeof(*sa));
if(atyp == 4){
#ifdef NOIPV6
return 1;
#else
if(family == 4) return 1;
len = 16;
*SAFAMILY(sa) = AF_INET6;
memcpy(SAADDR(sa), addr, 16);
#endif
}
#ifndef NOIPV6
else if(family == 6){
unsigned char prefix[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
*SAFAMILY(sa) = AF_INET6;
memcpy(SAADDR(sa), prefix, 12);
memcpy(12 + (unsigned char *)SAADDR(sa), addr, 4);
}
#endif
else {
*SAFAMILY(sa) = AF_INET;
memcpy(SAADDR(sa), addr, 4);
}
for(i = 0; i < len && !addr[i]; i++);
return (i == len)? 2 : 0;
}
#ifdef __linux__
#include <sched.h>

View File

@ -839,6 +839,24 @@ static int h_parent(int argc, unsigned char **argv){
chains->cidr = atoi(cidr + 1);
}
*SAPORT(&chains->addr) = htons((uint16_t)atoi((char *)argv[4]));
switch(chains->type){
case R_POP3:
case R_SMTP:
case R_FTP:
case R_ADMIN:
case R_TLS:
case R_DNS:
case R_HA:
if(!SAISNULL(&chains->addr) || *SAPORT(&chains->addr)){
fprintf(stderr, "Chaining error: chain type (%s) is a local redirection, it requires 0.0.0.0 as address and 0 as port on line %d\n", argv[2], linenum);
free(chains->exthost);
free(chains);
return(4);
}
break;
default:
break;
}
if(argc > 5) chains->extuser = (unsigned char *)strdup((char *)argv[5]);
if(argc > 6) chains->extpass = (unsigned char *)strdup((char *)argv[6]);
if(!acl->chains) {

View File

@ -205,6 +205,7 @@ extern int timeouts[12];
int sockmap(struct clientparam * param, int timeo, int usesplice);
int udpsockmap(struct clientparam * param, int timeo);
int udpbind(struct clientparam * param);
int socks5_setaddr(int family, int atyp, const unsigned char *addr, PROXYSOCKADDRTYPE *sa);
#ifdef __linux__
int switch_ns(struct srvparam *srv, int target_fd);
#endif

View File

@ -505,8 +505,8 @@ int MODULEMAINFUNC (int argc, char** argv){
}
break;
case 'N':
if(argv[i][3] == 'e') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.extNat);
else if(argv[i][3] == 'i') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.intNat);
if(argv[i][2] == 'e') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.extNat);
else if(argv[i][2] == 'i') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.intNat);
else getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.extNat);
break;
case 'n':

View File

@ -3,6 +3,19 @@
struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}};
struct nserver authnserver;
static int dnsqmatch(const unsigned char *a, const unsigned char *b, int len){
int i;
for(i = 0; i < len; i++){
unsigned char c1 = a[i], c2 = b[i];
if(c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
if(c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
if(c1 != c2) return 1;
}
return 0;
}
uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth){
@ -23,9 +36,12 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
SOCKET sock;
uint32_t ttl;
PROXYSOCKADDRTYPE addr;
PROXYSOCKADDRTYPE from;
PROXYSOCKADDRTYPE *sinsr, *sinsl;
int usetcp = 0;
unsigned short serial = 1;
unsigned char qbuf[300];
int qlen;
buf = b+2;
@ -92,6 +108,9 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
buf[len++] = (makeauth == 1)? 0x0c : (af==AF_INET6? 0x1c:0x01);/* PTR:host address */
buf[len++] = 0;
buf[len++] = 1; /* INET */
qlen = len - 12;
memcpy(qbuf, buf + 12, qlen);
if(usetcp){
buf-=2;
*(unsigned short*)buf = htons(len);
@ -104,30 +123,41 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
continue;
}
if(param) param->statscli64 += len;
len = sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf, 4096, conf.timeouts[DNS_TO]*1000);
len = sockrecvfrom(NULL, sock, (struct sockaddr *)&from, buf, 4096, conf.timeouts[DNS_TO]*1000);
if(len > 13 && usetcp){
unsigned short us;
us = ntohs(*(unsigned short*)buf);
len-=2;
buf+=2;
if(us > 4096 || us < len) len = 0;
else if(us > len){
if(sockrecvfrom(NULL, sock, (struct sockaddr *)&from, buf+len, us-len, conf.timeouts[DNS_TO]*1000) != us-len) len = 0;
else len = us;
}
}
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
if(len <= 13) {
continue;
}
if(param) param->statssrv64 += len;
if(usetcp){
unsigned short us;
us = ntohs(*(unsigned short*)buf);
len-=2;
buf+=2;
if(us > 4096 || us < len || (us > len && sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf+len, us-len, conf.timeouts[DNS_TO]*1000) != us-len)) {
continue;
}
if(!usetcp && (*SAFAMILY(&from) != *SAFAMILY(sinsr) ||
memcmp(SAADDR(&from), SAADDR(sinsr), SAADDRLEN(sinsr)) ||
*SAPORT(&from) != *SAPORT(sinsr))) {
continue; /* not from the server we asked */
}
if(*(unsigned short *)buf != serial)continue;
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
return 0;
}
if(!(buf[2] & 0x80)) continue; /* not a response */
nq = buf[5] + (((unsigned short)buf[4])<<8);
if (nq != 1) {
continue; /* we did only 1 request */
}
if(len < 12 + qlen || dnsqmatch(buf + 12, qbuf, qlen)) {
continue; /* question does not match the query */
}
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
return 0;
}
for(k = 13; k<len && buf[k]; k++) {
}
k++;

View File

@ -107,38 +107,20 @@ void * sockschild(struct clientparam* param) {
}
size = 4;
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET;
switch(c) {
#ifndef NOIPV6
case 4:
if(param->srv->family == 4) RETURN(997);
size = 16;
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
#endif
case 1:
for (i = 0; i<size; i++){
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
buf[i] = (unsigned char)res;
}
#ifndef NOIPV6
if (c == 1 && param->srv->family==6){
char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
memcpy(SAADDR(&param->sinsr), prefix, 12);
memcpy(12 + (char *)SAADDR(&param->sinsr), buf, 4);
memcpy(SAADDR(&param->req), prefix, 12);
memcpy(12 + (char *)SAADDR(&param->req), buf, 4);
}
else {
#endif
memcpy(SAADDR(&param->sinsr), buf, size);
memcpy(SAADDR(&param->req), buf, size);
#ifndef NOIPV6
}
#endif
if(command == 1 && SAISNULL(&param->req)) {
RETURN(431);
}
res = socks5_setaddr(param->srv->family, c, buf, &param->req);
if(res == 1) {RETURN(997);}
if(res == 2 && command == 1) {RETURN(431);}
param->sinsr = param->req;
myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
break;
case 3:
@ -285,7 +267,7 @@ CLEANRET:
sasize = sizeof(sin);
if(command != 3 && param->remsock != INVALID_SOCKET) param->srv->so._getsockname(param->sostate, param->remsock, (struct sockaddr *)&sin, &sasize);
if(!SAISNULL(&param->srv->extNat)){
if(command != 3 && !SAISNULL(&param->srv->extNat)){
uint16_t port;
port = *SAPORT(&sin);
sin = param->srv->extNat;
@ -293,7 +275,7 @@ CLEANRET:
}
else {
param->srv->so._getsockname(param->sostate, param->clisock, (struct sockaddr *)&sin, &sasize);
if(!SAISNULL(&param->srv->intNat)){
if(command == 3 && !SAISNULL(&param->srv->intNat)){
uint16_t port;
port = *SAPORT(&sin);
sin = param->srv->intNat;

View File

@ -257,16 +257,16 @@ int udpsockmap(struct clientparam *param, int timeo)
memset(&dst, 0, sizeof(dst));
switch (base[3]) {
case 1:
*SAFAMILY(&dst) = AF_INET;
memcpy(SAADDR(&dst), base + 4, 4);
if (socks5_setaddr(param->srv->family, 1, base + 4, &dst)) continue;
i = 8;
break;
#ifndef NOIPV6
case 4:
if (len < 22) return 484;
*SAFAMILY(&dst) = AF_INET6;
memcpy(SAADDR(&dst), base + 4, 16);
if (socks5_setaddr(param->srv->family, 4, base + 4, &dst)) continue;
i = 20;
break;
#endif
case 3: {
int sz = base[4];
if (len < 7 + sz) return 485;
@ -309,7 +309,8 @@ int udpsockmap(struct clientparam *param, int timeo)
if (!nhops) param->sinsr = dst;
if (!havedst) reconnect = 1;
else if ((param->srv->udpauth & 2) && !param->dstindep) {
else if (!nhops && *SAFAMILY(&dst) != *SAFAMILY(&param->sinsl)) reconnect = 1;
if (havedst && (param->srv->udpauth & 2) && !param->dstindep) {
param->preauth = 2;
ares = (*param->srv->authfunc)(param);
param->preauth = 0;