stream: detect retransmissions on closewait and finwait2 states

pull/141/merge
Victor Julien 14 years ago
parent 305ed3f23b
commit bc37cb6b8e

@ -20,6 +20,7 @@ alert tcp any any -> any any (msg:"SURICATA STREAM 4way handshake invalid ack";
alert tcp any any -> any any (msg:"SURICATA STREAM CLOSEWAIT ACK out of window"; stream-event:closewait_ack_out_of_window; sid:2210015; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM CLOSEWAIT FIN out of window"; stream-event:closewait_fin_out_of_window; sid:2210016; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM CLOSEWAIT invalid ACK"; stream-event:closewait_invalid_ack; sid:2210017; rev:1;)
#alert tcp any any -> any any (msg:"SURICATA STREAM CLOSEWAIT retransmission packet before last ack"; stream-event:closewait_pkt_before_last_ack; sid:2210052; rev:2;)
alert tcp any any -> any any (msg:"SURICATA STREAM CLOSING ACK wrong seq"; stream-event:closing_ack_wrong_seq; sid:2210018; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM CLOSING invalid ACK"; stream-event:closing_invalid_ack; sid:2210019; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED packet out of window"; stream-event:est_packet_out_of_window; sid:2210020; rev:1;)
@ -60,5 +61,5 @@ alert tcp any any -> any any (msg:"SURICATA STREAM SHUTDOWN RST invalid ack"; st
# Sequence gap: missing data in the reassembly engine. Usually due to packet loss. Will be very noisy on a overloaded link / sensor.
#alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; sid:2210048; rev:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly overlap with different data"; stream-event:reassembly_overlap_different_data; sid:2210050; rev:1;)
# next sid 2210052
# next sid 2210053

@ -146,6 +146,7 @@ enum {
STREAM_4WHS_INVALID_ACK,
STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW,
STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW,
STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK,
STREAM_CLOSEWAIT_INVALID_ACK,
STREAM_CLOSING_ACK_WRONG_SEQ,
STREAM_CLOSING_INVALID_ACK,

@ -137,6 +137,7 @@ struct DetectEngineEvents_ {
{ "stream.4whs_invalid_ack", STREAM_4WHS_INVALID_ACK, },
{ "stream.closewait_ack_out_of_window", STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW, },
{ "stream.closewait_fin_out_of_window", STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW, },
{ "stream.closewait_pkt_before_last_ack", STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK, },
{ "stream.closewait_invalid_ack", STREAM_CLOSEWAIT_INVALID_ACK, },
{ "stream.closing_ack_wrong_seq", STREAM_CLOSING_ACK_WRONG_SEQ, },
{ "stream.closing_invalid_ack", STREAM_CLOSING_INVALID_ACK, },

@ -2673,8 +2673,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
"%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p));
int retransmission = 0;
if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq - 1) &&
SEQ_EQ(TCP_GET_ACK(p), ssn->server.last_ack)) {
SCLogDebug("ssn %p: retransmission", ssn);
retransmission = 1;
} else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
@ -2690,9 +2696,11 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
return -1;
}
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
ssn->client.flags |= STREAMTCP_STREAM_FLAG_CLOSE_INITIATED;
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
if (!retransmission) {
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
ssn->client.flags |= STREAMTCP_STREAM_FLAG_CLOSE_INITIATED;
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
}
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
@ -2719,8 +2727,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
"%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p));
int retransmission = 0;
if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq - 1) &&
SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack)) {
SCLogDebug("ssn %p: retransmission", ssn);
retransmission = 1;
} else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
@ -2736,10 +2750,11 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
return -1;
}
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
ssn->server.flags |= STREAMTCP_STREAM_FLAG_CLOSE_INITIATED;
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
if (!retransmission) {
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
ssn->server.flags |= STREAMTCP_STREAM_FLAG_CLOSE_INITIATED;
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
}
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));
@ -3219,7 +3234,12 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
"%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p));
if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->client.last_ack))) {
SCLogDebug("ssn %p: -> retransmission", ssn);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
SCReturnInt(-1);
} else if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
@ -3261,7 +3281,12 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
"%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
TCP_GET_SEQ(p), TCP_GET_ACK(p));
if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->server.last_ack))) {
SCLogDebug("ssn %p: -> retransmission", ssn);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK);
SCReturnInt(-1);
} else if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) ||
SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""

Loading…
Cancel
Save