TCP: Zero Window Probe ACK detection for improper clients
This commit is contained in:
parent
acbc327faf
commit
d00468742f
2 changed files with 57 additions and 27 deletions
|
@ -643,7 +643,8 @@ Set when the all of the following are true:
|
||||||
* The segment size is zero.
|
* The segment size is zero.
|
||||||
* The window size is non-zero and not equal to the last-seen window size.
|
* The window size is non-zero and not equal to the last-seen window size.
|
||||||
* The sequence number is equal to the next expected sequence number.
|
* The sequence number is equal to the next expected sequence number.
|
||||||
* The acknowledgment number is equal to the last-seen acknowledgment number.
|
* The acknowledgment number is equal to the last-seen acknowledgment number,
|
||||||
|
* or to the next expected sequence number when answering to a ZeroWindowProbe.
|
||||||
* None of SYN, FIN, or RST are set.
|
* None of SYN, FIN, or RST are set.
|
||||||
|
|
||||||
// TCP_A_ZERO_WINDOW
|
// TCP_A_ZERO_WINDOW
|
||||||
|
|
|
@ -2274,13 +2274,23 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
|
||||||
&& window==0
|
&& window==0
|
||||||
&& window==tcpd->fwd->window
|
&& window==tcpd->fwd->window
|
||||||
&& seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
|
&& seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
|
||||||
&& ack==tcpd->fwd->tcp_analyze_seq_info->lastack
|
&& (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1))
|
||||||
&& (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
|
&& (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
|
||||||
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
|
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
|
||||||
if(!tcpd->ta) {
|
if(!tcpd->ta) {
|
||||||
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
|
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
|
||||||
}
|
}
|
||||||
tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
|
tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
|
||||||
|
|
||||||
|
/* Some receivers consume that extra byte brought in the PROBE,
|
||||||
|
* but it was too early to know that during the WINDOW PROBE analysis.
|
||||||
|
* Do it now by moving the rev nextseq & maxseqtobeacked.
|
||||||
|
* See issue 10745.
|
||||||
|
*/
|
||||||
|
if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)) {
|
||||||
|
tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
|
||||||
|
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
|
||||||
|
}
|
||||||
goto finished_fwd;
|
goto finished_fwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2324,7 +2334,10 @@ finished_fwd:
|
||||||
/* ACKED LOST PACKET
|
/* ACKED LOST PACKET
|
||||||
* If this segment acks beyond the 'max seq to be acked' in the other direction
|
* If this segment acks beyond the 'max seq to be acked' in the other direction
|
||||||
* then that means we have missed packets going in the
|
* then that means we have missed packets going in the
|
||||||
* other direction
|
* other direction.
|
||||||
|
* It might also indicate we are resuming from a Zero Window,
|
||||||
|
* where a Probe is just followed by an ACK opening again the window.
|
||||||
|
* See issue 8404.
|
||||||
*
|
*
|
||||||
* We only check this if we have actually seen some seq numbers
|
* We only check this if we have actually seen some seq numbers
|
||||||
* in the other direction.
|
* in the other direction.
|
||||||
|
@ -2336,33 +2349,46 @@ finished_fwd:
|
||||||
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
|
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We ensure there is no matching packet waiting in the unacked list,
|
/* resuming from a Zero Window Probe which re-opens the window,
|
||||||
* and take this opportunity to push the tail further than this single packet
|
* mark it as a Window Update
|
||||||
*/
|
*/
|
||||||
gboolean is_seq_in_unacked = FALSE;
|
if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)
|
||||||
guint32 maxseqtail = ack;
|
&& (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq)
|
||||||
ual = tcpd->rev->tcp_analyze_seq_info->segments;
|
&& (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE) ) {
|
||||||
while(ual) {
|
tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
|
||||||
/* prevent false positives */
|
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
|
||||||
if(GT_SEQ(ack,ual->seq) && LE_SEQ(ack,ual->nextseq)) {
|
tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
|
||||||
is_seq_in_unacked = TRUE;
|
|
||||||
}
|
|
||||||
/* look for a possible tail pushing the maxseqtobeacked further */
|
|
||||||
if(maxseqtail==ual->seq) {
|
|
||||||
maxseqtail = ual->nextseq;
|
|
||||||
}
|
|
||||||
ual=ual->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update 'max seq to be acked' in the other direction so we don't get
|
|
||||||
* this indication again.
|
|
||||||
*/
|
|
||||||
if(is_seq_in_unacked) {
|
|
||||||
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=(GT_SEQ(maxseqtail, ack)) ? ack : maxseqtail;
|
|
||||||
}
|
}
|
||||||
|
/* real ACKED LOST PACKET */
|
||||||
else {
|
else {
|
||||||
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=maxseqtail;
|
/* We ensure there is no matching packet waiting in the unacked list,
|
||||||
tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
|
* and take this opportunity to push the tail further than this single packet
|
||||||
|
*/
|
||||||
|
gboolean is_seq_in_unacked = FALSE;
|
||||||
|
guint32 maxseqtail = ack;
|
||||||
|
ual = tcpd->rev->tcp_analyze_seq_info->segments;
|
||||||
|
while(ual) {
|
||||||
|
/* prevent false positives */
|
||||||
|
if(GT_SEQ(ack,ual->seq) && LE_SEQ(ack,ual->nextseq)) {
|
||||||
|
is_seq_in_unacked = TRUE;
|
||||||
|
}
|
||||||
|
/* look for a possible tail pushing the maxseqtobeacked further */
|
||||||
|
if(maxseqtail==ual->seq) {
|
||||||
|
maxseqtail = ual->nextseq;
|
||||||
|
}
|
||||||
|
ual=ual->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update 'max seq to be acked' in the other direction so we don't get
|
||||||
|
* this indication again.
|
||||||
|
*/
|
||||||
|
if(is_seq_in_unacked) {
|
||||||
|
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=(GT_SEQ(maxseqtail, ack)) ? ack : maxseqtail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=maxseqtail;
|
||||||
|
tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2626,6 +2652,9 @@ finished_checking_retransmission_type:
|
||||||
* If this ever happens, this boundary value can "jump" further in order to
|
* If this ever happens, this boundary value can "jump" further in order to
|
||||||
* avoid duplicating multiple messages for the very same lost packet. See later
|
* avoid duplicating multiple messages for the very same lost packet. See later
|
||||||
* how ACKED LOST PACKET are handled.
|
* how ACKED LOST PACKET are handled.
|
||||||
|
* Zero Window Probes are logically left out at this moment, but if their data
|
||||||
|
* really were to be ack'ed, then it will be done later when analyzing their
|
||||||
|
* Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).
|
||||||
*/
|
*/
|
||||||
if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {
|
if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {
|
||||||
if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
|
if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
|
||||||
|
|
Loading…
Reference in a new issue