Nft firewall weirdness - not matching ip protocol?

I wanted to see what kinds of exotic traffic, if any, my router was passing, so I wrote an nft firewall table called info. Basically it ignores udp/tcp and then sees what is left. But I am getting very odd results, with udp being logged, when it shouldn't be, as well as ICMPv6

Somehow the logged packets are not triggering the "ip protocol udp" tests.

I am stumped

the nft table is as follows:

table inet info {

   set PROTOS {
      type inet_proto
      flags constant
      counter
      comment "list from   nft describe ip protocol" ;
      elements = {
        ip, icmp, igmp, ggp, ipencap, st, tcp, egp, pup, udp, hmp, xns-idp,
        rdp, iso-tp4, xtp, ddp, idpr-cmtp, ipv6, ipv6-route, ipv6-frag, idrp,
        rsvp, gre, esp, ah, skip, ipv6-icmp, ipv6-nonxt, ipv6-opts, rspf,
        vmtp, ospf, ipip, encap, pim
      }
   }

   chain input {
      type filter hook input priority 0; policy accept;

      ct state established     counter accept

      counter
      ip protocol @PROTOS counter
      ip protocol != @PROTOS counter

      ip protocol udp counter          return
      ip protocol tcp counter          return

      counter
      ip protocol tcp counter comment "should be zero"
      ip protocol udp counter comment "should be zero"
      ip protocol udplite counter
      ip protocol esp counter
      ip protocol ah counter
      ip protocol icmp counter
      ip protocol icmpv6 counter
      ip protocol comp counter
      ip protocol dccp counter
      ip protocol sctp counter
      ct state related     counter

      log prefix "UnusualInA "
      counter
   }

}    # end of table

#    nft list table inet info

The table with counter counts shows that udp packets have been removed from the logging, but...

table inet info {
        set PROTOS {
                type inet_proto
                flags constant
                counter
                comment "list from   nft describe ip protocol"
                elements = { ip counter packets 0 bytes 0, icmp counter packets 0 bytes 0, igmp counter packets 0 bytes 0, ggp counter packets 0 bytes 0, ipencap counter packets 0 bytes 0,
                             st counter packets 0 bytes 0, tcp counter packets 1 bytes 52, egp counter packets 0 bytes 0, pup counter packets 0 bytes 0, udp counter packets 295 bytes 53037,
                             hmp counter packets 0 bytes 0, xns-idp counter packets 0 bytes 0, rdp counter packets 0 bytes 0, iso-tp4 counter packets 0 bytes 0, xtp counter packets 0 bytes 0,
                             ddp counter packets 0 bytes 0, idpr-cmtp counter packets 0 bytes 0, ipv6 counter packets 0 bytes 0, ipv6-route counter packets 0 bytes 0, ipv6-frag counter packets 0 bytes 0,
                             idrp counter packets 0 bytes 0, rsvp counter packets 0 bytes 0, gre counter packets 0 bytes 0, esp counter packets 0 bytes 0, ah counter packets 0 bytes 0,
                             skip counter packets 0 bytes 0, ipv6-icmp counter packets 0 bytes 0, ipv6-nonxt counter packets 0 bytes 0, ipv6-opts counter packets 0 bytes 0, rspf counter packets 0 bytes 0,
                             vmtp counter packets 0 bytes 0, ospf counter packets 0 bytes 0, ipip counter packets 0 bytes 0, encap counter packets 0 bytes 0, pim counter packets 0 bytes 0 }
        }

        chain input {
                type filter hook input priority filter; policy accept;
                ct state established counter packets 1749 bytes 271473 accept
                counter packets 549 bytes 103515
                ip protocol @PROTOS counter packets 296 bytes 53089
                ip protocol != @PROTOS counter packets 0 bytes 0
                ip protocol udp counter packets 295 bytes 53037 return
                ip protocol tcp counter packets 1 bytes 52 return
                counter packets 253 bytes 50426
                ip protocol tcp counter packets 0 bytes 0 comment "should be zero"
                ip protocol udp counter packets 0 bytes 0 comment "should be zero"
                ip protocol 136 counter packets 0 bytes 0
                ip protocol esp counter packets 0 bytes 0
                ip protocol ah counter packets 0 bytes 0
                ip protocol icmp counter packets 0 bytes 0
                ip protocol ipv6-icmp counter packets 0 bytes 0
                ip protocol 108 counter packets 0 bytes 0
                ip protocol 33 counter packets 0 bytes 0
                ip protocol 132 counter packets 0 bytes 0
                ct state related counter packets 0 bytes 0
                log prefix "UnusualInA "
                counter packets 253 bytes 50426
        }
}

When we look at the logs we see both PROTO=ICMPv6 and PROTO=UDP which are not reflected in the counts.

Fri Feb 14 13:58:26 2025 kern.warn kernel: [267315.912306] UnusualInA IN=eth0.2 OUT= MAC=xxx SRC=fe80:0000:0000:0000 TC=0 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=136 CODE=0
Fri Feb 14 13:58:28 2025 kern.warn kernel: [267318.121308] UnusualInA IN=eth0.2 OUT= MAC=yyy SRC=fe80:0000:0000:00008 TC=0 HOPLIMIT=1 FLOWLBL=543241 PROTO=UDP SPT=33140 DPT=10001 LEN=238

ip protocol is ipv4-only , you need to use meta l4proto

Your each rule expanded is
meta nfproto ipv4 meta l4proto .... counter
icmp6 and ip6 udp related,new,notrack,invalid pass your filters unseen.

3 Likes

This is very helpful. Thank you. I know how to organize things better to ensure I don't do this again

Do not hesitate to ask if you have other questions.
Optimally your code would be using concatenation looking up vmap:

established relatrd return
...
jump protocheck
...
chain protocheck {
  meta nfproto . meta l4proto vmap { ipv6 .  icmpv6 :  return , ipv4 . icmp : return , all 4 of ip4 ip6 x tcp x udp } counter
 counter 
 limit rate 1/s log
 #return
}

i leave syntax repair to your discretion.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.