From: Eric Leblond Date: Wed, 11 Sep 2013 15:52:09 +0000 (+0200) Subject: reject: update computation of seq and ack X-Git-Tag: suricata-2.0beta2~256 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f224f87d1e59f90969d45e6dcbbd6918083ee7d;p=thirdparty%2Fsuricata.git reject: update computation of seq and ack We have follow TCP RFC (http://tools.ietf.org/html/rfc793#section-3.4). There is two cases depending on wether the original packet contains a ACK. If packet has no ACK, the RST seq number is 0 and the ACK is built the standard way. If packet has a ACK, the seq of the RST packet is equal to the ACK of incoming packet and the ACK is build using packet sequence number and size of the data. Regarding standard Ack number, it is computed using seq number of captured packet added to packet length. Finally 1 is added so we respect the RFC: If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent. With this patch we have some correct results. With the following rule: reject ssh any any -> 192.168.56.3 any (msg:"no SSH way"; sid:3; rev:1;) ssh connection to 192.168.56.3 is correctly resetted on client side. But this is not perfect. If we have the following rule: reject tcp any any -> 192.168.56.3 22 (msg:"no way"; sid:2; rev:1;) then the connection is not resetted on a standard ethernet network. But if we introduce 20ms delay on packets, then it is correctly resetted. This is explained when looking at the network trace. The reset is sent as answer to the SYN packet and it is emitted after the SYN ACK from server because the exchange is really fast. So this is discarded by the client OS which has already seen a ACK for the same sequence number. This should fix #895. --- diff --git a/src/respond-reject-libnet11.c b/src/respond-reject-libnet11.c index a5993d4f4f..f91a3173c6 100644 --- a/src/respond-reject-libnet11.c +++ b/src/respond-reject-libnet11.c @@ -105,8 +105,18 @@ int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir) switch (dir) { case REJECT_DIR_SRC: SCLogDebug("sending a tcp reset to src"); - lpacket.seq = TCP_GET_ACK(p); - lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize; + /* We follow http://tools.ietf.org/html/rfc793#section-3.4 : + * If packet has no ACK, the seq number is 0 and the ACK is built + * the normal way. If packet has a ACK, the seq of the RST packet + * is equal to the ACK of incoming packet and the ACK is build + * using packet sequence number and size of the data. */ + if (TCP_GET_ACK(p) == 0) { + lpacket.seq = 0; + lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize + 1; + } else { + lpacket.seq = TCP_GET_ACK(p); + lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize; + } lpacket.sp = TCP_GET_DST_PORT(p); lpacket.dp = TCP_GET_SRC_PORT(p); @@ -142,7 +152,7 @@ int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir) lpacket.sp, /* source port */ lpacket.dp, /* dst port */ lpacket.seq, /* seq number */ - lpacket.ack+1, /* ack number */ + lpacket.ack, /* ack number */ TH_RST|TH_ACK, /* flags */ lpacket.window, /* window size */ 0, /* checksum */