nfqws: ip_id fixes, more altorder support

This commit is contained in:
bol-van
2025-10-04 11:02:23 +03:00
parent beb0692d28
commit dcd9cfbb2b
8 changed files with 1974 additions and 1879 deletions

View File

@@ -83,6 +83,8 @@ typedef struct
bool b_cutoff; // mark for deletion bool b_cutoff; // mark for deletion
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff;
uint16_t ip_id;
t_l7proto l7proto; t_l7proto l7proto;
bool l7proto_discovered; bool l7proto_discovered;
char *hostname; char *hostname;

View File

@@ -420,7 +420,7 @@ bool prepare_udp_segment4(
memcpy(payload,data,len); memcpy(payload,data,len);
if (padding) if (padding)
fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0);
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
@@ -509,7 +509,7 @@ bool prepare_udp_segment6(
memcpy(payload,data,len); memcpy(payload,data,len);
if (padding) if (padding)
fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0);
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);

View File

@@ -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 3 split pos : host, endhost, midhost
if (multisplit_count >= 2) if (multisplit_count >= 2)
{ {
uint16_t ip_id_fake = (uint16_t)random();
uint8_t *seg; uint8_t *seg;
size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz; size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz;
uint8_t *fakehost; uint8_t *fakehost;
uint16_t ip_id_after_host;
seg = dis->data_payload; seg = dis->data_payload;
seg_len = dis->len_payload; seg_len = dis->len_payload;
@@ -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; pos_split_host = multisplit_count >= 3 ? multisplit_pos[2] : 0;
host_size = pos_endhost - pos_host; host_size = pos_endhost - pos_host;
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
// before_host segment // before_host segment
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
@@ -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)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
goto send_orig; 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))) if (!(fakehost = malloc(host_size + 1)))
{ {
DLOG("fakehost out of memory\n"); DLOG("fakehost out of memory\n");
@@ -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_az(fakehost, 1);
fill_random_az09(fakehost + 1, host_size - 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; fakehost[host_size] = 0;
DLOG("generated fake host: %s\n", fakehost); DLOG("generated fake host: %s\n", fakehost);
@@ -2093,15 +2089,29 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
pkt2_len = sizeof(pkt2); pkt2_len = sizeof(pkt2);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, 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, 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, dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
fakehost, host_size, pkt2, &pkt2_len)) fakehost, host_size, pkt2, &pkt2_len))
goto send_orig_clean; goto send_orig_clean;
DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
goto send_orig_clean; 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) 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); DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost);
@@ -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, 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, net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack,
dis->tcp->th_win, scale_factor, timestamps, 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, fooling_orig, 0, 0, 0,
seg + pos_host, sz, pkt1, &pkt1_len)) seg + pos_host, sz, pkt1, &pkt1_len))
goto send_orig_clean; goto send_orig_clean;
@@ -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; sz = pos_endhost - pos_split_host;
pkt1_len = sizeof(pkt1); 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, 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, net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack,
dis->tcp->th_win, scale_factor, timestamps, 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, fooling_orig, 0, 0, 0,
seg + pos_split_host, sz, pkt1, &pkt1_len)) seg + pos_split_host, sz, pkt1, &pkt1_len))
goto send_orig_clean; goto send_orig_clean;
@@ -2156,12 +2167,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
free(fakehost); free(fakehost);
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host);
return VERDICT_DROP; return VERDICT_DROP;
send_orig_clean: send_orig_clean:
free(fakehost); free(fakehost);
goto send_orig; goto send_orig;
} }
break; else
goto unsplitted_part;
case DESYNC_MULTISPLIT: case DESYNC_MULTISPLIT:
if (multisplit_count) if (multisplit_count)
{ {
@@ -2169,6 +2185,8 @@ send_orig_clean:
size_t seg_len, from, to; size_t seg_len, from, to;
unsigned int seqovl; unsigned int seqovl;
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
for (i = 0, from = 0; i <= multisplit_count; i++) for (i = 0, from = 0; i <= multisplit_count; i++)
{ {
to = i == multisplit_count ? dis->len_payload : multisplit_pos[i]; to = i == multisplit_count ? dis->len_payload : multisplit_pos[i];
@@ -2190,7 +2208,7 @@ send_orig_clean:
DLOG("seqovl is too large"); DLOG("seqovl is too large");
goto send_orig; 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); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
seg = ovlseg; seg = ovlseg;
} }
@@ -2230,17 +2248,26 @@ send_orig_clean:
from = to; from = to;
} }
if (replay) ctrack_replay->ip_id = ip_id;
return VERDICT_DROP; return VERDICT_DROP;
} }
break; else
goto unsplitted_part;
case DESYNC_MULTIDISORDER: case DESYNC_MULTIDISORDER:
if (multisplit_count) if (multisplit_count)
{ {
uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg; uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg;
size_t seg_len, from, to; size_t seg_len, from, to;
unsigned int seqovl; 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--) for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--)
{ {
from = i >= 0 ? multisplit_pos[i] : 0; from = i >= 0 ? multisplit_pos[i] : 0;
@@ -2264,7 +2291,7 @@ send_orig_clean:
DLOG("seqovl is too large"); DLOG("seqovl is too large");
goto send_orig; 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); memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
seg = ovlseg; seg = ovlseg;
} }
@@ -2286,32 +2313,45 @@ send_orig_clean:
to = from; to = from;
} }
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end);
return VERDICT_DROP; return VERDICT_DROP;
} }
break; else
goto unsplitted_part;
case DESYNC_FAKEDDISORDER: 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; 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; size_t seg_len, fakeseg2_len;
unsigned int seqovl; unsigned int seqovl;
int order;
if (dis->len_payload > sizeof(pat)) if (dis->len_payload > sizeof(pat))
{ {
DLOG("packet is too large\n"); DLOG("packet is too large\n");
goto send_orig; 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)
{
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos);
seqovl = 0; 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);
else else
seqovl = seqovl_pos; 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) if (seqovl)
{ {
@@ -2321,7 +2361,7 @@ send_orig_clean:
DLOG("seqovl is too large\n"); DLOG("seqovl is too large\n");
goto send_orig; 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); memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos);
seg = fakeseg; seg = fakeseg;
} }
@@ -2337,10 +2377,14 @@ send_orig_clean:
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment, 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)) pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
goto send_orig; goto send_orig;
}
pkt1_len = sizeof(pkt1); 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, 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,
@@ -2353,11 +2397,16 @@ send_orig_clean:
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
goto send_orig; goto send_orig;
}
if (split_pos)
{
ip_id = IP4_IP_ID_PREV(ip_id); ip_id = IP4_IP_ID_PREV(ip_id);
seg_len = sizeof(fakeseg); seg_len = sizeof(fakeseg);
@@ -2382,27 +2431,45 @@ send_orig_clean:
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
goto send_orig; goto send_orig;
}
}
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id);
return VERDICT_DROP; return VERDICT_DROP;
} }
break;
case DESYNC_FAKEDSPLIT: 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; 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; 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)) if (dis->len_payload > sizeof(pat))
{ {
DLOG("packet is too large\n"); DLOG("packet is too large\n");
goto send_orig; 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); 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, 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,
@@ -2411,16 +2478,15 @@ send_orig_clean:
pat, split_pos, fakeseg, &fakeseg_len)) pat, split_pos, fakeseg, &fakeseg_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
goto send_orig; 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__ #ifdef __linux__
// only linux return error if MTU is exceeded // only linux return error if MTU is exceeded
for (;; seqovl = 0) for (;; seqovl = 0)
@@ -2434,7 +2500,7 @@ send_orig_clean:
DLOG("seqovl is too large\n"); DLOG("seqovl is too large\n");
goto send_orig; 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); memcpy(ovlseg + seqovl, dis->data_payload, split_pos);
seg = ovlseg; seg = ovlseg;
} }
@@ -2468,23 +2534,22 @@ send_orig_clean:
break; break;
} }
#endif #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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
goto send_orig; goto send_orig;
} }
if (split_pos < dis->len_payload)
{
fakeseg_len = sizeof(fakeseg); 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, 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), 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, 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)) pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
@@ -2502,18 +2567,19 @@ send_orig_clean:
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
goto send_orig; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
goto send_orig; goto send_orig;
} }
}
if (replay) ctrack_replay->ip_id = ip_id;
return VERDICT_DROP; return VERDICT_DROP;
} }
break;
case DESYNC_IPFRAG2: case DESYNC_IPFRAG2:
if (!reasm_offset) if (!reasm_offset)
{ {
@@ -2569,6 +2635,17 @@ send_orig:
if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake)) 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); verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp);
return verdict; 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 // return : true - should continue, false - should stop with verdict

