Compare commits

..

No commits in common. "d21175b4a35a64973a6c6df1ee2ded7b8b510932" and "8b5dfcfae1aede51d0b43bdae9961dc6c3b6f166" have entirely different histories.

7 changed files with 132 additions and 180 deletions

View File

@ -143,11 +143,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
} }
else if (tcp_synack_segment(tcphdr)) else if (tcp_synack_segment(tcphdr))
{ {
// ignore SA dups if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
uint32_t seq0 = ntohl(tcphdr->th_ack)-1; if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
if (t->state!=SYN && t->seq0!=seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = seq0;
t->ack0 = ntohl(tcphdr->th_seq); t->ack0 = ntohl(tcphdr->th_seq);
} }
else if (tcphdr->th_flags & (TH_FIN|TH_RST)) else if (tcphdr->th_flags & (TH_FIN|TH_RST))

View File

@ -38,11 +38,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
return htons(ntohs(netorder_value)+cpuorder_increment); return htons(ntohs(netorder_value)+cpuorder_increment);
} }
bool ip_has_df(const struct ip *ip)
{
return ip && !!(ntohs(ip->ip_off) & IP_DF);
}
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind) uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
{ {
uint8_t *t = (uint8_t*)(tcp+1); uint8_t *t = (uint8_t*)(tcp+1);
@ -194,11 +189,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0; udp->uh_sum = 0;
} }
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id) static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
{ {
ip->ip_tos = tos; ip->ip_tos = tos;
ip->ip_sum = 0; ip->ip_sum = 0;
ip->ip_off = DF ? htons(IP_DF) : 0; ip->ip_off = 0;
ip->ip_v = 4; ip->ip_v = 4;
ip->ip_hl = 5; ip->ip_hl = 5;
ip->ip_len = htons(pktlen); ip->ip_len = htons(pktlen);
@ -227,7 +222,6 @@ bool prepare_tcp_segment4(
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -246,7 +240,7 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1); struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id); fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len); fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len); memcpy(payload,data,len);
@ -352,7 +346,6 @@ bool prepare_tcp_segment(
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -364,7 +357,7 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false; false;
@ -374,7 +367,6 @@ bool prepare_tcp_segment(
// padlen<0 means payload shrinking // padlen<0 means payload shrinking
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -401,7 +393,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1); uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id); fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen); fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len); memcpy(payload,data,len);
@ -506,7 +498,6 @@ bool prepare_udp_segment6(
} }
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -518,7 +509,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) : prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ? (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) : prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false; false;
@ -1837,7 +1828,6 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
uint8_t autottl_guess(uint8_t ttl, const autottl *attl) uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
{ {
uint8_t orig, path, fake; uint8_t orig, path, fake;
int d;
// 18.65.168.125 ( cloudfront ) 255 // 18.65.168.125 ( cloudfront ) 255
// 157.254.246.178 128 // 157.254.246.178 128
@ -1854,13 +1844,11 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
path = orig - ttl; path = orig - ttl;
d = (int)path + attl->delta; fake = path > attl->delta ? path - attl->delta : attl->min;
if (d<attl->min) fake=attl->min; if (fake<attl->min) fake=attl->min;
else if (d>attl->max) fake=attl->max; else if (fake>attl->max) fake=attl->max;
else fake=(uint8_t)d;
if (attl->delta<0 && fake>=path || attl->delta>=0 && fake<path) if (fake>=path) return 0;
return 0;
return fake; return fake;
} }
@ -1912,15 +1900,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr); tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
} }
@ -1929,15 +1917,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr); udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
} }

View File

@ -75,7 +75,6 @@ bool prepare_tcp_segment4(
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -109,7 +108,6 @@ bool prepare_tcp_segment(
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -123,7 +121,6 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -143,7 +140,6 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen); uint8_t *buf, size_t *buflen);
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -185,8 +181,6 @@ bool tcp_has_sack(struct tcphdr *tcp);
bool tcp_has_fastopen(const struct tcphdr *tcp); bool tcp_has_fastopen(const struct tcphdr *tcp);
bool ip_has_df(const struct ip *ip);
#ifdef __CYGWIN__ #ifdef __CYGWIN__
extern uint32_t w_win32_error; extern uint32_t w_win32_error;
@ -258,10 +252,9 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
typedef struct typedef struct
{ {
int8_t delta; uint8_t delta, min, max;
uint8_t min, max;
} autottl; } autottl;
#define AUTOTTL_DEFAULT_DELTA -1 #define AUTOTTL_DEFAULT_DELTA 1
#define AUTOTTL_DEFAULT_MIN 3 #define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20 #define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta) #define AUTOTTL_ENABLED(a) (!!(a).delta)

