diff --git a/binaries/aarch64/tpws b/binaries/aarch64/tpws index 0a8d984..b3ac624 100755 Binary files a/binaries/aarch64/tpws and b/binaries/aarch64/tpws differ diff --git a/binaries/arm/tpws b/binaries/arm/tpws index a387964..ff145a8 100755 Binary files a/binaries/arm/tpws and b/binaries/arm/tpws differ diff --git a/binaries/mips32r1-lsb/tpws b/binaries/mips32r1-lsb/tpws index 8d310bf..62c3aaf 100755 Binary files a/binaries/mips32r1-lsb/tpws and b/binaries/mips32r1-lsb/tpws differ diff --git a/binaries/mips32r1-msb/tpws b/binaries/mips32r1-msb/tpws index 9659258..539bc44 100755 Binary files a/binaries/mips32r1-msb/tpws and b/binaries/mips32r1-msb/tpws differ diff --git a/binaries/mips64r2-msb/tpws b/binaries/mips64r2-msb/tpws index 9ec4881..1a842f4 100755 Binary files a/binaries/mips64r2-msb/tpws and b/binaries/mips64r2-msb/tpws differ diff --git a/binaries/ppc/tpws b/binaries/ppc/tpws index e07feab..0305074 100755 Binary files a/binaries/ppc/tpws and b/binaries/ppc/tpws differ diff --git a/binaries/x86/tpws b/binaries/x86/tpws index e01e824..928d9a7 100755 Binary files a/binaries/x86/tpws and b/binaries/x86/tpws differ diff --git a/binaries/x86_64/tpws b/binaries/x86_64/tpws index 7e2ca00..6e67e01 100755 Binary files a/binaries/x86_64/tpws and b/binaries/x86_64/tpws differ diff --git a/binaries/x86_64/tpws_wsl.tgz b/binaries/x86_64/tpws_wsl.tgz index 9950f71..b4addfc 100644 Binary files a/binaries/x86_64/tpws_wsl.tgz and b/binaries/x86_64/tpws_wsl.tgz differ diff --git a/docs/readme.eng.md b/docs/readme.eng.md index ca30a23..3455dcd 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -559,6 +559,7 @@ tpws is transparent proxy. --local-sndbuf= ; SO_SNDBUF for local legs --remote-rcvbuf= ; SO_RCVBUF for remote legs --remote-sndbuf= ; SO_SNDBUF for remote legs + --nosplice ; do not use splice to transfer data between sockets --skip-nodelay ; do not set TCP_NODELAY for outgoing connections. incompatible with split. --no-resolve ; disable socks5 remote dns --resolver-threads= ; number of resolver worker threads @@ -1169,6 +1170,8 @@ Cleanup : `wsl --unregister tpws` Tested in windows 10 build 19041 (20.04). `--oob` , `--mss` and `--disorder` do not work. +RST detection in autohostlist scheme may not work. +WSL may glitch with pipes. `--nosplice` may be required. NOTICE. There is native windows solution GoodByeDPI. It works on packet level like nfqws. diff --git a/docs/readme.txt b/docs/readme.txt index bd88126..5fb00e8 100644 --- a/docs/readme.txt +++ b/docs/readme.txt @@ -658,6 +658,7 @@ tpws - это transparent proxy. --local-sndbuf= ; SO_SNDBUF для соединений client-proxy --remote-rcvbuf= ; SO_RCVBUF для соединений proxy-target --remote-sndbuf= ; SO_SNDBUF для соединений proxy-target + --nosplice ; не использовать splice на linux системах --skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split. --split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host @@ -1581,6 +1582,8 @@ tpws в режиме socks можно запускать и под более-м Не работают функции --oob и --mss из-за ограничений реализации WSL. --disorder не работает из-за особенностей tcp/ip стека windows. +Может не срабатывать детект RST в autohostlist. +WSL может глючить с pipes, ломая тем самым splice и приводя к зацикливанию процесса. Может потребоваться --nosplice. ЗАМЕЧАНИЕ. Под Windows существует нативное решение GoodByeDPI, выполняющее дурение на пакетном уровне (по типу nfqws). diff --git a/tpws/params.h b/tpws/params.h index fe5fa7a..1acdba2 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -81,6 +81,9 @@ struct params_s #if defined(BSD) bool pf_enable; #endif +#ifdef __linux__ + bool nosplice; +#endif }; extern struct params_s params; diff --git a/tpws/tamper.c b/tpws/tamper.c index 21573ae..0f6a468 100644 --- a/tpws/tamper.c +++ b/tpws/tamper.c @@ -345,32 +345,33 @@ void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,siz DBGPRINT("tamper_in hostname=%s", ctrack->hostname) - if (!*params.hostlist_auto_filename) return; - - HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters); - - if (ctrack->l7proto==HTTP && ctrack->hostname) + if (*params.hostlist_auto_filename) { - if (IsHttpReply(segment,*size)) + HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters); + + if (ctrack->l7proto==HTTP && ctrack->hostname) { - VPRINT("incoming HTTP reply detected for hostname %s", ctrack->hostname); - bFail = HttpReplyLooksLikeDPIRedirect(segment, *size, ctrack->hostname); - if (bFail) + if (IsHttpReply(segment,*size)) { - VPRINT("redirect to another domain detected. possibly DPI redirect.") - HOSTLIST_DEBUGLOG_APPEND("%s : redirect to another domain", ctrack->hostname); + VPRINT("incoming HTTP reply detected for hostname %s", ctrack->hostname); + bFail = HttpReplyLooksLikeDPIRedirect(segment, *size, ctrack->hostname); + if (bFail) + { + VPRINT("redirect to another domain detected. possibly DPI redirect.") + HOSTLIST_DEBUGLOG_APPEND("%s : redirect to another domain", ctrack->hostname); + } + else + VPRINT("local or in-domain redirect detected. it's not a DPI redirect.") } else - VPRINT("local or in-domain redirect detected. it's not a DPI redirect.") - } - else - { - // received not http reply. do not monitor this connection anymore - VPRINT("incoming unknown HTTP data detected for hostname %s", ctrack->hostname); - } - if (bFail) - auto_hostlist_failed(ctrack->hostname); - + { + // received not http reply. do not monitor this connection anymore + VPRINT("incoming unknown HTTP data detected for hostname %s", ctrack->hostname); + } + if (bFail) + auto_hostlist_failed(ctrack->hostname); + + } } ctrack->bTamperInCutoff = true; } diff --git a/tpws/tpws.c b/tpws/tpws.c index a8405e7..f4f644c 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -144,6 +144,9 @@ static void exithelp(void) " --local-sndbuf=\n" " --remote-rcvbuf=\n" " --remote-sndbuf=\n" +#ifdef __linux__ + " --nosplice\t\t\t\t; do not use splice to transfer data between sockets\n" +#endif " --skip-nodelay\t\t\t\t; do not set TCP_NODELAY option for outgoing connections (incompatible with split options)\n" " --maxconn=\n" #ifdef SPLICE_PRESENT @@ -333,6 +336,7 @@ void parse_params(int argc, char *argv[]) #elif defined(__linux__) { "mss",required_argument,0,0 },// optidx=53 { "mss-pf",required_argument,0,0 },// optidx=54 + { "nosplice",no_argument,0,0 },// optidx=55 #endif { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { NULL,0,NULL,0 } @@ -773,6 +777,9 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; + case 55: /* nosplice */ + params.nosplice = true; + break; #endif } } @@ -912,11 +919,11 @@ static bool set_ulimit(void) if (!params.maxfiles) { - // 4 fds per tamper connection (2 pipe + 2 socket), 6 fds for tcp proxy connection (4 pipe + 2 socket) + // 4 fds per tamper connection (2 pipe + 2 socket), 6 fds for tcp proxy connection (4 pipe + 2 socket), 2 fds (2 socket) for nosplice // additional 1/2 for unpaired remote legs sending buffers // 16 for listen_fd, epoll, hostlist, ... #ifdef SPLICE_PRESENT - fdmax = (params.tamper && !params.tamper_start && !params.tamper_cutoff ? 4 : 6) * params.maxconn; + fdmax = (params.nosplice ? 2 : (params.tamper && !params.tamper_start && !params.tamper_cutoff ? 4 : 6)) * params.maxconn; #else fdmax = 2 * params.maxconn; #endif diff --git a/tpws/tpws_conn.c b/tpws/tpws_conn.c index 5e73c75..1fcd593 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -440,7 +440,7 @@ static tproxy_conn_t *new_conn(int fd, bool remote) #ifdef SPLICE_PRESENT // if dont tamper - both legs are spliced, create 2 pipes // otherwise create pipe only in local leg - if ((!remote || !params.tamper || params.tamper_start || params.tamper_cutoff ) && pipe2(conn->splice_pipe, O_NONBLOCK) != 0) + if (!params.nosplice && ( !remote || !params.tamper || params.tamper_start || params.tamper_cutoff ) && pipe2(conn->splice_pipe, O_NONBLOCK) != 0) { fprintf(stderr, "Could not create the splice pipe\n"); free_conn(conn); @@ -662,7 +662,7 @@ static bool handle_unsent(tproxy_conn_t *conn) DBGPRINT("+handle_unsent, fd=%d has_unsent=%d has_unsent_partner=%d",conn->fd,conn_has_unsent(conn),conn_partner_alive(conn) ? conn_has_unsent(conn->partner) : false) #ifdef SPLICE_PRESENT - if (conn->wr_unsent) + if (!params.nosplice && conn->wr_unsent) { wr = splice(conn->splice_pipe[0], NULL, conn->fd, NULL, conn->wr_unsent, SPLICE_F_MOVE | SPLICE_F_NONBLOCK); DBGPRINT("splice unsent=%zd wr=%zd err=%d",conn->wr_unsent,wr,errno) @@ -1067,7 +1067,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32 { DBGPRINT("%s leg fd=%d stream pos : %" PRIu64 "(n%" PRIu64 ")/%" PRIu64, conn->remote ? "remote" : "local", conn->fd, conn->trd,conn->tnrd+1,conn->twr) #ifdef SPLICE_PRESENT - if (!params.tamper || conn->remote && conn->partner->track.bTamperInCutoff || !conn->remote && !in_tamper_out_range(conn)) + if (!params.nosplice && (!params.tamper || conn->remote && conn->partner->track.bTamperInCutoff || !conn->remote && !in_tamper_out_range(conn))) { // incoming data from remote leg we splice without touching // pipe is in the local leg, so its in conn->partner->splice_pipe