View File

@@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
return true; 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; 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) while (bufsize)
{ {
size = bufsize>patsize ? patsize : bufsize; size = bufsize>patsize ? patsize : bufsize;

View File

@@ -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); 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); int fprint_localtime(FILE *F);

View File

@@ -583,8 +583,7 @@ static int win_main(const char *windivert_filter)
return 0; return 0;
} }
usleep(500000); usleep(500000);
} } while (!logical_net_filter_match());
while (!logical_net_filter_match());
DLOG_CONDUP("logical network now present\n"); DLOG_CONDUP("logical network now present\n");
} }
@@ -820,7 +819,8 @@ static bool parse_autottl(const char *s, autottl *t, int8_t def_delta, uint8_t d
{ {
neg = false; neg = false;
s++; s++;
} else if (*s=='-') }
else if (*s == '-')
s++; s++;
switch (sscanf(s, "%u:%u-%u", &delta, &min, &max)) switch (sscanf(s, "%u:%u-%u", &delta, &min, &max))
{ {
@@ -1204,7 +1204,8 @@ static bool parse_fakedsplit_mod(char *opt, struct fakedsplit_mod *fs_mod)
{ {
if (!e2 || !e2[1] || e2[1] == ',') goto err; if (!e2 || !e2[1] || e2[1] == ',') goto err;
fs_mod->ordering = atoi(e2 + 1); fs_mod->ordering = atoi(e2 + 1);
if (fs_mod->ordering<0 || fs_mod->ordering>3) goto err; // unsplitted altorder in 0x03 mask. 0x04 reserved. splitted altorder in 0x18 mask
if ((fs_mod->ordering & 0xFFFFFFE4) || (((fs_mod->ordering>>3) & 3)>2)) goto err;
} }
else if (strcmp(p, "none")) else if (strcmp(p, "none"))
goto err; goto err;
@@ -1331,8 +1332,6 @@ static void SplitDebug(void)
} }
} }
static const char * tld[]={"com","org","net","edu","gov","biz"};
static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache) static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
{ {
const uint8_t *ext; const uint8_t *ext;
@@ -2758,15 +2757,18 @@ int main(int argc, char **argv)
char buf[sizeof(dp->seqovl_pattern)]; char buf[sizeof(dp->seqovl_pattern)];
size_t sz = sizeof(buf); size_t sz = sizeof(buf);
load_file_or_exit(optarg, buf, &sz, NULL); load_file_or_exit(optarg, buf, &sz, NULL);
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz); fill_pattern(dp->seqovl_pattern, sizeof(dp->seqovl_pattern), buf, sz, 0);
} }
break; break;
case IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN: case IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN:
{ {
char buf[sizeof(dp->fsplit_pattern)]; if (!(dp->fsplit_pattern = malloc(dp->fsplit_pattern_size=32768)))
size_t sz=sizeof(buf); {
load_file_or_exit(optarg,buf,&sz,NULL); DLOG_ERR("out of memory\n");
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz); exit_clean(1);
}
load_file_or_exit(optarg, dp->fsplit_pattern, &dp->fsplit_pattern_size, NULL);
dp->fsplit_pattern = realloc(dp->fsplit_pattern, dp->fsplit_pattern_size);
} }
break; break;
case IDX_DPI_DESYNC_FAKEDSPLIT_MOD: case IDX_DPI_DESYNC_FAKEDSPLIT_MOD:
@@ -2916,7 +2918,7 @@ int main(int argc, char **argv)
char buf[sizeof(dp->udplen_pattern)]; char buf[sizeof(dp->udplen_pattern)];
size_t sz = sizeof(buf); size_t sz = sizeof(buf);
load_file_or_exit(optarg, buf, &sz, NULL); load_file_or_exit(optarg, buf, &sz, NULL);
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz); fill_pattern(dp->udplen_pattern, sizeof(dp->udplen_pattern), buf, sz, 0);
} }
break; break;
case IDX_DPI_DESYNC_CUTOFF: case IDX_DPI_DESYNC_CUTOFF:

