From 187affb84470053c39bd05e8d336b383bee732b2 Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 12 Nov 2024 16:25:42 +0300 Subject: [PATCH 1/4] nfqws: add seqovl support to multisplit/multidisorder --- nfq/desync.c | 171 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 128 insertions(+), 43 deletions(-) diff --git a/nfq/desync.c b/nfq/desync.c index 3f0a5f1..700bfe4 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -1,5 +1,8 @@ #define _GNU_SOURCE +#include +#include + #include "desync.h" #include "protocol.h" #include "params.h" @@ -8,9 +11,6 @@ #include "ipset.h" #include "conntrack.h" -#include - - const char *fake_http_request_default = "GET / HTTP/1.1\r\nHost: www.iana.org\r\n" "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0\r\n" "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" @@ -1273,22 +1273,62 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_MULTISPLIT: if (multisplit_count) { - size_t from,to; + uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; + size_t seg_len,from,to; + unsigned int seqovl; for (i=0,from=0 ; i<=multisplit_count ; i++) { to = i==multisplit_count ? dis->len_payload : multisplit_pos[i]; - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, - net32_add(dis->tcp->th_seq,from), dis->tcp->th_ack, - dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), - fooling_orig,0,0, - dis->data_payload+from, to-from, pkt1, &pkt1_len)) - return verdict; - DLOG("sending multisplit part %d %zu-%zu len=%zu : ",i+1,from,to-1,to-from); - hexdump_limited_dlog(dis->data_payload+from,to-from,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - return verdict; + seqovl = dp->desync_seqovl; +#ifdef __linux__ +// only linux return error if MTU is exceeded + for(;;seqovl=0) + { +#endif + if (seqovl) + { + seg_len = to-from+seqovl; + if (seg_len>sizeof(ovlseg)) + { + DLOG("seqovl is too large"); + return verdict; + } + fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); + memcpy(ovlseg+seqovl,dis->data_payload+from,to-from); + seg = ovlseg; + } + else + { + seqovl = 0; + seg = dis->data_payload+from; + seg_len = to-from; + } + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, + net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, + dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), + fooling_orig,0,0, + seg, seg_len, pkt1, &pkt1_len)) + return verdict; + DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ",i+1,from,to-1,to-from,seqovl); + hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + { +#ifdef __linux__ + if (errno==EMSGSIZE && seqovl) + { + DLOG("MTU exceeded. cancelling seqovl.\n"); + continue; + } +#endif + return verdict; + } +#ifdef __linux__ + break; + } +#endif from = to; } @@ -1298,20 +1338,44 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint case DESYNC_MULTIDISORDER: if (multisplit_count) { - size_t from,to; + uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; + size_t seg_len,from,to; + unsigned int seqovl; for (i=multisplit_count-1,to=dis->len_payload ; i>=-1 ; i--) { from = i>=0 ? multisplit_pos[i] : 0; + seg = dis->data_payload+from; + seg_len = to-from; + seqovl = 0; + if (i>=0 && dp->desync_seqovl) + { + if (dp->desync_seqovl>=from) + DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl for part %d.\n",dp->desync_seqovl,from,i+2); + else + { + seqovl = dp->desync_seqovl; + seg_len = to-from+seqovl; + if (seg_len>sizeof(ovlseg)) + { + DLOG("seqovl is too large"); + return verdict; + } + fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); + memcpy(ovlseg+seqovl,dis->data_payload+from,to-from); + seg = ovlseg; + } + } + pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, - net32_add(dis->tcp->th_seq,from), dis->tcp->th_ack, + net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), fooling_orig,0,0, - dis->data_payload+from, to-from, pkt1, &pkt1_len)) + seg, seg_len, pkt1, &pkt1_len)) return verdict; - DLOG("sending multisplit part %d %zu-%zu len=%zu : ",i+2,from,to-1,to-from); - hexdump_limited_dlog(dis->data_payload+from,to-from,PKTDATA_MAXDUMP); DLOG("\n"); + DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ",i+2,from,to-1,to-from,seqovl); + hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) return verdict; @@ -1423,34 +1487,53 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint return verdict; } - if (dp->desync_seqovl) + unsigned int seqovl = dp->desync_seqovl; +#ifdef __linux__ +// only linux return error if MTU is exceeded + for(;;seqovl=0) { - seg_len = split_pos+dp->desync_seqovl; - if (seg_len>sizeof(ovlseg)) +#endif + if (seqovl) { - DLOG("seqovl is too large"); + seg_len = split_pos+seqovl; + if (seg_len>sizeof(ovlseg)) + { + DLOG("seqovl is too large"); + return verdict; + } + fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); + memcpy(ovlseg+seqovl,dis->data_payload,split_pos); + seg = ovlseg; + } + else + { + seg = dis->data_payload; + seg_len = split_pos; + } + + pkt1_len = sizeof(pkt1); + if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,-seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, + ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), + fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, + seg, seg_len, pkt1, &pkt1_len)) + return verdict; + DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ",split_pos-1, split_pos, seqovl); + hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); + if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) + { +#ifdef __linux__ + if (errno==EMSGSIZE && seqovl) + { + DLOG("MTU exceeded. cancelling seqovl.\n"); + continue; + } +#endif return verdict; } - fill_pattern(ovlseg,dp->desync_seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); - memcpy(ovlseg+dp->desync_seqovl,dis->data_payload,split_pos); - seg = ovlseg; +#ifdef __linux__ + break; } - else - { - seg = dis->data_payload; - seg_len = split_pos; - } - - pkt1_len = sizeof(pkt1); - if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,-dp->desync_seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, - ttl_orig,IP4_TOS(dis->ip),IP6_FLOW(dis->ip6), - fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, - seg, seg_len, pkt1, &pkt1_len)) - return verdict; - DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ",split_pos-1, split_pos, dp->desync_seqovl); - hexdump_limited_dlog(seg,seg_len,PKTDATA_MAXDUMP); DLOG("\n"); - if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) - return verdict; +#endif if (desync_mode==DESYNC_FAKEDSPLIT) { @@ -1524,6 +1607,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (bFake) { + // if we are here original message was not sent in any form + // allowing system to pass the message to queue can result in unpredicted send order DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", dis->len_pkt, dis->len_payload); verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6); if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , dis->data_pkt, dis->len_pkt)) From 08238664cda3ee950bfba46d45b932a8c9080bf4 Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 12 Nov 2024 17:48:43 +0300 Subject: [PATCH 2/4] docs compile: move binaries in ipk to /opt/zapret/binaries/my --- docs/compile/build_howto_openwrt.txt | 42 +++++++++---------- .../openwrt/package/zapret/ip2net/Makefile | 4 +- .../openwrt/package/zapret/ip2net/readme.txt | 2 +- .../openwrt/package/zapret/mdig/Makefile | 4 +- .../openwrt/package/zapret/mdig/readme.txt | 2 +- .../openwrt/package/zapret/nfqws/Makefile | 4 +- .../openwrt/package/zapret/nfqws/readme.txt | 2 +- .../openwrt/package/zapret/tpws/Makefile | 4 +- .../openwrt/package/zapret/tpws/readme.txt | 2 +- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/compile/build_howto_openwrt.txt b/docs/compile/build_howto_openwrt.txt index d81ee24..9ff5f1a 100644 --- a/docs/compile/build_howto_openwrt.txt +++ b/docs/compile/build_howto_openwrt.txt @@ -1,21 +1,21 @@ -How to compile native programs for use in openwrt -------------------------------------------------- - -1) Download latest SDK for your platform from https://downloads.openwrt.org - - curl -o - https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz | tar -Jxvf - - cd openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64 - -2) ./scripts/feeds update -a - ./scripts/feeds install -a - -3) cp -R /opt/zapret/docs/compile/openwrt/. . - cp -R /opt/zapret/tpws package/zapret/tpws - cp -R /opt/zapret/nfq package/zapret/nfqws - cp -R /opt/zapret/mdig package/zapret/mdig - cp -R /opt/zapret/ip2net package/zapret/ip2net - -4) make package/{tpws,nfqws,mdig,ip2net}/compile - -5) find bin -name tpws*.ipk - #take your tpws*.ipk , nfqws*.ipk , ip2net*.ipk, mdig*.ipk from there +How to compile native programs for use in openwrt +------------------------------------------------- + +1) Download latest SDK for your platform from https://downloads.openwrt.org + + curl -o - https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz | tar -Jxvf - + cd openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64 + +2) ./scripts/feeds update -a + ./scripts/feeds install -a + +3) cp -R /opt/zapret/docs/compile/openwrt/. . + cp -R /opt/zapret/tpws package/zapret/tpws + cp -R /opt/zapret/nfq package/zapret/nfqws + cp -R /opt/zapret/mdig package/zapret/mdig + cp -R /opt/zapret/ip2net package/zapret/ip2net + +4) make package/{tpws,nfqws,mdig,ip2net}/compile + +5) find bin -name tpws*.ipk + #take your tpws*.ipk , nfqws*.ipk , ip2net*.ipk, mdig*.ipk from there diff --git a/docs/compile/openwrt/package/zapret/ip2net/Makefile b/docs/compile/openwrt/package/zapret/ip2net/Makefile index 4564675..bec7c00 100644 --- a/docs/compile/openwrt/package/zapret/ip2net/Makefile +++ b/docs/compile/openwrt/package/zapret/ip2net/Makefile @@ -24,8 +24,8 @@ define Build/Compile endef define Package/ip2net/install - $(INSTALL_DIR) $(1)/opt/zapret/ip2net - $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/ip2net + $(INSTALL_DIR) $(1)/opt/zapret/binaries/my + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/binaries/my endef $(eval $(call BuildPackage,ip2net)) diff --git a/docs/compile/openwrt/package/zapret/ip2net/readme.txt b/docs/compile/openwrt/package/zapret/ip2net/readme.txt index abf7acd..a5674f5 100644 --- a/docs/compile/openwrt/package/zapret/ip2net/readme.txt +++ b/docs/compile/openwrt/package/zapret/ip2net/readme.txt @@ -1 +1 @@ -Copy "ip2net" folder here ! +Copy "ip2net" folder here ! diff --git a/docs/compile/openwrt/package/zapret/mdig/Makefile b/docs/compile/openwrt/package/zapret/mdig/Makefile index 55d55d2..e587539 100644 --- a/docs/compile/openwrt/package/zapret/mdig/Makefile +++ b/docs/compile/openwrt/package/zapret/mdig/Makefile @@ -24,8 +24,8 @@ define Build/Compile endef define Package/mdig/install - $(INSTALL_DIR) $(1)/opt/zapret/mdig - $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/mdig + $(INSTALL_DIR) $(1)/opt/zapret/binaries/my + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/binaries/my endef $(eval $(call BuildPackage,mdig)) diff --git a/docs/compile/openwrt/package/zapret/mdig/readme.txt b/docs/compile/openwrt/package/zapret/mdig/readme.txt index 14e5c14..b1865b2 100644 --- a/docs/compile/openwrt/package/zapret/mdig/readme.txt +++ b/docs/compile/openwrt/package/zapret/mdig/readme.txt @@ -1 +1 @@ -Copy "mdig" folder here ! +Copy "mdig" folder here ! diff --git a/docs/compile/openwrt/package/zapret/nfqws/Makefile b/docs/compile/openwrt/package/zapret/nfqws/Makefile index 48b562f..781a2a9 100644 --- a/docs/compile/openwrt/package/zapret/nfqws/Makefile +++ b/docs/compile/openwrt/package/zapret/nfqws/Makefile @@ -25,8 +25,8 @@ define Build/Compile endef define Package/nfqws/install - $(INSTALL_DIR) $(1)/opt/zapret/nfq - $(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/nfq + $(INSTALL_DIR) $(1)/opt/zapret/binaries/my + $(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/binaries/my endef $(eval $(call BuildPackage,nfqws)) diff --git a/docs/compile/openwrt/package/zapret/nfqws/readme.txt b/docs/compile/openwrt/package/zapret/nfqws/readme.txt index daf8b84..4c5b89f 100644 --- a/docs/compile/openwrt/package/zapret/nfqws/readme.txt +++ b/docs/compile/openwrt/package/zapret/nfqws/readme.txt @@ -1 +1 @@ -Copy "nfq" folder here ! +Copy "nfq" folder here ! diff --git a/docs/compile/openwrt/package/zapret/tpws/Makefile b/docs/compile/openwrt/package/zapret/tpws/Makefile index 3f8dfc7..831c255 100644 --- a/docs/compile/openwrt/package/zapret/tpws/Makefile +++ b/docs/compile/openwrt/package/zapret/tpws/Makefile @@ -25,8 +25,8 @@ define Build/Compile endef define Package/tpws/install - $(INSTALL_DIR) $(1)/opt/zapret/tpws - $(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/tpws + $(INSTALL_DIR) $(1)/opt/zapret/binaries/my + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/binaries/my endef $(eval $(call BuildPackage,tpws)) diff --git a/docs/compile/openwrt/package/zapret/tpws/readme.txt b/docs/compile/openwrt/package/zapret/tpws/readme.txt index 18fa3ed..60297f8 100644 --- a/docs/compile/openwrt/package/zapret/tpws/readme.txt +++ b/docs/compile/openwrt/package/zapret/tpws/readme.txt @@ -1 +1 @@ -Copy "tpws" folder here ! +Copy "tpws" folder here ! From 28797184e47b205a49efd6e5ccc18a02a3b4fac5 Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 12 Nov 2024 18:35:14 +0300 Subject: [PATCH 3/4] nfqws: apply seqovl only to the first multisplit part to prevent server races --- nfq/desync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nfq/desync.c b/nfq/desync.c index 700bfe4..620fbb8 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -1280,7 +1280,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { to = i==multisplit_count ? dis->len_payload : multisplit_pos[i]; - seqovl = dp->desync_seqovl; + // do seqovl only to the first packet + // otherwise it's prone to race condition on server side + // what happens first : server pushes socket buffer to process or another packet with seqovl arrives + seqovl = i==0 ? dp->desync_seqovl : 0; #ifdef __linux__ // only linux return error if MTU is exceeded for(;;seqovl=0) From 8bc74333b8324e81fc32166353ec341a8b3f0171 Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 12 Nov 2024 21:49:01 +0300 Subject: [PATCH 4/4] nfqws: fallback to unknown proto pos if failed to resolve known proto pos --- nfq/desync.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nfq/desync.c b/nfq/desync.c index 620fbb8..53aba77 100644 --- a/nfq/desync.c +++ b/nfq/desync.c @@ -1179,6 +1179,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { multisplit_count=0; split_pos = ResolvePos(rdata_payload, rlen_payload, l7proto, spos); + if (!split_pos) split_pos = dp->split_unknown.pos; DLOG("regular split pos: %zu\n",split_pos); if (!split_pos || split_pos>rlen_payload) split_pos=1; split_pos=pos_normalize(split_pos,reasm_offset,dis->len_payload);