tpws: support 'n' prefix in tamper-start and tamper-cutoff

This commit is contained in:
bol-van 2024-03-09 14:26:07 +03:00
parent 3f9f1c36b8
commit cffcfe71da
4 changed files with 49 additions and 20 deletions

View File

@ -61,6 +61,7 @@ struct params_s
int hostlist_auto_fail_threshold, hostlist_auto_fail_time;
hostfail_pool *hostlist_auto_fail_counters;
bool tamper_start_n,tamper_cutoff_n;
unsigned int tamper_start,tamper_cutoff;
int debug;

View File

@ -189,8 +189,8 @@ static void exithelp(void)
" --unixeol\t\t\t\t; replace 0D0A to 0A\n"
" --tlsrec=sni\t\t\t\t; make 2 TLS records. split at SNI. don't split if SNI is not present\n"
" --tlsrec-pos=<pos>\t\t\t; make 2 TLS records. split at specified pos\n"
" --tamper-start=<pos>\t\t\t; start tampering only from specified outbound stream position. default is 0.\n"
" --tamper-cutoff=<pos>\t\t\t; do not tamper anymore after specified outbound stream position. default is unlimited.\n",
" --tamper-start=[n]<pos>\t\t; start tampering only from specified outbound stream position. default is 0. 'n' means data block number.\n"
" --tamper-cutoff=[n]<pos>\t\t; do not tamper anymore after specified outbound stream position. default is unlimited.\n",
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
);
exit(1);
@ -670,10 +670,30 @@ void parse_params(int argc, char *argv[])
params.skip_nodelay = true;
break;
case 49: /* tamper-start */
params.tamper_start = atoi(optarg);
{
const char *p=optarg;
if (*p=='n')
{
params.tamper_start_n=true;
p++;
}
else
params.tamper_start_n=false;
params.tamper_start = atoi(p);
}
break;
case 50: /* tamper-cutoff */
params.tamper_cutoff = atoi(optarg);
{
const char *p=optarg;
if (*p=='n')
{
params.tamper_cutoff_n=true;
p++;
}
else
params.tamper_cutoff_n=false;
params.tamper_cutoff = atoi(p);
}
break;
#if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__)
case 51: /* enable-pf */

View File

@ -893,6 +893,12 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
return false;
}
static bool in_tamper_out_range(tproxy_conn_t *conn)
{
return (params.tamper_start_n ? (conn->tnrd+1) : conn->trd) >= params.tamper_start &&
(!params.tamper_cutoff || (params.tamper_cutoff_n ? (conn->tnrd+1) : conn->trd) < params.tamper_cutoff);
}
static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_size, size_t *segment_size, size_t *split_pos)
{
*split_pos=0;
@ -905,13 +911,16 @@ static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_
tamper_in(&conn->partner->track,segment,segment_buffer_size,segment_size);
}
}
else if (conn->trd >= params.tamper_start && (!params.tamper_cutoff || conn->trd < params.tamper_cutoff))
{
DBGPRINT("tamper_out stream pos %zu. tamper range %u-%u", conn->trd, params.tamper_start, params.tamper_cutoff)
tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos);
}
else
DBGPRINT("stream pos %zu is out of tamper range %u-%u", conn->trd, params.tamper_start, params.tamper_cutoff)
{
bool in_range = in_tamper_out_range(conn);
DBGPRINT("tamper_out stream pos %" PRIu64 "(n%" PRIu64 "). tamper range %s%u-%s%u (%s)",
conn->trd, conn->tnrd+1,
params.tamper_start_n ? "n" : "" , params.tamper_start,
params.tamper_cutoff_n ? "n" : "" , params.tamper_cutoff,
in_range ? "IN RANGE" : "OUT OF RANGE")
if (in_range) tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos);
}
}
}
@ -945,14 +954,14 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
{
// throw it to a black hole
uint8_t waste[65070];
ssize_t trd=0;
uint64_t trd=0;
while((rd=recv(conn->fd, waste, sizeof(waste), MSG_DONTWAIT))>0 && trd<MAX_WASTE)
{
trd+=rd;
conn->trd+=rd;
}
DBGPRINT("wasted recv=%zd all_rd=%zd err=%d",rd,trd,errno)
DBGPRINT("wasted recv=%zd all_rd=%" PRIu64 " err=%d",rd,trd,errno)
return true;
}
@ -966,13 +975,9 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
DBGPRINT("numbytes=%d",numbytes)
if (numbytes>0)
{
if (conn->remote)
VPRINT("remote leg stream pos R/W : %zu/%zu",conn->trd,conn->twr)
else
VPRINT("local leg stream pos : %zu/%zu",conn->trd,conn->twr)
VPRINT("%s leg stream pos : %" PRIu64 "(n%" PRIu64 ")/%" PRIu64, conn->remote ? "remote" : "local", conn->trd,conn->tnrd+1,conn->twr)
#ifdef SPLICE_PRESENT
if (!params.tamper || conn->remote && conn->partner->track.bTamperInCutoff ||
!conn->remote && (conn->trd < params.tamper_start || params.tamper_cutoff && conn->trd >= params.tamper_cutoff))
if (!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
@ -983,6 +988,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
if (rd<0 && errno==EAGAIN) rd=0;
if (rd>0)
{
conn->tnrd++;
conn->trd += rd;
conn->partner->wr_unsent += rd;
wr = splice(conn->partner->splice_pipe[0], NULL, conn->partner->fd, NULL, conn->partner->wr_unsent, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
@ -1013,6 +1019,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
// tamper needs to know stream position of the block start
tamper(conn, buf, sizeof(buf), &bs, &split_pos);
// increase after tamper
conn->tnrd++;
conn->trd+=rd;
if (split_pos)
@ -1070,7 +1077,7 @@ static bool remove_closed_connections(int efd, struct tailhead *close_list)
shutdown(conn->fd,SHUT_RDWR);
epoll_del(conn);
VPRINT("Socket fd=%d (partner_fd=%d, remote=%d) closed, connection removed. total_read=%zu total_write=%zu event_count=%u",
VPRINT("Socket fd=%d (partner_fd=%d, remote=%d) closed, connection removed. total_read=%" PRIu64 " total_write=%" PRIu64 " event_count=%u",
conn->fd, conn->partner ? conn->partner->fd : 0, conn->remote, conn->trd, conn->twr, conn->event_count)
if (conn->remote) legs_remote--; else legs_local--;
free_conn(conn);

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdbool.h>
#include <inttypes.h>
#include <sys/queue.h>
#include <time.h>
#include "tamper.h"
@ -67,7 +68,7 @@ struct tproxy_conn
bool bFlowIn,bFlowOut, bFlowInPrev,bFlowOutPrev, bPrevRdhup;
// total read,write
size_t trd,twr;
uint64_t trd,twr, tnrd;
// number of epoll_wait events
unsigned int event_count;