Loading nfq/conntrack.h +3 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,8 @@ typedef struct bool b_cutoff; // mark for deletion bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; uint16_t ip_id; t_l7proto l7proto; bool l7proto_discovered; char *hostname; Loading nfq/darkmagic.c +2 −2 Original line number Diff line number Diff line Loading @@ -420,7 +420,7 @@ bool prepare_udp_segment4( memcpy(payload,data,len); if (padding) fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); Loading Loading @@ -509,7 +509,7 @@ bool prepare_udp_segment6( memcpy(payload,data,len); if (padding) fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); Loading nfq/desync.c +1257 −1180 Original line number Diff line number Diff line Loading @@ -2015,10 +2015,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint // if 3 split pos : host, endhost, midhost if (multisplit_count >= 2) { uint16_t ip_id_fake = (uint16_t)random(); uint8_t *seg; size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz; uint8_t *fakehost; uint16_t ip_id_after_host; seg = dis->data_payload; seg_len = dis->len_payload; Loading @@ -2027,6 +2027,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint pos_split_host = multisplit_count >= 3 ? multisplit_pos[2] : 0; host_size = pos_endhost - pos_host; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; // before_host segment pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, Loading @@ -2042,16 +2044,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; // pkt3: after_host segment pkt3_len = sizeof(pkt3); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,pos_endhost), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), fooling_orig,0,0,0, seg+pos_endhost, seg_len-pos_endhost, pkt3, &pkt3_len)) goto send_orig; if (!(fakehost = malloc(host_size + 1))) { DLOG("fakehost out of memory\n"); Loading Loading @@ -2084,7 +2076,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { fill_random_az(fakehost, 1); fill_random_az09(fakehost + 1, host_size - 1); if (host_size>=7) fakehost[host_size-4] = '.'; if (host_size >= 7) { fakehost[host_size - 4] = '.'; memcpy(fakehost + host_size - 3, tld[random() % (sizeof(tld) / sizeof(*tld))], 3); } } fakehost[host_size] = 0; DLOG("generated fake host: %s\n", fakehost); Loading @@ -2093,15 +2089,29 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint pkt2_len = sizeof(pkt2); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_fake,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, fakehost, host_size, pkt2, &pkt2_len)) goto send_orig_clean; DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size); hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) goto send_orig_clean; ip_id_after_host = IP4_IP_ID_NEXT(ip_id); if (pos_split_host) ip_id_after_host = IP4_IP_ID_NEXT(ip_id_after_host); // pkt3: after_host segment pkt3_len = sizeof(pkt3); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_endhost), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF, ttl_orig, IP4_TOS(dis->ip), ip_id_after_host, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_endhost, seg_len - pos_endhost, pkt3, &pkt3_len)) goto send_orig_clean; if (dp->hfs_mod.ordering == 1) { DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost); Loading @@ -2115,7 +2125,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_host, sz, pkt1, &pkt1_len)) goto send_orig_clean; Loading @@ -2129,10 +2139,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { sz = pos_endhost - pos_split_host; pkt1_len = sizeof(pkt1); ip_id = IP4_IP_ID_NEXT(ip_id); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),net16_add(ip_id_fake,1),IP6_FLOW(dis->ip6), DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_split_host, sz, pkt1, &pkt1_len)) goto send_orig_clean; Loading @@ -2156,12 +2167,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } free(fakehost); if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host); return VERDICT_DROP; send_orig_clean: free(fakehost); goto send_orig; } break; else goto unsplitted_part; case DESYNC_MULTISPLIT: if (multisplit_count) { Loading @@ -2169,6 +2185,8 @@ send_orig_clean: size_t seg_len, from, to; unsigned int seqovl; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; for (i = 0, from = 0; i <= multisplit_count; i++) { to = i == multisplit_count ? dis->len_payload : multisplit_pos[i]; Loading @@ -2190,7 +2208,7 @@ send_orig_clean: DLOG("seqovl is too large"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); seg = ovlseg; } Loading Loading @@ -2230,17 +2248,26 @@ send_orig_clean: from = to; } if (replay) ctrack_replay->ip_id = ip_id; return VERDICT_DROP; } break; else goto unsplitted_part; case DESYNC_MULTIDISORDER: if (multisplit_count) { uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg; size_t seg_len, from, to; unsigned int seqovl; uint16_t ip_id_end; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; ip_id_end = ip_id = IP4_IP_ID_ADD(ip_id, (uint16_t)multisplit_count); ip_id=IP4_IP_ID_ADD(ip_id,(uint16_t)multisplit_count); for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--) { from = i >= 0 ? multisplit_pos[i] : 0; Loading @@ -2264,7 +2291,7 @@ send_orig_clean: DLOG("seqovl is too large"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); seg = ovlseg; } Loading @@ -2286,32 +2313,45 @@ send_orig_clean: to = from; } if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end); return VERDICT_DROP; } break; else goto unsplitted_part; case DESYNC_FAKEDDISORDER: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; size_t seg_len, fakeseg2_len; unsigned int seqovl; int order; if (dis->len_payload > sizeof(pat)) { DLOG("packet is too large\n"); goto send_orig; } fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); ip_id=IP4_IP_ID_NEXT(ip_id); if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; if (seqovl_pos>=split_pos) seqovl = 0; if (split_pos) { order = dp->fs_mod.ordering & 3; if (seqovl_pos >= split_pos) DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos); seqovl = 0; } else seqovl = seqovl_pos; ip_id = IP4_IP_ID_NEXT(ip_id); } else { order = (dp->fs_mod.ordering >> 3) & 3; } fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); if (seqovl) { Loading @@ -2321,7 +2361,7 @@ send_orig_clean: DLOG("seqovl is too large\n"); goto send_orig; } fill_pattern(fakeseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(fakeseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos); seg = fakeseg; } Loading @@ -2337,10 +2377,14 @@ send_orig_clean: dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len)) goto send_orig; if (order == 0) { DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) goto send_orig; } pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, Loading @@ -2353,11 +2397,16 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (order <= 1) { DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) goto send_orig; } if (split_pos) { ip_id = IP4_IP_ID_PREV(ip_id); seg_len = sizeof(fakeseg); Loading @@ -2382,27 +2431,45 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; if (order <= 2) { DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len)) goto send_orig; } } if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id); return VERDICT_DROP; } break; case DESYNC_FAKEDSPLIT: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; size_t fakeseg_len, seg_len; int order; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; if (dis->len_payload > sizeof(pat)) { DLOG("packet is too large\n"); goto send_orig; } fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); if (split_pos) { order = dp->fs_mod.ordering & 3; } else { order = (dp->fs_mod.ordering >> 3) & 3; split_pos = dis->len_payload; } fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, Loading @@ -2411,16 +2478,15 @@ send_orig_clean: pat, split_pos, fakeseg, &fakeseg_len)) goto send_orig; if (dp->fs_mod.ordering==0) if (order == 0) { ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } unsigned int seqovl = reasm_offset ? 0 : seqovl_pos; unsigned int seqovl = (reasm_offset || split_pos>=dis->len_payload) ? 0 : seqovl_pos; #ifdef __linux__ // only linux return error if MTU is exceeded for (;; seqovl = 0) Loading @@ -2434,7 +2500,7 @@ send_orig_clean: DLOG("seqovl is too large\n"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload, split_pos); seg = ovlseg; } Loading Loading @@ -2468,23 +2534,22 @@ send_orig_clean: break; } #endif if (dp->fs_mod.ordering<=1) if (order <= 1) { if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } if (split_pos < dis->len_payload) { fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len)) goto send_orig; ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) Loading @@ -2502,18 +2567,19 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (dp->fs_mod.ordering<=2) if (order <= 2) { if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } } if (replay) ctrack_replay->ip_id = ip_id; return VERDICT_DROP; } break; case DESYNC_IPFRAG2: if (!reasm_offset) { Loading Loading @@ -2569,6 +2635,17 @@ send_orig: if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake)) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp); return verdict; unsplitted_part: if (replay && dis->ip && ctrack_replay->ip_id) { DLOG("changing ip_id of unsplitted part\n"); dis->ip->ip_id = ctrack_replay->ip_id; ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id); return VERDICT_MODIFY; } goto send_orig; } // return : true - should continue, false - should stop with verdict Loading nfq/helpers.c +9 −1 Original line number Diff line number Diff line Loading @@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size) return true; } void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize) void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset) { size_t size; if (offset%=patsize) { size = patsize-offset; size = bufsize>size ? size : bufsize; memcpy(buf,pattern+offset,size); buf += size; bufsize -= size; } while (bufsize) { size = bufsize>patsize ? patsize : bufsize; Loading nfq/helpers.h +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ static inline uint32_t pntoh32(const uint8_t *p) { } bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset); int fprint_localtime(FILE *F); Loading Loading
nfq/conntrack.h +3 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,8 @@ typedef struct bool b_cutoff; // mark for deletion bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; uint16_t ip_id; t_l7proto l7proto; bool l7proto_discovered; char *hostname; Loading
nfq/darkmagic.c +2 −2 Original line number Diff line number Diff line Loading @@ -420,7 +420,7 @@ bool prepare_udp_segment4( memcpy(payload,data,len); if (padding) fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); Loading Loading @@ -509,7 +509,7 @@ bool prepare_udp_segment6( memcpy(payload,data,len); if (padding) fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0); else memset(payload+len,0,padlen); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); Loading
nfq/desync.c +1257 −1180 Original line number Diff line number Diff line Loading @@ -2015,10 +2015,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint // if 3 split pos : host, endhost, midhost if (multisplit_count >= 2) { uint16_t ip_id_fake = (uint16_t)random(); uint8_t *seg; size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz; uint8_t *fakehost; uint16_t ip_id_after_host; seg = dis->data_payload; seg_len = dis->len_payload; Loading @@ -2027,6 +2027,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint pos_split_host = multisplit_count >= 3 ? multisplit_pos[2] : 0; host_size = pos_endhost - pos_host; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; // before_host segment pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, Loading @@ -2042,16 +2044,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; // pkt3: after_host segment pkt3_len = sizeof(pkt3); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq,pos_endhost), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), fooling_orig,0,0,0, seg+pos_endhost, seg_len-pos_endhost, pkt3, &pkt3_len)) goto send_orig; if (!(fakehost = malloc(host_size + 1))) { DLOG("fakehost out of memory\n"); Loading Loading @@ -2084,7 +2076,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { fill_random_az(fakehost, 1); fill_random_az09(fakehost + 1, host_size - 1); if (host_size>=7) fakehost[host_size-4] = '.'; if (host_size >= 7) { fakehost[host_size - 4] = '.'; memcpy(fakehost + host_size - 3, tld[random() % (sizeof(tld) / sizeof(*tld))], 3); } } fakehost[host_size] = 0; DLOG("generated fake host: %s\n", fakehost); Loading @@ -2093,15 +2089,29 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint pkt2_len = sizeof(pkt2); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_fake,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, fakehost, host_size, pkt2, &pkt2_len)) goto send_orig_clean; DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size); hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len)) goto send_orig_clean; ip_id_after_host = IP4_IP_ID_NEXT(ip_id); if (pos_split_host) ip_id_after_host = IP4_IP_ID_NEXT(ip_id_after_host); // pkt3: after_host segment pkt3_len = sizeof(pkt3); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_endhost), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF, ttl_orig, IP4_TOS(dis->ip), ip_id_after_host, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_endhost, seg_len - pos_endhost, pkt3, &pkt3_len)) goto send_orig_clean; if (dp->hfs_mod.ordering == 1) { DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost); Loading @@ -2115,7 +2125,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),ip_id_fake,IP6_FLOW(dis->ip6), DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_host, sz, pkt1, &pkt1_len)) goto send_orig_clean; Loading @@ -2129,10 +2139,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint { sz = pos_endhost - pos_split_host; pkt1_len = sizeof(pkt1); ip_id = IP4_IP_ID_NEXT(ip_id); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF,ttl_orig,IP4_TOS(dis->ip),net16_add(ip_id_fake,1),IP6_FLOW(dis->ip6), DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, 0, 0, 0, seg + pos_split_host, sz, pkt1, &pkt1_len)) goto send_orig_clean; Loading @@ -2156,12 +2167,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint } free(fakehost); if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host); return VERDICT_DROP; send_orig_clean: free(fakehost); goto send_orig; } break; else goto unsplitted_part; case DESYNC_MULTISPLIT: if (multisplit_count) { Loading @@ -2169,6 +2185,8 @@ send_orig_clean: size_t seg_len, from, to; unsigned int seqovl; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; for (i = 0, from = 0; i <= multisplit_count; i++) { to = i == multisplit_count ? dis->len_payload : multisplit_pos[i]; Loading @@ -2190,7 +2208,7 @@ send_orig_clean: DLOG("seqovl is too large"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); seg = ovlseg; } Loading Loading @@ -2230,17 +2248,26 @@ send_orig_clean: from = to; } if (replay) ctrack_replay->ip_id = ip_id; return VERDICT_DROP; } break; else goto unsplitted_part; case DESYNC_MULTIDISORDER: if (multisplit_count) { uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg; size_t seg_len, from, to; unsigned int seqovl; uint16_t ip_id_end; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; ip_id_end = ip_id = IP4_IP_ID_ADD(ip_id, (uint16_t)multisplit_count); ip_id=IP4_IP_ID_ADD(ip_id,(uint16_t)multisplit_count); for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--) { from = i >= 0 ? multisplit_pos[i] : 0; Loading @@ -2264,7 +2291,7 @@ send_orig_clean: DLOG("seqovl is too large"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from); seg = ovlseg; } Loading @@ -2286,32 +2313,45 @@ send_orig_clean: to = from; } if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end); return VERDICT_DROP; } break; else goto unsplitted_part; case DESYNC_FAKEDDISORDER: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; size_t seg_len, fakeseg2_len; unsigned int seqovl; int order; if (dis->len_payload > sizeof(pat)) { DLOG("packet is too large\n"); goto send_orig; } fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); ip_id=IP4_IP_ID_NEXT(ip_id); if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; if (seqovl_pos>=split_pos) seqovl = 0; if (split_pos) { order = dp->fs_mod.ordering & 3; if (seqovl_pos >= split_pos) DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos); seqovl = 0; } else seqovl = seqovl_pos; ip_id = IP4_IP_ID_NEXT(ip_id); } else { order = (dp->fs_mod.ordering >> 3) & 3; } fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); if (seqovl) { Loading @@ -2321,7 +2361,7 @@ send_orig_clean: DLOG("seqovl is too large\n"); goto send_orig; } fill_pattern(fakeseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(fakeseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos); seg = fakeseg; } Loading @@ -2337,10 +2377,14 @@ send_orig_clean: dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len)) goto send_orig; if (order == 0) { DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) goto send_orig; } pkt1_len = sizeof(pkt1); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, Loading @@ -2353,11 +2397,16 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (order <= 1) { DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len)) goto send_orig; } if (split_pos) { ip_id = IP4_IP_ID_PREV(ip_id); seg_len = sizeof(fakeseg); Loading @@ -2382,27 +2431,45 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; if (order <= 2) { DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len)) goto send_orig; } } if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id); return VERDICT_DROP; } break; case DESYNC_FAKEDSPLIT: if (split_pos) { uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg; size_t fakeseg_len, seg_len; int order; if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; if (dis->len_payload > sizeof(pat)) { DLOG("packet is too large\n"); goto send_orig; } fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern)); fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset); if (split_pos) { order = dp->fs_mod.ordering & 3; } else { order = (dp->fs_mod.ordering >> 3) & 3; split_pos = dis->len_payload; } fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, Loading @@ -2411,16 +2478,15 @@ send_orig_clean: pat, split_pos, fakeseg, &fakeseg_len)) goto send_orig; if (dp->fs_mod.ordering==0) if (order == 0) { ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } unsigned int seqovl = reasm_offset ? 0 : seqovl_pos; unsigned int seqovl = (reasm_offset || split_pos>=dis->len_payload) ? 0 : seqovl_pos; #ifdef __linux__ // only linux return error if MTU is exceeded for (;; seqovl = 0) Loading @@ -2434,7 +2500,7 @@ send_orig_clean: DLOG("seqovl is too large\n"); goto send_orig; } fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern)); fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0); memcpy(ovlseg + seqovl, dis->data_payload, split_pos); seg = ovlseg; } Loading Loading @@ -2468,23 +2534,22 @@ send_orig_clean: break; } #endif if (dp->fs_mod.ordering<=1) if (order <= 1) { if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos); hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } if (split_pos < dis->len_payload) { fakeseg_len = sizeof(fakeseg); if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len)) goto send_orig; ip_id=IP4_IP_ID_NEXT(ip_id); DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) Loading @@ -2502,18 +2567,19 @@ send_orig_clean: if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) goto send_orig; if (dp->fs_mod.ordering<=2) if (order <= 2) { if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id; DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos); hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n"); if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len)) goto send_orig; } } if (replay) ctrack_replay->ip_id = ip_id; return VERDICT_DROP; } break; case DESYNC_IPFRAG2: if (!reasm_offset) { Loading Loading @@ -2569,6 +2635,17 @@ send_orig: if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake)) verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp); return verdict; unsplitted_part: if (replay && dis->ip && ctrack_replay->ip_id) { DLOG("changing ip_id of unsplitted part\n"); dis->ip->ip_id = ctrack_replay->ip_id; ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id); return VERDICT_MODIFY; } goto send_orig; } // return : true - should continue, false - should stop with verdict Loading
nfq/helpers.c +9 −1 Original line number Diff line number Diff line Loading @@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size) return true; } void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize) void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset) { size_t size; if (offset%=patsize) { size = patsize-offset; size = bufsize>size ? size : bufsize; memcpy(buf,pattern+offset,size); buf += size; bufsize -= size; } while (bufsize) { size = bufsize>patsize ? patsize : bufsize; Loading
nfq/helpers.h +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ static inline uint32_t pntoh32(const uint8_t *p) { } bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset); int fprint_localtime(FILE *F); Loading