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..e86ed56 100644 --- a/src/common.c +++ b/src/common.c @@ -531,6 +531,11 @@ int doconnect(struct clientparam * param){ 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; diff --git a/src/proxymain.c b/src/proxymain.c index e0612cd..1509658 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,34 @@ int MODULEMAINFUNC (int argc, char** argv){ } else { new_sock = srv.so._accept(srv.so.state, sock, (struct sockaddr*)&defparam.sincr, &size); + + if (srv.keepip) { +#ifndef NOIPV6 + struct sockaddr_in6 local_addr; + socklen_t local_addr_len = sizeof(local_addr); + getsockname(new_sock, (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; + srv.extsa = local_addr2; + } else { + srv.extsa6 = local_addr; + } + } else { + srv.extsa = 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); + + srv.extsa = local_addr; +#endif + } if(new_sock == INVALID_SOCKET){ #ifdef _WIN32 switch(WSAGetLastError()){ @@ -938,6 +976,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;