mirror of
https://github.com/3proxy/3proxy.git
synced 2026-08-26 09:55:48 +08:00
Add per-service local port ranges
This commit is contained in:
parent
8f62e42e7d
commit
a5584f9bdf
@ -176,6 +176,9 @@ listen on given local HOST:port for incoming connections instead of making remot
|
||||
.B -r\fIHOST\fB:\fIport\fR
|
||||
connect to given remote HOST:port instead of listening local connection on -p or default port. Can be used with another 3proxy service running -R option for connect back functionality. Most commonly used with proxy or socks. HOST can be given as IP or hostname, useful in case of dynamic DNS.
|
||||
.br
|
||||
.B -Tr\fIFIRST\fB-\fILAST\fR, -Ur\fIFIRST\fB-\fILAST\fR, -UAr\fIFIRST\fB-\fILAST\fR
|
||||
(Linux) use the inclusive local ephemeral port range FIRST-LAST for outgoing IPv4 TCP (-Tr) or UDP (-Ur) sockets of this service. -UAr applies only to the UDP relay socket returned to a SOCKS5 UDP ASSOCIATE client. Use it when this port range must be forwarded by NAT and allowed by a firewall. Requires kernel support for IP_LOCAL_PORT_RANGE (Linux 6.3 or newer). The option is applied before bind(2); no system-wide sysctl is changed. For example, \fBsocks -p1080 -Ur20000-30000 -UAr30000-31000\fR.
|
||||
.br
|
||||
.B -oc\fIOPTIONS\fB, -os\fIOPTIONS\fB, -ol\fIOPTIONS\fB, -or\fIOPTIONS\fB, -oR\fIOPTIONS\fR
|
||||
options for proxy-to-client (\fB-oc\fR), proxy-to-server (\fB-os\fR), proxy listening (\fB-ol\fR), connect back client (\fB-or\fR), connect back listening (\fB-oR\fR) sockets.
|
||||
Options like TCP_CORK, TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS, TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT, SO_EXCLUSIVEADDRUSE, SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be supported depending on OS.
|
||||
|
||||
24
src/common.c
24
src/common.c
@ -52,6 +52,11 @@ int switch_ns(struct srvparam *srv, int target_fd) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef IP_LOCAL_PORT_RANGE
|
||||
#define IP_LOCAL_PORT_RANGE 51
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char * copyright = COPYRIGHT;
|
||||
|
||||
@ -722,6 +727,7 @@ int doconnect(struct clientparam * param){
|
||||
}
|
||||
*SAPORT(¶m->sinsl) = 0;
|
||||
setopts(param->remsock, param->srv->srvsockopts);
|
||||
if(set_local_port_range(param->srv, param->remsock, (struct sockaddr *)¶m->sinsl, LOCAL_PORT_RANGE_TCP)) return 12;
|
||||
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||
#if defined SO_BINDTODEVICE
|
||||
@ -767,6 +773,24 @@ int doconnect(struct clientparam * param){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_local_port_range(struct srvparam *srv, SOCKET sock, const struct sockaddr *sa, int range_type){
|
||||
#ifdef __linux__
|
||||
uint32_t range = range_type == LOCAL_PORT_RANGE_TCP ? srv->tcp_local_port_range :
|
||||
range_type == LOCAL_PORT_RANGE_UDP ? srv->udp_local_port_range : srv->udp_associate_port_range;
|
||||
|
||||
if(range && sa->sa_family == AF_INET &&
|
||||
((const struct sockaddr_in *)sa)->sin_port == 0 &&
|
||||
srv->so._setsockopt(srv->so.state, sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE,
|
||||
(char *)&range, sizeof(range))) return -1;
|
||||
#else
|
||||
(void)srv;
|
||||
(void)sock;
|
||||
(void)sa;
|
||||
(void)range_type;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scanaddr(const unsigned char *s, uint32_t * ip, uint32_t * mask) {
|
||||
unsigned d1, d2, d3, d4, m;
|
||||
int res;
|
||||
|
||||
@ -149,6 +149,10 @@ void * dnsprchild(struct clientparam* param) {
|
||||
}
|
||||
memset(¶m->sinsl, 0, sizeof(param->sinsl));
|
||||
*SAFAMILY(¶m->sinsl) = *SAFAMILY(&nservers[0].addr);
|
||||
if(set_local_port_range(param->srv, param->remsock, (struct sockaddr *)¶m->sinsl,
|
||||
nservers[0].usetcp ? LOCAL_PORT_RANGE_TCP : LOCAL_PORT_RANGE_UDP)) {
|
||||
RETURN(819);
|
||||
}
|
||||
if(param->srv->so._bind(param->sostate, param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) {
|
||||
RETURN(819);
|
||||
}
|
||||
@ -222,4 +226,3 @@ CLEANRET:
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +121,7 @@ void * ftpprchild(struct clientparam* param) {
|
||||
}
|
||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||
*SAPORT(¶m->sincl) = 0;
|
||||
if(set_local_port_range(param->srv, clidatasock, (struct sockaddr *)¶m->sincl, LOCAL_PORT_RANGE_TCP)){RETURN(822);}
|
||||
if(param->srv->so._bind(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, SASIZE(¶m->sincl))){RETURN(822);}
|
||||
if (pasv) {
|
||||
if(param->srv->so._listen(param->sostate, clidatasock, 1)) {RETURN(823);}
|
||||
|
||||
@ -352,6 +352,10 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
|
||||
int readconfig(FILE * fp);
|
||||
void initcommands(void);
|
||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||
#define LOCAL_PORT_RANGE_TCP 1
|
||||
#define LOCAL_PORT_RANGE_UDP 2
|
||||
#define LOCAL_PORT_RANGE_UDP_ASSOCIATE 3
|
||||
int set_local_port_range(struct srvparam *srv, SOCKET sock, const struct sockaddr *sa, int range_type);
|
||||
|
||||
|
||||
uint32_t myrand(void);
|
||||
@ -433,4 +437,3 @@ extern char * ceargv[32];
|
||||
#define WEBBANNERS 35
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -345,6 +345,7 @@ 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"
|
||||
" -TrFIRST-LAST, -UrFIRST-LAST, -UArFIRST-LAST Linux: local TCP, UDP or UDP ASSOCIATE ranges\n"
|
||||
" -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"
|
||||
@ -568,6 +569,35 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
srv.needuser = 0;
|
||||
if(*(argv[i] + 2)) srv.needuser = atoi(argv[i] + 2);
|
||||
break;
|
||||
case 'U':
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *end;
|
||||
const char *range_arg;
|
||||
unsigned long first, last;
|
||||
uint32_t *range;
|
||||
|
||||
if(argv[i][2] == 'r') {
|
||||
range_arg = argv[i] + 3;
|
||||
range = &srv.udp_local_port_range;
|
||||
}
|
||||
else if(argv[i][2] == 'A' && argv[i][3] == 'r') {
|
||||
range_arg = argv[i] + 4;
|
||||
range = &srv.udp_associate_port_range;
|
||||
}
|
||||
else { error = 1; break; }
|
||||
errno = 0;
|
||||
first = strtoul(range_arg, &end, 10);
|
||||
if(errno || end == range_arg || *end != '-') { error = 1; break; }
|
||||
errno = 0;
|
||||
last = strtoul(end + 1, &end, 10);
|
||||
if(errno || *end || !first || !last || first > last || last > 65535) { error = 1; break; }
|
||||
*range = ((uint32_t)last << 16) | (uint32_t)first;
|
||||
}
|
||||
#else
|
||||
error = 1;
|
||||
#endif
|
||||
break;
|
||||
case 'x':
|
||||
srv.nostarttls = 1;
|
||||
break;
|
||||
@ -590,7 +620,27 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
srv.transparent = 1;
|
||||
if(!argv[i][2]) {
|
||||
srv.transparent = 1;
|
||||
break;
|
||||
}
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *end;
|
||||
unsigned long first, last;
|
||||
|
||||
if(argv[i][2] != 'r') { error = 1; break; }
|
||||
errno = 0;
|
||||
first = strtoul(argv[i] + 3, &end, 10);
|
||||
if(errno || end == argv[i] + 3 || *end != '-') { error = 1; break; }
|
||||
errno = 0;
|
||||
last = strtoul(end + 1, &end, 10);
|
||||
if(errno || *end || !first || !last || first > last || last > 65535) { error = 1; break; }
|
||||
srv.tcp_local_port_range = ((uint32_t)last << 16) | (uint32_t)first;
|
||||
}
|
||||
#else
|
||||
error = 1;
|
||||
#endif
|
||||
break;
|
||||
case 'S':
|
||||
srv.stacksize = atoi(argv[i]+2);
|
||||
@ -1797,5 +1847,3 @@ FILTER_ACTION handledatfltsrv(struct clientparam *cparam, unsigned char ** buf_p
|
||||
}
|
||||
return PASS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -60,6 +60,10 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
|
||||
*SAFAMILY(sinsl) = *SAFAMILY(&nservers[i].addr);
|
||||
}
|
||||
if((sock=so._socket(so.state, SASOCK(sinsl), usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break;
|
||||
if(param && set_local_port_range(param->srv, sock, (struct sockaddr *)sinsl, usetcp ? LOCAL_PORT_RANGE_TCP : LOCAL_PORT_RANGE_UDP)) {
|
||||
so._closesocket(so.state, sock);
|
||||
break;
|
||||
}
|
||||
if(so._bind(so.state, sock,(struct sockaddr *)sinsl,SASIZE(sinsl))){
|
||||
so._shutdown(so.state, sock, SHUT_RDWR);
|
||||
so._closesocket(so.state, sock);
|
||||
@ -228,4 +232,4 @@ uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){
|
||||
value[3] = 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,6 +218,8 @@ void * sockschild(struct clientparam* param) {
|
||||
if((res = udpbind(param))) {RETURN(res);}
|
||||
}
|
||||
else if(command == 2) {
|
||||
if(set_local_port_range(param->srv, param->remsock, (struct sockaddr *)¶m->sinsl,
|
||||
LOCAL_PORT_RANGE_TCP)) RETURN(12);
|
||||
if(param->srv->so._bind(param->sostate, param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) {
|
||||
*SAPORT(¶m->sinsl) = 0;
|
||||
if(param->srv->so._bind(param->sostate, param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl)))RETURN (12);
|
||||
@ -243,6 +245,7 @@ fflush(stderr);
|
||||
#endif
|
||||
sin = param->sincl;
|
||||
*SAPORT(&sin) = 0;
|
||||
if(set_local_port_range(param->srv, param->clisock, (struct sockaddr *)&sin, LOCAL_PORT_RANGE_UDP_ASSOCIATE)) {RETURN (12);}
|
||||
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
|
||||
sasize = SASIZE(&sin);
|
||||
param->srv->so._getsockname(param->sostate, param->clisock, (struct sockaddr *)&sin, &sasize);
|
||||
|
||||
@ -590,6 +590,9 @@ struct srvparam {
|
||||
unsigned char *udpbuf;
|
||||
unsigned char *udpbuf2;
|
||||
int udplen;
|
||||
uint32_t tcp_local_port_range;
|
||||
uint32_t udp_local_port_range;
|
||||
uint32_t udp_associate_port_range;
|
||||
};
|
||||
|
||||
struct clientparam {
|
||||
|
||||
@ -121,6 +121,12 @@ int udpbind(struct clientparam *param)
|
||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||
#endif
|
||||
param->remsock = s;
|
||||
if (set_local_port_range(param->srv, param->remsock,
|
||||
(struct sockaddr *)¶m->sinsl, LOCAL_PORT_RANGE_UDP)) {
|
||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||
param->remsock = INVALID_SOCKET;
|
||||
return 12;
|
||||
}
|
||||
if (param->srv->so._bind(param->sostate, param->remsock,
|
||||
(struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) {
|
||||
*SAPORT(¶m->sinsl) = 0;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user