View File

@ -879,7 +879,7 @@ static bool orig_send_rewrite(
} }
// return : true - orig was sent completely, false - should send orig another way // return : true - orig was sent completely, false - should send orig another way
static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend) static bool tcp_orig_send(uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
{ {
if (dp->dup_repeats || bForceSend) if (dp->dup_repeats || bForceSend)
{ {
@ -890,12 +890,10 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
struct sockaddr_storage src, dst; struct sockaddr_storage src, dst;
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor; uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
uint32_t *timestamps; uint32_t *timestamps;
bool sack,DF; bool sack;
extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst); extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst);
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
if (dp->dup_repeats && check_dup_interval(dp,ctrack)) if (dp->dup_repeats && check_dup_interval(dp,ctrack))
{ {
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
@ -910,19 +908,19 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
sack = tcp_has_sack(dis->tcp); sack = tcp_has_sack(dis->tcp);
nmss = tcp_find_mss(dis->tcp); nmss = tcp_find_mss(dis->tcp);
ip_id = IP4_IP_ID_FIX(dis->ip); ip_id = IP4_IP_ID_FIX(dis->ip);
DF = ip_has_df(dis->ip);
len = sizeof(pkt); len = sizeof(pkt);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
flags_orig, sack, nmss, flags_orig, sack, nmss,
dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->dup_fooling_mode,dp->dup_badseq_increment,dp->dup_badseq_ack_increment, dp->dup_fooling_mode,dp->dup_badseq_increment,dp->dup_badseq_ack_increment,
dis->data_payload, dis->len_payload, pkt, &len)) dis->data_payload, dis->len_payload, pkt, &len))
{ {
DLOG_ERR("dup: packet reconstruct failed\n"); DLOG_ERR("dup: packet reconstruct failed\n");
return false; return false;
} }
DLOG("sending %u dups with packet reconstruct\n", dp->dup_repeats); DLOG("sending %u dups with packet reconstruct\n", dp->dup_repeats);
// send dups // send dups
@ -958,7 +956,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
return false; return false;
} }
// return : true - orig was sent completely, false - should send orig another way // return : true - orig was sent completely, false - should send orig another way
static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend) static bool udp_orig_send(uint32_t fwmark, const char *ifout, const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis, bool bForceSend)
{ {
if (dp->dup_repeats || bForceSend) if (dp->dup_repeats || bForceSend)
{ {
@ -968,18 +966,14 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
uint16_t ip_id; uint16_t ip_id;
struct sockaddr_storage src, dst; struct sockaddr_storage src, dst;
uint8_t ttl_orig,ttl_fake; uint8_t ttl_orig,ttl_fake;
bool DF;
extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst); extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst);
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
if (dp->dup_repeats && check_dup_interval(dp,ctrack)) if (dp->dup_repeats && check_dup_interval(dp,ctrack))
{ {
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = dis->ip6 ? dp->dup_ttl6 : dp->dup_ttl; ttl_fake = dis->ip6 ? dp->dup_ttl6 : dp->dup_ttl;
if (!ttl_fake) ttl_fake = ttl_orig; if (!ttl_fake) ttl_fake = ttl_orig;
DF = ip_has_df(dis->ip);
if (dp->dup_fooling_mode) if (dp->dup_fooling_mode)
{ {
@ -987,7 +981,7 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
len = sizeof(pkt); len = sizeof(pkt);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
DF,ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->dup_fooling_mode, NULL, 0, 0, dp->dup_fooling_mode, NULL, 0, 0,
dis->data_payload, dis->len_payload, pkt, &len)) dis->data_payload, dis->len_payload, pkt, &len))
{ {
@ -1048,7 +1042,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
size_t pkt1_len, pkt2_len; size_t pkt1_len, pkt2_len;
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor; uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
uint32_t *timestamps; uint32_t *timestamps;
bool bSack,DF; bool bSack;
uint16_t nmss; uint16_t nmss;
uint32_t desync_fwmark = fwmark | params.desync_fwmark; uint32_t desync_fwmark = fwmark | params.desync_fwmark;
@ -1213,7 +1207,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
timestamps = tcp_find_timestamps(dis->tcp); timestamps = tcp_find_timestamps(dis->tcp);
bSack = tcp_has_sack(dis->tcp); bSack = tcp_has_sack(dis->tcp);
nmss = tcp_find_mss(dis->tcp); nmss = tcp_find_mss(dis->tcp);
DF = ip_has_df(dis->ip);
if (!replay) if (!replay)
{ {
@ -1224,7 +1217,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_SYNACK: case DESYNC_SYNACK:
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, 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, TH_SYN|TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len)) NULL, 0, pkt1, &pkt1_len))
{ {
@ -1248,7 +1241,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, bSack, nmss, 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, bSack, nmss, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len)) 0,0,0, dp->fake_syndata,dp->fake_syndata_size, pkt1,&pkt1_len))
{ {
goto send_orig; goto send_orig;
@ -1461,8 +1454,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!replay) if (!replay)
{ {
maybe_cutoff(ctrack, IPPROTO_TCP); maybe_cutoff(ctrack, IPPROTO_TCP);
if (orig_mod(dp,ctrack,dis)) // ttl can change !
verdict = VERDICT_MODIFY;
if (!process_desync_interval(dp, ctrack)) if (!process_desync_interval(dp, ctrack))
{ {
reasm_orig_cancel(ctrack); reasm_orig_cancel(ctrack);
@ -1704,7 +1695,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
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,
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
fake_data, fake_item->size, pkt1, &pkt1_len)) fake_data, fake_item->size, pkt1, &pkt1_len))
{ {
@ -1728,7 +1719,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (reasm_offset) break; if (reasm_offset) break;
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode==DESYNC_RSTACK ? TH_ACK:0), 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, TH_RST | (dp->desync_mode==DESYNC_RSTACK ? TH_ACK:0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
NULL, 0, pkt1, &pkt1_len)) NULL, 0, pkt1, &pkt1_len))
{ {
@ -1756,7 +1747,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
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,
DF,ttl_orig,0,0,IP6_FLOW(dis->ip6), ttl_orig,0,0,IP6_FLOW(dis->ip6),
fooling_orig,0,0, fooling_orig,0,0,
dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
{ {
@ -1824,8 +1815,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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,
net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack,
dis->tcp->th_win, scale_factor, timestamps, dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,0,0, fooling_orig,0,0,
seg, seg_len, pkt1, &pkt1_len)) seg, seg_len, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -1894,8 +1884,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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,
net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack, net32_add(dis->tcp->th_seq,from-seqovl), dis->tcp->th_ack,
dis->tcp->th_win, scale_factor, timestamps, dis->tcp->th_win, scale_factor, timestamps,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,0,0, fooling_orig,0,0,
seg, seg_len, pkt1, &pkt1_len)) seg, seg_len, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -1954,7 +1943,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
fakeseg2_len = sizeof(fakeseg2); fakeseg2_len = sizeof(fakeseg2);
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), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,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;
@ -1966,7 +1955,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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,
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len)) seg, seg_len, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -1986,7 +1975,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
seg_len = sizeof(fakeseg); seg_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,
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat, split_pos, fakeseg, &seg_len)) pat, split_pos, fakeseg, &seg_len))
goto send_orig; goto send_orig;
@ -1998,7 +1987,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
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,
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
dis->data_payload, split_pos, pkt1, &pkt1_len)) dis->data_payload, split_pos, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -2034,7 +2023,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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,
DF,ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat, split_pos, fakeseg, &fakeseg_len)) pat, split_pos, fakeseg, &fakeseg_len))
goto send_orig; goto send_orig;
@ -2070,7 +2059,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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,-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,-seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
DF,ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
seg, seg_len, pkt1, &pkt1_len)) seg, seg_len, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -2101,7 +2090,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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), ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, dp->desync_fooling_mode,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;
@ -2113,7 +2102,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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), 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_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment, fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len)) dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len))
goto send_orig; goto send_orig;
@ -2179,6 +2168,9 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
default: default:
break; break;
} }
if (bFake)
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
} }
send_orig: send_orig:
@ -2186,7 +2178,7 @@ send_orig:
if ((verdict & VERDICT_MASK)==VERDICT_DROP) if ((verdict & VERDICT_MASK)==VERDICT_DROP)
verdict = ct_new_postnat_fix_tcp(ctrack, dis->ip, dis->ip6, dis->tcp); verdict = ct_new_postnat_fix_tcp(ctrack, dis->ip, dis->ip6, dis->tcp);
else else
if (tcp_orig_send(verdict,desync_fwmark,ifout,dp,ctrack_replay,dis,bFake)) if (tcp_orig_send(desync_fwmark,ifout,dp,ctrack_replay,dis,bFake))
verdict = ct_new_postnat_fix_tcp(ctrack, dis->ip, dis->ip6, dis->tcp); verdict = ct_new_postnat_fix_tcp(ctrack, dis->ip, dis->ip6, dis->tcp);
return verdict; return verdict;
} }
@ -2224,7 +2216,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100]; uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
size_t pkt1_len, pkt2_len; size_t pkt1_len, pkt2_len;
uint8_t ttl_orig,ttl_fake; uint8_t ttl_orig,ttl_fake;
bool DF;
t_l7proto l7proto = UNKNOWN; t_l7proto l7proto = UNKNOWN;
extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst); extract_endpoints(dis->ip, dis->ip6, NULL, dis->udp, &src, &dst);
@ -2309,7 +2300,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint32_t desync_fwmark = fwmark | params.desync_fwmark; uint32_t desync_fwmark = fwmark | params.desync_fwmark;
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
DF = ip_has_df(dis->ip);
if (dis->len_payload) if (dis->len_payload)
{ {
@ -2560,8 +2550,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (!replay) if (!replay)
{ {
maybe_cutoff(ctrack, IPPROTO_UDP); maybe_cutoff(ctrack, IPPROTO_UDP);
if (orig_mod(dp,ctrack,dis)) // ttl can change !
verdict = VERDICT_MODIFY;
if (!process_desync_interval(dp, ctrack)) goto send_orig; if (!process_desync_interval(dp, ctrack)) goto send_orig;
} }
} }
@ -2651,7 +2639,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
n++; n++;
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
DF,ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6), ttl_fake, IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode, NULL, 0, 0, dp->desync_fooling_mode, NULL, 0, 0,
fake_item->data, fake_item->size, pkt1, &pkt1_len)) fake_item->data, fake_item->size, pkt1, &pkt1_len))
{ {
@ -2674,7 +2662,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
{ {
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
DF,ttl_orig,0,0,IP6_FLOW(dis->ip6),fooling_orig,NULL,0,0, ttl_orig,0,0,IP6_FLOW(dis->ip6),fooling_orig,NULL,0,0,
dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
{ {
goto send_orig; goto send_orig;
@ -2696,7 +2684,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
{ {
case DESYNC_UDPLEN: case DESYNC_UDPLEN:
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len)) if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
{ {
DLOG("could not construct packet with modified length. too large ?\n"); DLOG("could not construct packet with modified length. too large ?\n");
break; break;
@ -2721,7 +2709,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
memcpy(pkt2+pkt2_len,dis->data_payload+1,szcopy); memcpy(pkt2+pkt2_len,dis->data_payload+1,szcopy);
pkt2_len+=szcopy; pkt2_len+=szcopy;
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len)) if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
{ {
DLOG("could not construct packet with modified length. too large ?\n"); DLOG("could not construct packet with modified length. too large ?\n");
break; break;
@ -2782,13 +2770,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
default: default:
break; break;
} }
if (bFake)
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
} }
send_orig: send_orig:
if ((verdict & VERDICT_MASK)==VERDICT_DROP) if ((verdict & VERDICT_MASK)==VERDICT_DROP)
verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt); verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt);
else else
if (udp_orig_send(verdict,desync_fwmark,ifout,dp,ctrack_replay,dis,bFake)) if (udp_orig_send(desync_fwmark,ifout,dp,ctrack_replay,dis,bFake))
verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt); verdict = ct_new_postnat_fix_udp(ctrack, dis->ip, dis->ip6, dis->udp, &dis->len_pkt);
return verdict; return verdict;
} }

