@ -277,7 +277,7 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, size_t sz, size_t
if ( ReasmInit ( reasm , sz , ctrack - > seq_last ) )
if ( ReasmInit ( reasm , sz , ctrack - > seq_last ) )
{
{
ReasmFeed ( reasm , ctrack - > seq_last , data_payload , len_payload ) ;
ReasmFeed ( reasm , ctrack - > seq_last , data_payload , len_payload ) ;
DLOG ( reasm - > size_present = = reasm - > size ? " starting reassemble. now we have %zu \n " : " starting reassemble. now we have %zu/%zu \n " , reasm - > size_present , reasm - > size ) ;
DLOG ( " starting reassemble. now we have %zu/%zu \n " , reasm - > size_present , reasm - > size ) ;
return true ;
return true ;
}
}
else
else
@ -295,9 +295,9 @@ static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, con
{
{
if ( ctrack & & ! ReasmIsEmpty ( reasm ) )
if ( ctrack & & ! ReasmIsEmpty ( reasm ) )
{
{
if ( ReasmFeed ( reasm , proto = = IPPROTO_TCP ? ctrack - > seq_last : - 1 , data_payload , len_payload ) )
if ( ReasmFeed ( reasm , proto = = IPPROTO_TCP ? ( size_t ) ctrack - > seq_last : reasm - > size_present , data_payload , len_payload ) )
{
{
DLOG ( reasm - > size_present = = reasm - > size ? " reassemble : feeding data payload size=%zu. now we have %zu \n " : " reassemble : feeding data payload size=%zu. now we have %zu/%zu \n " , len_payload , reasm - > size_present , reasm - > size )
DLOG ( " reassemble : feeding data payload size=%zu. now we have %zu/%zu \n " , len_payload , reasm - > size_present , reasm - > size )
return true ;
return true ;
}
}
else
else
@ -313,27 +313,26 @@ static bool reasm_orig_feed(t_ctrack *ctrack, uint8_t proto, const uint8_t *data
{
{
return reasm_feed ( ctrack , & ctrack - > reasm_orig , proto , data_payload , len_payload ) ;
return reasm_feed ( ctrack , & ctrack - > reasm_orig , proto , data_payload , len_payload ) ;
}
}
static void reasm_orig_fin ( t_ctrack * ctrack )
static void reasm_orig_stop ( t_ctrack * ctrack , const char * dlog_msg )
{
if ( ctrack & & ReasmIsFull ( & ctrack - > reasm_orig ) )
{
DLOG ( " reassemble session finished \n " ) ;
ReasmClear ( & ctrack - > reasm_orig ) ;
send_delayed ( ctrack ) ;
}
}
static void reasm_orig_cancel ( t_ctrack * ctrack )
{
{
if ( ctrack )
if ( ctrack )
{
{
if ( ! ReasmIsEmpty ( & ctrack - > reasm_orig ) )
if ( ! ReasmIsEmpty ( & ctrack - > reasm_orig ) )
{
{
DLOG ( " reassemble session cancelled \n " ) ;
DLOG ( " %s " , dlog_msg ) ;
ReasmClear ( & ctrack - > reasm_orig ) ;
ReasmClear ( & ctrack - > reasm_orig ) ;
}
}
send_delayed ( ctrack ) ;
send_delayed ( ctrack ) ;
}
}
}
}
static void reasm_orig_cancel ( t_ctrack * ctrack )
{
reasm_orig_stop ( ctrack , " reassemble session cancelled \n " ) ;
}
static void reasm_orig_fin ( t_ctrack * ctrack )
{
reasm_orig_stop ( ctrack , " reassemble session finished \n " ) ;
}
static uint8_t ct_new_postnat_fix ( const t_ctrack * ctrack , struct ip * ip , struct ip6_hdr * ip6 , uint8_t proto , struct udphdr * udp , struct tcphdr * tcp , size_t * len_pkt )
static uint8_t ct_new_postnat_fix ( const t_ctrack * ctrack , struct ip * ip , struct ip6_hdr * ip6 , uint8_t proto , struct udphdr * udp , struct tcphdr * tcp , size_t * len_pkt )
@ -655,6 +654,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
{
{
DLOG ( " packet contains HTTP request \n " )
DLOG ( " packet contains HTTP request \n " )
if ( ctrack & & ! ctrack - > l7proto ) ctrack - > l7proto = HTTP ;
if ( ctrack & & ! ctrack - > l7proto ) ctrack - > l7proto = HTTP ;
// we do not reassemble http
reasm_orig_cancel ( ctrack ) ;
forced_wssize_cutoff ( ctrack ) ;
forced_wssize_cutoff ( ctrack ) ;
fake = params . fake_http ;
fake = params . fake_http ;
fake_size = params . fake_http_size ;
fake_size = params . fake_http_size ;
@ -664,7 +667,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
if ( ! bHaveHost )
if ( ! bHaveHost )
{
{
DLOG ( " not applying tampering to HTTP without Host: \n " )
DLOG ( " not applying tampering to HTTP without Host: \n " )
reasm_orig_fin ( ctrack ) ;
return verdict ;
return verdict ;
}
}
}
}
@ -698,7 +700,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
// do not reconstruct unexpected large payload (they are feeding garbage ?)
// do not reconstruct unexpected large payload (they are feeding garbage ?)
if ( ! reasm_orig_start ( ctrack , TLSRecordLen ( data_payload ) , 16384 , data_payload , len_payload ) )
if ( ! reasm_orig_start ( ctrack , TLSRecordLen ( data_payload ) , 16384 , data_payload , len_payload ) )
{
{
fprintf ( stderr , " reasm start failed ! out of memory. \n " ) ;
reasm_orig_cancel ( ctrack ) ;
reasm_orig_cancel ( ctrack ) ;
return verdict ;
return verdict ;
}
}
@ -746,7 +747,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
if ( params . desync_skip_nosni & & ! bHaveHost )
if ( params . desync_skip_nosni & & ! bHaveHost )
{
{
DLOG ( " not applying tampering to TLS ClientHello without hostname in the SNI \n " )
DLOG ( " not applying tampering to TLS ClientHello without hostname in the SNI \n " )
reasm_orig_fin ( ctrack ) ;
reasm_orig_cancel ( ctrack ) ;
return verdict ;
return verdict ;
}
}
@ -755,7 +756,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
bKnownProtocol = true ;
bKnownProtocol = true ;
}
}
reasm_orig_fin ( ctrack ) ;
reasm_orig_cancel ( ctrack ) ;
rdata_payload = NULL ;
rdata_payload = NULL ;
if ( bHaveHost )
if ( bHaveHost )
@ -1065,6 +1066,21 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
return verdict ;
return verdict ;
}
}
// return : true - should continue, false - should stop with verdict
static bool quic_reasm_cancel ( t_ctrack * ctrack , const char * reason )
{
reasm_orig_cancel ( ctrack ) ;
if ( params . desync_any_proto )
{
DLOG ( " %s. applying tampering because desync_any_proto is set \n " , reason )
return true ;
}
else
{
DLOG ( " %s. not applying tampering because desync_any_proto is not set \n " , reason )
return false ;
}
}
static uint8_t dpi_desync_udp_packet_play ( bool replay , uint32_t fwmark , const char * ifout , uint8_t * data_pkt , size_t * len_pkt , struct ip * ip , struct ip6_hdr * ip6hdr , struct udphdr * udphdr , size_t transport_len , uint8_t * data_payload , size_t len_payload )
static uint8_t dpi_desync_udp_packet_play ( bool replay , uint32_t fwmark , const char * ifout , uint8_t * data_pkt , size_t * len_pkt , struct ip * ip , struct ip6_hdr * ip6hdr , struct udphdr * udphdr , size_t transport_len , uint8_t * data_payload , size_t len_payload )
{
{
@ -1127,7 +1143,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
if ( ctrack & & ! ctrack - > l7proto ) ctrack - > l7proto = QUIC ;
if ( ctrack & & ! ctrack - > l7proto ) ctrack - > l7proto = QUIC ;
uint8_t clean [ 9000 ] , * pclean ;
uint8_t clean [ 16384 ] , * pclean ;
size_t clean_len ;
size_t clean_len ;
bool bIsHello = false ;
bool bIsHello = false ;
@ -1145,14 +1161,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
{
{
if ( ctrack & & ! ReasmIsEmpty ( & ctrack - > reasm_orig ) )
if ( ctrack & & ! ReasmIsEmpty ( & ctrack - > reasm_orig ) )
{
{
size_t newlen = ctrack - > reasm_orig . size_present + clean_len ;
if ( ReasmHasSpace ( & ctrack - > reasm_orig , clean_len ) )
if ( newlen > 16384 )
{
DLOG ( " QUIC reasm is too long. cancelling. \n " ) ;
reasm_orig_cancel ( ctrack ) ;
return verdict ; // cannot be first packet
}
if ( ReasmResize ( & ctrack - > reasm_orig , newlen ) )
{
{
reasm_orig_feed ( ctrack , IPPROTO_UDP , clean , clean_len ) ;
reasm_orig_feed ( ctrack , IPPROTO_UDP , clean , clean_len ) ;
pclean = ctrack - > reasm_orig . packet ;
pclean = ctrack - > reasm_orig . packet ;
@ -1160,7 +1169,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
}
}
else
else
{
{
fprintf ( stderr , " reasm update failed ! out of memory .\n " ) ;
DLOG ( " QUIC reasm is too long. cancelling .\n " ) ;
reasm_orig_cancel ( ctrack ) ;
reasm_orig_cancel ( ctrack ) ;
return verdict ; // cannot be first packet
return verdict ; // cannot be first packet
}
}
@ -1179,9 +1188,9 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
{
{
if ( bIsHello & & ! bReqFull & & ReasmIsEmpty ( & ctrack - > reasm_orig ) )
if ( bIsHello & & ! bReqFull & & ReasmIsEmpty ( & ctrack - > reasm_orig ) )
{
{
if ( ! reasm_orig_start ( ctrack , clean_len , clean_len , clean , clean_len ) )
// preallocate max buffer to avoid reallocs that cause memory copy
if ( ! reasm_orig_start ( ctrack , 16384 , 16384 , clean , clean_len ) )
{
{
fprintf ( stderr , " reasm start failed ! out of memory. \n " ) ;
reasm_orig_cancel ( ctrack ) ;
reasm_orig_cancel ( ctrack ) ;
return verdict ;
return verdict ;
}
}
@ -1220,40 +1229,19 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
}
}
else
else
{
{
reasm_orig_cancel ( ctrack ) ;
if ( ! quic_reasm_cancel ( ctrack , " QUIC initial without ClientHello " ) ) return verdict ;
if ( params . desync_any_proto )
DLOG ( " QUIC initial without ClientHello. applying tampering because desync_any_proto is set \n " )
else
{
DLOG ( " not applying tampering to QUIC initial without ClientHello \n " )
return verdict ;
}
}
}
}
}
else
else
{
{
// defrag failed
// defrag failed
reasm_orig_cancel ( ctrack ) ;
if ( ! quic_reasm_cancel ( ctrack , " QUIC initial defrag CRYPTO failed " ) ) return verdict ;
if ( params . desync_any_proto )
DLOG ( " QUIC initial without CRYPTO frame. applying tampering because desync_any_proto is set \n " )
else
{
DLOG ( " not applying tampering to QUIC initial without CRYPTO frame \n " )
return verdict ;
}
}
}
}
}
else
else
{
{
// decrypt failed
// decrypt failed
reasm_orig_cancel ( ctrack ) ;
if ( ! quic_reasm_cancel ( ctrack , " QUIC initial decryption failed " ) ) return verdict ;
if ( params . desync_any_proto )
DLOG ( " QUIC initial decryption failed. applying tampering because desync_any_proto is set \n " )
else
{
DLOG ( " not applying tampering to QUIC initial that could not be decrypted \n " )
return verdict ;
}
}
}
fake = params . fake_quic ;
fake = params . fake_quic ;
@ -1301,8 +1289,11 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, uint32_t fwmark, const ch
DLOG ( " not applying tampering to this request \n " )
DLOG ( " not applying tampering to this request \n " )
if ( ! bExcluded & & * params . hostlist_auto_filename & & ctrack )
if ( ! bExcluded & & * params . hostlist_auto_filename & & ctrack )
{
{
if ( ! ctrack - > hostname ) ctrack - > hostname = strdup ( host ) ;
if ( ! ctrack - > hostname )
process_retrans_fail ( ctrack , IPPROTO_UDP ) ;
// first request is not retrans
ctrack - > hostname = strdup ( host ) ;
else
process_retrans_fail ( ctrack , IPPROTO_UDP ) ;
}
}
return verdict ;
return verdict ;
}
}