mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-29 21:40:52 +03:00
nfqws: fix reasm seq handling
This commit is contained in:
parent
452d9210a6
commit
7d789f79d0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -142,13 +142,13 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
if (tcp_syn_segment(tcphdr))
|
if (tcp_syn_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||||
t->seq0 = htonl(tcphdr->th_seq);
|
t->seq0 = ntohl(tcphdr->th_seq);
|
||||||
}
|
}
|
||||||
else if (tcp_synack_segment(tcphdr))
|
else if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||||
if (!t->seq0) t->seq0 = htonl(tcphdr->th_ack)-1;
|
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
|
||||||
t->ack0 = htonl(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))
|
||||||
{
|
{
|
||||||
@ -159,25 +159,25 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
if (t->state==SYN)
|
if (t->state==SYN)
|
||||||
{
|
{
|
||||||
t->state=ESTABLISHED;
|
t->state=ESTABLISHED;
|
||||||
if (!bReverse && !t->ack0) t->ack0 = htonl(tcphdr->th_ack)-1;
|
if (!bReverse && !t->ack0) t->ack0 = ntohl(tcphdr->th_ack)-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scale = tcp_find_scale_factor(tcphdr);
|
scale = tcp_find_scale_factor(tcphdr);
|
||||||
if (bReverse)
|
if (bReverse)
|
||||||
{
|
{
|
||||||
t->pos_orig = t->seq_last = htonl(tcphdr->th_ack);
|
t->pos_orig = t->seq_last = ntohl(tcphdr->th_ack);
|
||||||
t->ack_last = htonl(tcphdr->th_seq);
|
t->ack_last = ntohl(tcphdr->th_seq);
|
||||||
t->pos_reply = t->ack_last + len_payload;
|
t->pos_reply = t->ack_last + len_payload;
|
||||||
t->winsize_reply = htons(tcphdr->th_win);
|
t->winsize_reply = ntohs(tcphdr->th_win);
|
||||||
if (scale!=SCALE_NONE) t->scale_reply = scale;
|
if (scale!=SCALE_NONE) t->scale_reply = scale;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t->seq_last = htonl(tcphdr->th_seq);
|
t->seq_last = ntohl(tcphdr->th_seq);
|
||||||
t->pos_orig = t->seq_last + len_payload;
|
t->pos_orig = t->seq_last + len_payload;
|
||||||
t->pos_reply = t->ack_last = htonl(tcphdr->th_ack);
|
t->pos_reply = t->ack_last = ntohl(tcphdr->th_ack);
|
||||||
t->winsize_orig = htons(tcphdr->th_win);
|
t->winsize_orig = ntohs(tcphdr->th_win);
|
||||||
if (scale!=SCALE_NONE) t->scale_orig = scale;
|
if (scale!=SCALE_NONE) t->scale_orig = scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ bool ReasmResize(t_reassemble *reasm, size_t new_size)
|
|||||||
if (reasm->size_present > new_size) reasm->size_present = new_size;
|
if (reasm->size_present > new_size) reasm->size_present = new_size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ReasmFeed(t_reassemble *reasm, size_t seq, const void *payload, size_t len)
|
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
|
||||||
{
|
{
|
||||||
if (reasm->seq!=seq) return false; // fail session if out of sequence
|
if (reasm->seq!=seq) return false; // fail session if out of sequence
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ typedef struct
|
|||||||
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
|
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
|
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
|
||||||
size_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
|
uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
|
||||||
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
|
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
|
||||||
size_t size_present; // how many bytes already stored in 'packet'
|
size_t size_present; // how many bytes already stored in 'packet'
|
||||||
} t_reassemble;
|
} t_reassemble;
|
||||||
@ -109,7 +109,7 @@ bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start);
|
|||||||
bool ReasmResize(t_reassemble *reasm, size_t new_size);
|
bool ReasmResize(t_reassemble *reasm, size_t new_size);
|
||||||
void ReasmClear(t_reassemble *reasm);
|
void ReasmClear(t_reassemble *reasm);
|
||||||
// false means reassemble session has failed and we should ReasmClear() it
|
// false means reassemble session has failed and we should ReasmClear() it
|
||||||
bool ReasmFeed(t_reassemble *reasm, size_t seq, const void *payload, size_t len);
|
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len);
|
||||||
// check if it has enough space to buffer 'len' bytes
|
// check if it has enough space to buffer 'len' bytes
|
||||||
bool ReasmHasSpace(t_reassemble *reasm, size_t len);
|
bool ReasmHasSpace(t_reassemble *reasm, size_t len);
|
||||||
inline static bool ReasmIsEmpty(t_reassemble *reasm) {return !reasm->size;}
|
inline static bool ReasmIsEmpty(t_reassemble *reasm) {return !reasm->size;}
|
||||||
|
18
nfq/desync.c
18
nfq/desync.c
@ -269,14 +269,15 @@ static bool send_delayed(t_ctrack *ctrack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||||
{
|
{
|
||||||
ReasmClear(reasm);
|
ReasmClear(reasm);
|
||||||
if (sz<=szMax)
|
if (sz<=szMax)
|
||||||
{
|
{
|
||||||
if (ReasmInit(reasm,sz,ctrack->seq_last))
|
uint32_t seq = (proto==IPPROTO_TCP) ? ctrack->seq_last : 0;
|
||||||
|
if (ReasmInit(reasm,sz,seq))
|
||||||
{
|
{
|
||||||
ReasmFeed(reasm,ctrack->seq_last,data_payload,len_payload);
|
ReasmFeed(reasm,seq,data_payload,len_payload);
|
||||||
DLOG("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;
|
||||||
}
|
}
|
||||||
@ -287,15 +288,16 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, size_t sz, size_t
|
|||||||
DLOG("unexpected large payload for reassemble: size=%zu\n",sz);
|
DLOG("unexpected large payload for reassemble: size=%zu\n",sz);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool reasm_orig_start(t_ctrack *ctrack, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
static bool reasm_orig_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||||
{
|
{
|
||||||
return reasm_start(ctrack,&ctrack->reasm_orig,sz,szMax,data_payload,len_payload);
|
return reasm_start(ctrack,&ctrack->reasm_orig,proto,sz,szMax,data_payload,len_payload);
|
||||||
}
|
}
|
||||||
static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, const uint8_t *data_payload, size_t len_payload)
|
static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, const uint8_t *data_payload, size_t len_payload)
|
||||||
{
|
{
|
||||||
if (ctrack && !ReasmIsEmpty(reasm))
|
if (ctrack && !ReasmIsEmpty(reasm))
|
||||||
{
|
{
|
||||||
if (ReasmFeed(reasm,proto==IPPROTO_TCP ? (size_t)ctrack->seq_last : reasm->size_present, data_payload, len_payload))
|
uint32_t seq = (proto==IPPROTO_TCP) ? ctrack->seq_last : (uint32_t)reasm->size_present;
|
||||||
|
if (ReasmFeed(reasm, seq, data_payload, len_payload))
|
||||||
{
|
{
|
||||||
DLOG("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;
|
||||||
@ -698,7 +700,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, uint32_t fwmark, const ch
|
|||||||
!(ctrack->req_seq_finalized && seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end)))
|
!(ctrack->req_seq_finalized && seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end)))
|
||||||
{
|
{
|
||||||
// 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,IPPROTO_TCP,TLSRecordLen(data_payload),16384,data_payload,len_payload))
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
return verdict;
|
return verdict;
|
||||||
@ -1189,7 +1191,7 @@ 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))
|
||||||
{
|
{
|
||||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
// preallocate max buffer to avoid reallocs that cause memory copy
|
||||||
if (!reasm_orig_start(ctrack,16384,16384,clean,clean_len))
|
if (!reasm_orig_start(ctrack,IPPROTO_UDP,16384,16384,clean,clean_len))
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
return verdict;
|
return verdict;
|
||||||
|
@ -131,7 +131,7 @@ size_t TLSHandshakeLen(const uint8_t *data)
|
|||||||
}
|
}
|
||||||
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len)
|
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
return len>=4 && data[0]==0x01;
|
return len>=4 && data[0]==0x01 && TLSHandshakeLen(data)>0;
|
||||||
}
|
}
|
||||||
bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
|
bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user