diff --git a/man/socks.8 b/man/socks.8 index 6bc127b..e8444ac 100644 --- a/man/socks.8 +++ b/man/socks.8 @@ -42,6 +42,16 @@ of IP-IP NAT (will not work for PAT) Internal address. IP address proxy accepts connections to. By default connection to any interface is accepted. It\'s usually unsafe. .TP +.B -k +External address given by +.B -e +is ignored and the internal address or generally the address client conected to is used instead. +This allows to utilize AnyIP Linux feature when +.B -i0.0.0.0 +or in case of IPv6 +.B -i:: +is set. Not available for Windows platform. +.TP .B -p Port. Port proxy listens for incoming connections. Default is 1080. .TP diff --git a/src/common.c b/src/common.c index ec25eb6..402072c 100644 --- a/src/common.c +++ b/src/common.c @@ -521,16 +521,48 @@ int doconnect(struct clientparam * param){ if(!*SAPORT(¶m->sinsr))*SAPORT(¶m->sinsr) = *SAPORT(¶m->req); if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);} if(SAISNULL(¶m->sinsl)){ + if (param->srv->keepip) { #ifndef NOIPV6 - if(*SAFAMILY(¶m->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6; - else + struct sockaddr_in6 local_addr; + socklen_t local_addr_len = sizeof(local_addr); + getsockname(param->clisock, (struct sockaddr *)&local_addr, &local_addr_len); + + if(*SAFAMILY(&local_addr) == AF_INET6) { + if (IN6_IS_ADDR_V4MAPPED(&local_addr.sin6_addr)) { + struct sockaddr_in6 local_addr2; + memset(&local_addr2, 0, sizeof(local_addr2)); + local_addr2.sin6_family = AF_INET; + local_addr2.sin6_port = local_addr.sin6_port; + param->sinsl = local_addr2; + } else { + param->sinsl = local_addr; + } + } else { + param->sinsl = local_addr; + } +#else + struct sockaddr_in local_addr; + socklen_t local_addr_len = sizeof(local_addr); + getsockname(new_sock, (struct sockaddr *)&local_addr, &local_addr_len); + param->sinsl = local_addr; #endif - param->sinsl = param->srv->extsa; + } else { +#ifndef NOIPV6 + if(*SAFAMILY(¶m->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6; + else +#endif + param->sinsl = param->srv->extsa; + } } *SAPORT(¶m->sinsl) = 0; setopts(param->remsock, param->srv->srvsockopts); param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); + + if (param->srv->keepip) { + int opt = 1; + param->srv->so._setsockopt(param->sostate, param->remsock, SOL_IP, IP_FREEBIND, (char *)&opt, sizeof(int)); + } #ifdef REUSE { int opt; @@ -564,7 +596,7 @@ int doconnect(struct clientparam * param){ if(param->srv->so._bind(param->sostate, param->remsock, (struct sockaddr*)¶m->sinsl, SASIZE(¶m->sinsl))==-1) { return 12; } - + if(param->operation >= 256 || (param->operation & CONNECT)){ if(connectwithpoll(param, param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr),CONNECT_TO)) { return 13; diff --git a/src/proxymain.c b/src/proxymain.c index e0612cd..7f069d3 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -239,6 +239,9 @@ int MODULEMAINFUNC (int argc, char** argv){ "\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" +#ifndef _WIN32 + " -k outgoing connection will have local IP where client connected, thus ignores -e (useful in AnyIP case)\n" +#endif " -rHOST:PORT Use IP:port for connect back proxy instead of listen port\n" " -RHOST:PORT Use PORT to listen connect back proxy connection to pass data to\n" " -4 Use IPv4 for outgoing connections\n" @@ -377,6 +380,13 @@ int MODULEMAINFUNC (int argc, char** argv){ #endif } break; +#ifndef _WIN32 + case 'k': + { + srv.keepip = 1; + } + break; +#endif case 'N': getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.extNat); break; @@ -763,6 +773,7 @@ int MODULEMAINFUNC (int argc, char** argv){ } else { new_sock = srv.so._accept(srv.so.state, sock, (struct sockaddr*)&defparam.sincr, &size); + if(new_sock == INVALID_SOCKET){ #ifdef _WIN32 switch(WSAGetLastError()){ @@ -938,6 +949,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){ srv->logdumpcli = conf.logdumpcli; srv->cbsock = INVALID_SOCKET; srv->needuser = 1; + srv->keepip = 0; #ifdef WITHSPLICE srv->usesplice = 1; #endif diff --git a/src/structures.h b/src/structures.h index a2f5ba7..601a9d8 100644 --- a/src/structures.h +++ b/src/structures.h @@ -479,6 +479,7 @@ struct srvparam { int paused, version; int singlepacket; int usentlm; + int keepip; int needuser; int silent; int transparent;