|
|
|
@@ -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
|
|
|
|
|