From c793ec8e1cd786fff948964d8605a3e664150775 Mon Sep 17 00:00:00 2001 From: Vladimir Goncharov Date: Thu, 22 Aug 2024 15:49:50 +0700 Subject: [PATCH] bind address for connect --- tpws/params.h | 3 +++ tpws/tpws.c | 35 +++++++++++++++++++++++++++-------- tpws/tpws_conn.c | 21 +++++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/tpws/params.h b/tpws/params.h index 292bf0d..c6c8aeb 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -72,6 +72,9 @@ struct params_s bool tamper_start_n,tamper_cutoff_n; unsigned int tamper_start,tamper_cutoff; + struct sockaddr_in connect_bind4; + struct sockaddr_in6 connect_bind6; + int debug; #if defined(BSD) diff --git a/tpws/tpws.c b/tpws/tpws.c index 1de0e22..cef5f59 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -138,6 +138,7 @@ static void exithelp(void) " * multiple binds are supported. each bind-addr, bind-iface* start new bind\n" " --port=\t\t\t\t; only one port number for all binds is supported\n" " --socks\t\t\t\t; implement socks4/5 proxy instead of transparent proxy\n" + " --connect-bind-addr=| ; address for outbound connections\n" " --no-resolve\t\t\t\t; disable socks5 remote dns ability\n" " --resolver-threads=\t\t; number of resolver worker threads\n" " --local-rcvbuf=\n" @@ -355,13 +356,14 @@ void parse_params(int argc, char *argv[]) { "skip-nodelay",no_argument,0,0 },// optidx=51 { "tamper-start",required_argument,0,0 },// optidx=52 { "tamper-cutoff",required_argument,0,0 },// optidx=53 + { "connect-bind-addr",required_argument,0,0 },// optidx=54 #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - { "enable-pf",no_argument,0,0 },// optidx=54 + { "enable-pf",no_argument,0,0 },// optidx=55 #elif defined(__linux__) - { "mss",required_argument,0,0 },// optidx=54 - { "mss-pf",required_argument,0,0 },// optidx=55 + { "mss",required_argument,0,0 },// optidx=55 + { "mss-pf",required_argument,0,0 },// optidx=56 #ifdef SPLICE_PRESENT - { "nosplice",no_argument,0,0 },// optidx=55 + { "nosplice",no_argument,0,0 },// optidx=57 #endif #endif { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility @@ -784,12 +786,29 @@ void parse_params(int argc, char *argv[]) params.tamper_cutoff = atoi(p); } break; + case 54: /* connect-bind-addr */ + { + if (inet_pton(AF_INET, optarg, ¶ms.connect_bind4.sin_addr)) + { + params.connect_bind4.sin_family = AF_INET; + } + else if (inet_pton(AF_INET6, optarg, ¶ms.connect_bind6.sin6_addr)) + { + params.connect_bind6.sin6_family = AF_INET6; + } + else + { + fprintf(stderr, "bad bind addr : %s\n", optarg); + exit_clean(1); + } + } + break; #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - case 54: /* enable-pf */ + case 55: /* enable-pf */ params.pf_enable = true; break; #elif defined(__linux__) - case 54: /* mss */ + case 55: /* mss */ // this option does not work in any BSD and MacOS. OS may accept but it changes nothing params.mss = atoi(optarg); if (params.mss<88 || params.mss>32767) @@ -798,7 +817,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 55: /* mss-pf */ + case 56: /* mss-pf */ if (!pf_parse(optarg,¶ms.mss_pf)) { fprintf(stderr, "Invalid MSS port filter.\n"); @@ -806,7 +825,7 @@ void parse_params(int argc, char *argv[]) } break; #ifdef SPLICE_PRESENT - case 56: /* nosplice */ + case 57: /* nosplice */ params.nosplice = true; break; #endif diff --git a/tpws/tpws_conn.c b/tpws/tpws_conn.c index 23df5df..70b05cf 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -390,6 +390,27 @@ static int connect_remote(const struct sockaddr *remote_addr, bool bApplyConnect VPRINT("Not setting MSS. Port %u is out of MSS port range.",port) } } + + // if no bind address specified - address family will be 0 in params_connect_bindX + if(remote_addr->sa_family == params.connect_bind4.sin_family) + { + if (bind(remote_fd, (struct sockaddr *)¶ms.connect_bind4, sizeof(struct sockaddr_in)) == -1) + { + perror("bind on connect"); + close(remote_fd); + return -1; + } + } + else if(remote_addr->sa_family == params.connect_bind6.sin6_family) + { + if (bind(remote_fd, (struct sockaddr *)¶ms.connect_bind6, sizeof(struct sockaddr_in6)) == -1) + { + perror("bind on connect"); + close(remote_fd); + return -1; + } + } + if (connect(remote_fd, remote_addr, remote_addr->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) < 0) { if(errno != EINPROGRESS)