View File

@ -692,18 +692,11 @@ static void load_file_or_exit(const char *filename, void *buf, size_t *size)
static bool parse_autottl(const char *s, autottl *t) static bool parse_autottl(const char *s, autottl *t)
{ {
bool neg=true;
unsigned int delta,min,max; unsigned int delta,min,max;
AUTOTTL_SET_DEFAULT(*t); AUTOTTL_SET_DEFAULT(*t);
if (s) if (s)
{ {
max = t->max; max = t->max;
if (*s=='+')
{
neg=false;
s++;
} else if (*s=='-')
s++;
switch (sscanf(s,"%u:%u-%u",&delta,&min,&max)) switch (sscanf(s,"%u:%u-%u",&delta,&min,&max))
{ {
case 3: case 3:
@ -713,8 +706,8 @@ static bool parse_autottl(const char *s, autottl *t)
if ((delta && !min) || min>255 || min>max) return false; if ((delta && !min) || min>255 || min>max) return false;
t->min=(uint8_t)min; t->min=(uint8_t)min;
case 1: case 1:
if (delta>127) return false; if (delta>255) return false;
t->delta=(int8_t)(neg ? -delta : delta); t->delta=(uint8_t)delta;
break; break;
default: default:
return false; return false;
@ -1350,7 +1343,8 @@ static bool wf_make_filter(
char pf_dst_buf[512],iface[64]; char pf_dst_buf[512],iface[64];
const char *pf_dst; const char *pf_dst;
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(&params.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : ""; const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(&params.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(&params.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : ""; const char *f_tcp_not_empty = *pf_tcp_src ? DIVERT_TCP_NOT_EMPTY " and " : "";
snprintf(iface,sizeof(iface)," ifIdx=%u and subIfIdx=%u and",IfIdx,SubIfIdx); snprintf(iface,sizeof(iface)," ifIdx=%u and subIfIdx=%u and",IfIdx,SubIfIdx);
if (!*pf_tcp_src && !*pf_udp_src) return false; if (!*pf_tcp_src && !*pf_udp_src) return false;
@ -1459,14 +1453,14 @@ static void exithelp(void)
" --orig-mod-start=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n" " --orig-mod-start=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
" --orig-mod-cutoff=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n" " --orig-mod-cutoff=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
" --dup=<int>\t\t\t\t\t; duplicate original packets. send N dups before original.\n" " --dup=<int>\t\t\t\t\t; duplicate original packets. send N dups before original.\n"
" --dup-replace=[0|1]\t\t\t\t; 1 or no argument means do not send original, only dups\n"
" --dup-ttl=<int>\t\t\t\t; set TTL for dups\n" " --dup-ttl=<int>\t\t\t\t; set TTL for dups\n"
" --dup-replace=[0|1]\t\t\t\t; 1 or no argument means do not send original, only dups\n"
" --dup-ttl6=<int>\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n" " --dup-ttl6=<int>\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n"
" --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n" " --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
" --dup-badack-increment=<int|0xHEX>\t\t; badseq fooling ackseq signed increment for dup. default %d\n"
" --dup-start=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n" " --dup-start=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
" --dup-cutoff=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n" " --dup-cutoff=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
" --dup-desync-badack-increment=<int|0xHEX>\t; badseq fooling ackseq signed increment for dup. default %d\n"
" --hostcase\t\t\t\t\t; change Host: => host:\n" " --hostcase\t\t\t\t\t; change Host: => host:\n"
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" " --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
@ -1482,7 +1476,7 @@ static void exithelp(void)
#endif #endif
" --dpi-desync-ttl=<int>\t\t\t\t; set ttl for fakes packets\n" " --dpi-desync-ttl=<int>\t\t\t\t; set ttl for fakes packets\n"
" --dpi-desync-ttl6=<int>\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n" " --dpi-desync-ttl6=<int>\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n"
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n" " --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %u:%u-%u\n"
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n" " --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n"
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n" " --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2\n"
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n" " --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
@ -2763,73 +2757,7 @@ int main(int argc, char **argv)
DLOG_ERR("Need divert port (--port)\n"); DLOG_ERR("Need divert port (--port)\n");
exit_clean(1); exit_clean(1);
} }
#endif #elif defined(__CYGWIN__)
DLOG("adding low-priority default empty desync profile\n");
// add default empty profile
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n",desync_profile_count);
#ifndef __CYGWIN__
if (params.debug_target == LOG_TARGET_FILE && params.droproot && chown(params.debug_logfile, params.uid, -1))
fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile);
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
#endif
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
dp = &dpl->dp;
// not specified - use desync_ttl value instead
if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6=dp->desync_ttl;
if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6=dp->dup_ttl;
if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6=dp->orig_mod_ttl;
if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
if (AUTOTTL_ENABLED(dp->desync_autottl))
DLOG("profile %d autottl ipv4 %d:%u-%u\n",dp->n,dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max);
if (AUTOTTL_ENABLED(dp->desync_autottl6))
DLOG("profile %d autottl ipv6 %d:%u-%u\n",dp->n,dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max);
split_compat(dp);
if (!dp_fake_defaults(dp))
{
DLOG_ERR("could not fill fake defaults\n");
exit_clean(1);
}
if (!onetime_tls_mod(dp))
{
DLOG_ERR("could not mod tls\n");
exit_clean(1);
}
#ifndef __CYGWIN__
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
#endif
}
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed\n");
exit_clean(1);
}
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed\n");
exit_clean(1);
}
DLOG("\nlists summary:\n");
HostlistsDebug();
IpsetsDebug();
DLOG("\nsplits summary:\n");
SplitDebug();
DLOG("\n");
#ifdef __CYGWIN__
if (!*windivert_filter) if (!*windivert_filter)
{ {
if (!*wf_pf_tcp_src && !*wf_pf_udp_src) if (!*wf_pf_tcp_src && !*wf_pf_udp_src)
@ -2869,9 +2797,74 @@ int main(int argc, char **argv)
DLOG_ERR("A copy of winws is already running with the same filter\n"); DLOG_ERR("A copy of winws is already running with the same filter\n");
goto exiterr; goto exiterr;
} }
} }
#endif #endif
DLOG("adding low-priority default empty desync profile\n");
// add default empty profile
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n",desync_profile_count);
#ifndef __CYGWIN__
if (params.debug_target == LOG_TARGET_FILE && params.droproot && chown(params.debug_logfile, params.uid, -1))
fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile);
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
#endif
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
dp = &dpl->dp;
// not specified - use desync_ttl value instead
if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6=dp->desync_ttl;
if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6=dp->dup_ttl;
if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6=dp->orig_mod_ttl;
if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
if (AUTOTTL_ENABLED(dp->desync_autottl))
DLOG("profile %d autottl ipv4 %u:%u-%u\n",dp->n,dp->desync_autottl.delta,dp->desync_autottl.min,dp->desync_autottl.max);
if (AUTOTTL_ENABLED(dp->desync_autottl6))
DLOG("profile %d autottl ipv6 %u:%u-%u\n",dp->n,dp->desync_autottl6.delta,dp->desync_autottl6.min,dp->desync_autottl6.max);
split_compat(dp);
if (!dp_fake_defaults(dp))
{
DLOG_ERR("could not fill fake defaults\n");
exit_clean(1);
}
if (!onetime_tls_mod(dp))
{
DLOG_ERR("could not mod tls\n");
exit_clean(1);
}
#ifndef __CYGWIN__
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
#endif
}
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed\n");
exit_clean(1);
}
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed\n");
exit_clean(1);
}
DLOG("\nlists summary:\n");
HostlistsDebug();
IpsetsDebug();
DLOG("\nsplits summary:\n");
SplitDebug();
DLOG("\n");
if (bDry) if (bDry)
{ {
DLOG_CONDUP("command line parameters verified\n"); DLOG_CONDUP("command line parameters verified\n");

View File

@ -294,12 +294,3 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
return true; return true;
return false; return false;
} }
// check if we need empty outgoing ACK
bool dp_list_need_all_out(struct desync_profile_list_head *head)
{
struct desync_profile_list *dpl;
LIST_FOREACH(dpl, head, next)
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
return true;
return false;
}

View File

@ -126,10 +126,10 @@ struct desync_profile
hostfail_pool *hostlist_auto_fail_counters; hostfail_pool *hostlist_auto_fail_counters;
}; };
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude)) #define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6) #define PROFILE_HAS_ORIG_MOD(dp) (dp->orig_mod_ttl || dp->orig_mod_ttl6)
struct desync_profile_list { struct desync_profile_list {
struct desync_profile dp; struct desync_profile dp;
@ -140,7 +140,6 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry); void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head); void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head); bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
bool dp_list_need_all_out(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp); void dp_init(struct desync_profile *dp);
bool dp_fake_defaults(struct desync_profile *dp); bool dp_fake_defaults(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp); void dp_clear(struct desync_profile *dp);