View File

@@ -20,6 +20,7 @@ const char *progname = "nfqws";
#error UNKNOWN_SYSTEM_TIME #error UNKNOWN_SYSTEM_TIME
#endif #endif
const char * tld[6] = { "com","org","net","edu","gov","biz" };
int DLOG_FILE(FILE *F, const char *format, va_list args) int DLOG_FILE(FILE *F, const char *format, va_list args)
{ {
@@ -297,6 +298,8 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
} }
static void dp_clear_dynamic(struct desync_profile *dp) static void dp_clear_dynamic(struct desync_profile *dp)
{ {
free(dp->fsplit_pattern);
hostlist_collection_destroy(&dp->hl_collection); hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&dp->hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&dp->ips_collection); ipset_collection_destroy(&dp->ips_collection);

View File

@@ -68,6 +68,8 @@
#define MAX_GIDS 64 #define MAX_GIDS 64
extern const char * tld[6];
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID }; enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID };
struct fake_tls_mod_cache struct fake_tls_mod_cache
@@ -140,8 +142,9 @@ struct desync_profile
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment; uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun; struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP]; uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
size_t fake_syndata_size; uint8_t *fsplit_pattern;
size_t fake_syndata_size, fsplit_pattern_size;
struct fake_tls_mod tls_mod_last; struct fake_tls_mod tls_mod_last;
struct blob_item *tls_fake_last; struct blob_item *tls_fake_last;