Problem with iplen_smaller_than_hlen

We run Suricata 8.0.2-profiling in docker (jasonish/suricata:8.0.2-profiling)

And we encounter issue with attached pcap

mtls.pcap (6.1 KB)

This is mTLS traffic of Sliver utility

It produce only “flow” event

  "event_type": "flow",
...
  "proto": "TCP",
  "app_proto": "failed",
  "app_proto_tc": "tls"
...

and in stats.log we have this entries

decoder.event.ipv4.iplen_smaller_than_hlen
flow.wrk.flows_evicted_needs_work

I think it is triggered because in packet 4 we have reported length of 0

image

I assume that Suricata encounter this bad packet and evict flow as “broken”

Is this expected behavior or not?

This is indeed the current behavior, but I guess we could have a config option to behave like Wireshark and accept the packet

I think one of the problem is that a broken packet is Client-hello, so tls parser cant do its job correctly

As I understend iplen_smaller_than_hlen mean

IP header Total Lenght (TL) smaller than IP header lenght

I look into RFC6274 and RFC791, this check is suggested by section 3.2. RFC6274

For obvious reasons, the Internet header cannot be larger than the
whole Internet datagram of which it is part. Therefore, the
following check should be enforced:

                      IHL * 4 <= Total Length

  This needs to refer to the size of the datagram as specified by
  the sender in the Total Length field, since link layers might have
  added some padding (see Section 3.4).

If the packet does not pass this check, it should be dropped, and
this event should be logged (e.g., a counter could be incremented
reflecting the packet drop).

But it seams that some vendors dont follow this RFC (

I think you can better results with quick&dirty patch

diff --git a/src/decode-ipv4.c b/src/decode-ipv4.c
index 86ea095c62..bcf3a98f39 100644
--- a/src/decode-ipv4.c
+++ b/src/decode-ipv4.c
@@ -487,7 +487,7 @@ static const IPV4Hdr *DecodeIPV4Packet(Packet *p, const uint8_t *pkt, uint16_t l
 
     if (unlikely(IPV4_GET_RAW_IPLEN(ip4h) < IPV4_GET_RAW_HLEN(ip4h))) {
         ENGINE_SET_INVALID_EVENT(p, IPV4_IPLEN_SMALLER_THAN_HLEN);
-        return NULL;
+        // return NULL;
     }
 
     if (unlikely(len < IPV4_GET_RAW_IPLEN(ip4h))) {
@@ -558,7 +558,12 @@ int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
 #endif /* DEBUG */
 
     const uint8_t *data = pkt + IPV4_GET_RAW_HLEN(ip4h);
-    const uint16_t data_len = IPV4_GET_RAW_IPLEN(ip4h) - IPV4_GET_RAW_HLEN(ip4h);
+    uint16_t data_len;
+    if (IPV4_GET_RAW_IPLEN(ip4h) == 0) {
+        data_len = len - IPV4_GET_RAW_HLEN(ip4h);
+    } else {
+        data_len = IPV4_GET_RAW_IPLEN(ip4h) - IPV4_GET_RAW_HLEN(ip4h);
+    }
 
     /* check what next decoder to invoke */
     switch (p->proto) {

I think this is worth opening a redmine ticket