# TCP/IP Header Length Calculation Rules using byte\_math

**URL:** <https://forum.suricata.io/t/tcp-ip-header-length-calculation-rules-using-byte-math/6128>\
**Category:** Rules\
**Tags:** rules, suricata\
**Created:** [December 3, 2025, 6:00am UTC](https://forum.suricata.io/t/tcp-ip-header-length-calculation-rules-using-byte-math/6128 "2025-12-03T06:00:20Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Flying\_Sheep](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.suricata.io/flying_sheep/32/3748_2.png) [@Flying\_Sheep](https://forum.suricata.io/u/Flying_Sheep)\
**Post date:** [December 3, 2025, 6:00am UTC](https://forum.suricata.io/t/tcp-ip-header-length-calculation-rules-using-byte-math/6128/1 "2025-12-03T06:00:20Z")

</div>

> Please include the following information with your help request:
> 
> - Suricata version:8.0.1
> - Operating system and/or Linux distribution:ubuntu 25.04
> - How you installed Suricata:from source

Hi, I‘m using suricata to identify os fingerprints. Here are some rules which intended to calculate the total length of tcp header and ip header with byte\_extract, byte\_math and byte\_test:

```auto
alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";endswith;byte_extract:1,12,tcphdrlen;byte_math:bytes tcphdrlen,offset 0,oper >>,rvalue 4,result tcphdrlen;ipv4.hdr;byte_math:bytes 1,offset 0,oper +,rvalue tcphdrlen,result totallen,bitmask 15;byte_test:totallen,<,13,0;ttl:128;sid:1104778; rev:1;)
#this rule is meant to be triggered, which indicates ip header length + tcp header length = 13*4 = 52
alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";endswith;byte_extract:1,12,tcphdrlen;byte_math:bytes tcphdrlen,offset 0,oper >>,rvalue 4,result tcphdrlen;ipv4.hdr;byte_math:bytes 1,offset 0,oper +,rvalue tcphdrlen,result totallen,bitmask 15;byte_test:totallen,=,13,0;ttl:128;sid:1104779; rev:1;)
alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";endswith;byte_extract:1,12,tcphdrlen;byte_math:bytes tcphdrlen,offset 0,oper >>,rvalue 4,result tcphdrlen;ipv4.hdr;byte_math:bytes 1,offset 0,oper +,rvalue tcphdrlen,result totallen,bitmask 15;byte_test:totallen,>,13,0;ttl:128;sid:1104780; rev:1;)
#alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";endswith;ttl:128;sid:1104781; rev:1;)

```

To my surprise none of the rules above are fired, since theoretically they cover all possible scenarios. Only sid 1104781 will be fired if I uncomment it, which confuses me.🤨  
Your advice would be of great help to me. Thanks in advance! 😀

---

<div class="post-metadata">

**Author:** ![Flying\_Sheep](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.suricata.io/flying_sheep/32/3748_2.png) [@Flying\_Sheep](https://forum.suricata.io/u/Flying_Sheep)\
**Post date:** [December 3, 2025, 6:06am UTC](https://forum.suricata.io/t/tcp-ip-header-length-calculation-rules-using-byte-math/6128/2 "2025-12-03T06:06:46Z")

</div>

update:The rule will be triggered if I use byte\_test directly, while extracting bytes to a variable and then applying byte\_test to it does not work. 😢

```auto
#works
alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";offset:20;byte_test:1,=,0x80,0;ttl:128,12;sid:1104780; rev:1;)
#does not work
alert tcp any any -> any any (msg:"Windows 8";tcp.flags:S,CE;window:65535;tcp.hdr;content:"|02 04 05 b4 01 03 03 08 01 01 04 02|";offset:20;byte_extract:1,12,tcphdrlen;byte_test:tcphdrlen,=,0x80,0;ttl:128;sid:1104781; rev:1;)

```
