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[=<char>|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=<pos>\t\t\t; make 2 TLS records. split at specified pos\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",
 		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)
 					{