stream: accept and flag ack of ZWP data

Tcp Zero Window Probes try to send a single byte payload to "probe" if
the window has reopened. This single byte is, if accepted, not retransmitted.
pull/8638/head
Victor Julien 3 years ago
parent 64fb4066cf
commit 30a716a4ab

@ -42,6 +42,10 @@ alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED SYN resend"; stre
alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED SYN resend with different seq"; stream-event:est_syn_resend_diff_seq; classtype:protocol-command-decode; sid:2210027; rev:2;)
alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED SYN to client"; stream-event:est_syn_toclient; classtype:protocol-command-decode; sid:2210028; rev:2;)
alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED invalid ack"; stream-event:est_invalid_ack; classtype:protocol-command-decode; sid:2210029; rev:2;)
# ACK received for Zero Window Probe segment.
#alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED ack for ZWP data"; stream-event:est_invalid_ack; classtype:protocol-command-decode; sid:2210065; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM FIN invalid ack"; stream-event:fin_invalid_ack; classtype:protocol-command-decode; sid:2210030; rev:2;)
alert tcp any any -> any any (msg:"SURICATA STREAM FIN1 ack with wrong seq"; stream-event:fin1_ack_wrong_seq; classtype:protocol-command-decode; sid:2210031; rev:2;)
alert tcp any any -> any any (msg:"SURICATA STREAM FIN1 FIN with wrong seq"; stream-event:fin1_fin_wrong_seq; classtype:protocol-command-decode; sid:2210032; rev:2;)
@ -105,5 +109,5 @@ alert tcp any any -> any any (msg:"SURICATA STREAM FIN SYN reuse"; stream-event:
# Depth setting reached for a stream. Very common in normal traffic, so disable by default.
#alert tcp any any -> any any (msg:"SURICATA STREAM reassembly depth reached"; stream-event:reassembly_depth_reached; classtype:protocol-command-decode; sid:2210062; rev:1;)
# next sid 2210065
# next sid 2210066

@ -730,6 +730,10 @@ const struct DecodeEvents_ DEvents[] = {
"stream.est_invalid_ack",
STREAM_EST_INVALID_ACK,
},
{
"stream.est_ack_zwp_data",
STREAM_EST_ACK_ZWP_DATA,
},
{
"stream.fin_invalid_ack",
STREAM_FIN_INVALID_ACK,

@ -259,6 +259,7 @@ enum {
STREAM_EST_SYN_RESEND_DIFF_SEQ,
STREAM_EST_SYN_TOCLIENT,
STREAM_EST_INVALID_ACK,
STREAM_EST_ACK_ZWP_DATA,
STREAM_FIN_INVALID_ACK,
STREAM_FIN1_ACK_WRONG_SEQ,
STREAM_FIN1_FIN_WRONG_SEQ,

@ -204,6 +204,9 @@ enum TcpState {
#define STREAMTCP_FLAG_TCP_FAST_OPEN BIT_U32(15)
/** SYN/ACK ignored the data while ACKing the SYN */
#define STREAMTCP_FLAG_TFO_DATA_IGNORED BIT_U32(16)
/* zero window probe */
#define STREAMTCP_FLAG_ZWP_TS BIT_U32(17)
#define STREAMTCP_FLAG_ZWP_TC BIT_U32(18)
/*
* Per STREAM flags

@ -2527,11 +2527,18 @@ static int HandleEstablishedPacketToServer(
"ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p), TCP_GET_WINDOW(p));
if (StreamTcpValidateAck(ssn, &(ssn->server), p) == -1) {
const bool has_ack = (p->tcph->th_flags & TH_ACK) != 0;
if (has_ack) {
if ((ssn->flags & STREAMTCP_FLAG_ZWP_TC) && TCP_GET_ACK(p) == ssn->server.next_seq + 1) {
SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
StreamTcpSetEvent(p, STREAM_EST_ACK_ZWP_DATA);
} else if (StreamTcpValidateAck(ssn, &ssn->server, p) == -1) {
SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
return -1;
}
}
/* check for Keep Alive */
if ((p->payload_len == 0 || p->payload_len == 1) &&
@ -2616,6 +2623,8 @@ static int HandleEstablishedPacketToServer(
SCLogDebug("ssn %p: zero window probe", ssn);
zerowindowprobe = 1;
STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE);
ssn->flags |= STREAMTCP_FLAG_ZWP_TS;
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p);
} else if (SEQ_GEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_seq)) {
StreamTcpUpdateNextSeq(ssn, &ssn->client, (TCP_GET_SEQ(p) + p->payload_len));
@ -2694,11 +2703,18 @@ static int HandleEstablishedPacketToClient(
" ACK %" PRIu32 ", WIN %"PRIu16"", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p), TCP_GET_WINDOW(p));
if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
const bool has_ack = (p->tcph->th_flags & TH_ACK) != 0;
if (has_ack) {
if ((ssn->flags & STREAMTCP_FLAG_ZWP_TS) && TCP_GET_ACK(p) == ssn->client.next_seq + 1) {
SCLogDebug("ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
StreamTcpSetEvent(p, STREAM_EST_ACK_ZWP_DATA);
} else if (StreamTcpValidateAck(ssn, &ssn->client, p) == -1) {
SCLogDebug("ssn %p: rejecting because of invalid ack value", ssn);
StreamTcpSetEvent(p, STREAM_EST_INVALID_ACK);
return -1;
}
}
/* To get the server window value from the servers packet, when connection
is picked up as midstream */
@ -2757,6 +2773,10 @@ static int HandleEstablishedPacketToClient(
SCLogDebug("ssn %p: zero window probe", ssn);
zerowindowprobe = 1;
STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE);
ssn->flags |= STREAMTCP_FLAG_ZWP_TC;
/* accept the segment */
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p);
} else if (SEQ_GEQ(TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_seq)) {
StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));

Loading…
Cancel
Save