tpws: nosplice

This commit is contained in:
bol-van 2024-04-03 22:21:17 +03:00
parent 747f9676a6
commit a570845453
15 changed files with 43 additions and 26 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -559,6 +559,7 @@ tpws is transparent proxy.
--local-sndbuf=<bytes> ; SO_SNDBUF for local legs
--remote-rcvbuf=<bytes> ; SO_RCVBUF for remote legs
--remote-sndbuf=<bytes> ; 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=<int> ; 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.

View File

@ -658,6 +658,7 @@ tpws - это transparent proxy.
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
--remote-sndbuf=<bytes> ; 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).

View File

@ -81,6 +81,9 @@ struct params_s
#if defined(BSD)
bool pf_enable;
#endif
#ifdef __linux__
bool nosplice;
#endif
};
extern struct params_s params;

View File

@ -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(&params.hostlist_auto_fail_counters);
if (ctrack->l7proto==HTTP && ctrack->hostname)
if (*params.hostlist_auto_filename)
{
if (IsHttpReply(segment,*size))
HostFailPoolPurgeRateLimited(&params.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;
}

View File

@ -144,6 +144,9 @@ static void exithelp(void)
" --local-sndbuf=<bytes>\n"
" --remote-rcvbuf=<bytes>\n"
" --remote-sndbuf=<bytes>\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=<max_connections>\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

View File

@ -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