diff --git a/binaries/aarch64/tpws b/binaries/aarch64/tpws index 9ca22f4..de0df16 100755 Binary files a/binaries/aarch64/tpws and b/binaries/aarch64/tpws differ diff --git a/binaries/arm/tpws b/binaries/arm/tpws index 16277fa..7a62918 100755 Binary files a/binaries/arm/tpws and b/binaries/arm/tpws differ diff --git a/binaries/freebsd-x64/tpws b/binaries/freebsd-x64/tpws index 8331e73..7e79eec 100755 Binary files a/binaries/freebsd-x64/tpws and b/binaries/freebsd-x64/tpws differ diff --git a/binaries/mac64/tpws b/binaries/mac64/tpws index e6d1655..465e121 100755 Binary files a/binaries/mac64/tpws and b/binaries/mac64/tpws differ diff --git a/binaries/mips32r1-lsb/tpws b/binaries/mips32r1-lsb/tpws index 11100aa..e59b7fc 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 ff17f33..a6a3fb9 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 da49335..77c14d7 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 37c5b11..1fc3d95 100755 Binary files a/binaries/ppc/tpws and b/binaries/ppc/tpws differ diff --git a/binaries/x86/tpws b/binaries/x86/tpws index 2e1b46d..b946018 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 0c62e54..459f4f1 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 b47500d..03e25a0 100644 Binary files a/binaries/x86_64/tpws_wsl.tgz and b/binaries/x86_64/tpws_wsl.tgz differ diff --git a/tpws/params.h b/tpws/params.h index 8830cfb..2ec3ac9 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -50,6 +50,7 @@ struct params_s bool split_any_protocol; int split_pos; bool disorder, oob; + uint8_t oob_byte; int ttl_default; char pidfile[256]; @@ -60,6 +61,8 @@ struct params_s int hostlist_auto_fail_threshold, hostlist_auto_fail_time; hostfail_pool *hostlist_auto_fail_counters; + unsigned int tamper_start,tamper_cutoff; + int debug; #if defined(BSD) diff --git a/tpws/tpws.c b/tpws/tpws.c index f07296e..c5a254f 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -176,7 +176,7 @@ static void exithelp(void) #else " --disorder\t\t\t\t; when splitting simulate sending second fragment first\n" #endif - " --oob\t\t\t\t\t; when splitting send out of band zero byte\n" + " --oob[=|0xHEX]\t\t\t; when splitting send out of band byte. default is HEX 0x00.\n" " --hostcase\t\t\t\t; change Host: => host:\n" " --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostdot\t\t\t\t; add \".\" after Host: name\n" @@ -188,7 +188,9 @@ static void exithelp(void) " --methodeol\t\t\t\t; add end-of-line before method\n" " --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=\t\t\t; make 2 TLS records. split at specified pos\n", + " --tlsrec-pos=\t\t\t; make 2 TLS records. split at specified pos\n" + " --tamper-start=\t\t\t; start tampering only from specified outbound stream position. default is 0.\n" + " --tamper-cutoff=\t\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); @@ -295,7 +297,7 @@ void parse_params(int argc, char *argv[]) { "split-pos",required_argument,0,0 },// optidx=24 { "split-any-protocol",optional_argument,0,0},// optidx=25 { "disorder",no_argument,0,0 },// optidx=26 - { "oob",no_argument,0,0 },// optidx=27 + { "oob",optional_argument,0,0 },// optidx=27 { "methodspace",no_argument,0,0 },// optidx=28 { "methodeol",no_argument,0,0 },// optidx=29 { "hosttab",no_argument,0,0 },// optidx=30 @@ -317,8 +319,10 @@ void parse_params(int argc, char *argv[]) { "socks",no_argument,0,0 },// optidx=46 { "no-resolve",no_argument,0,0 },// optidx=47 { "skip-nodelay",no_argument,0,0 },// optidx=48 + { "tamper-start",required_argument,0,0 },// optidx=49 + { "tamper-cutoff",required_argument,0,0 },// optidx=50 #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - { "enable-pf",no_argument,0,0 },// optidx=49 + { "enable-pf",no_argument,0,0 },// optidx=51 #endif { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { NULL,0,NULL,0 } @@ -508,6 +512,18 @@ void parse_params(int argc, char *argv[]) save_default_ttl(); break; case 27: /* oob */ + if (optarg) + { + size_t l = strlen(optarg); + unsigned int bt; + if (l==1) params.oob_byte = (uint8_t)*optarg; + else if (l!=4 || sscanf(optarg,"0x%02X",&bt)!=1) + { + fprintf(stderr, "Invalid argument for oob\n"); + exit_clean(1); + } + else params.oob_byte = (uint8_t)bt; + } params.oob = true; break; case 28: /* methodspace */ @@ -653,8 +669,14 @@ void parse_params(int argc, char *argv[]) case 48: /* skip-nodelay */ params.skip_nodelay = true; break; + case 49: /* tamper-start */ + params.tamper_start = atoi(optarg); + break; + case 50: /* tamper-cutoff */ + params.tamper_cutoff = atoi(optarg); + break; #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - case 49: /* enable-pf */ + case 51: /* enable-pf */ params.pf_enable = true; break; #endif @@ -798,7 +820,7 @@ static bool set_ulimit(void) // additional 1/2 for unpaired remote legs sending buffers // 16 for listen_fd, epoll, hostlist, ... #ifdef SPLICE_PRESENT - fdmax = (params.tamper ? 4 : 6) * params.maxconn; + fdmax = (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 a85d5fb..aa7893e 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -400,7 +400,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((!params.tamper || !remote) && pipe2(conn->splice_pipe, O_NONBLOCK) != 0) + if ((!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); @@ -905,10 +905,13 @@ 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 + 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) } } @@ -963,8 +966,13 @@ 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) #ifdef SPLICE_PRESENT - if (!params.tamper || conn->remote && conn->partner->track.bTamperInCutoff) + if (!params.tamper || conn->remote && conn->partner->track.bTamperInCutoff || + !conn->remote && (conn->trd < params.tamper_start || params.tamper_cutoff && conn->trd >= params.tamper_cutoff)) { // incoming data from remote leg we splice without touching // pipe is in the local leg, so its in conn->partner->splice_pipe @@ -998,26 +1006,28 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32 if (rd<0 && errno==EAGAIN) rd=0; if (rd>0) { - conn->trd+=rd; - size_t split_pos; bs = rd; - + + // tamper needs to know stream position of the block start tamper(conn, buf, sizeof(buf), &bs, &split_pos); + // increase after tamper + conn->trd+=rd; if (split_pos) { - uint8_t oob; - VPRINT("Splitting at pos %zu", split_pos) if (params.oob) { - oob = buf[split_pos]; - buf[split_pos] = 0; + uint8_t oob_save; + oob_save = buf[split_pos]; + buf[split_pos] = params.oob_byte; + wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos+1, MSG_OOB, params.disorder ? 1 : 0); + buf[split_pos] = oob_save; } - wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos+1, params.oob ? MSG_OOB : 0, params.disorder ? 1 : 0); - if (params.oob) buf[split_pos] = oob; + else + wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, 0, params.disorder ? 1 : 0); DBGPRINT("send_or_buffer(1) fd=%d wr=%zd err=%d",conn->partner->fd,wr,errno) if (wr >= 0) {