Re: [nftables] conntrack behavior wondering

Mathias Dufresne
2026-03-03T09:00:24Z

Hi, me again : )

My understanding of linux firewalling was far worst than I expected.

input/output are used by connections to localhost only and packets
passing through the firewall do not use them. Packets passing through
the firewall only use forward.

Now regarding the fact I was needing to accept packet without using CT
it was a route issue. I built a test firewall to not break everything
while doing these tests and I forgot to modify routes on SSH servers
which replying through the normal router, not the test firewall.

SSH client -> test FW -> SSH server -> usual router -> SSH client

This made CT crazy enough to not match related/established.

My bad. Sorry all that noise ; )

Best regards,

mathias

Le 2026-03-02 à 20:57, Mathias Dufresne a écrit :
> Hi everyone,
>
> I don't understand conntrack behavior while forwarding packets. For me
> a packet kept its status of being new, related or established all the
> way, until it reached the target.
>
> Below is the configuration I tested. In that configuration input,
> forward and output are:
>
> - accepting related and established packets
>
> - jumping to service chain
>
> - dropping everything after logging the drop.
>
> This configuration allows SSH connection correctly but in a strange
> manner:
>
> - SSH to the firewall (10.91.62.172/32) works well and generates only
> one log, the on from chain ip_log_svc_administrative_services/ssh
> which logs NEW packet from input hook.
>
> - SSH through the firewall works (the connection works) but logs are
> strange (to me at least) as :
>
>   - no logs from chain ip_log_svc_administrative_services/ssh which
> logs NEW packet from input hook.
>
>   - no logs for output hook which shall see a new packet and shall not
> match established/related rule and then shall throw the packet
> to chain svc-ssh-out, but no log from there.
>
>   - there logs from forward once the packet has been passed to chain
> svc-ssh-fwd but the logs which are generated are always the logs of
> rules without ct state. Both previous pairs of rules using ct state
> are ignored.
>
> If packets are supposed to keep the CT status along all three hooks,
> I'd expect one log from input as new, two others logs for new from
> forward then from output and finally logs from forward as
> related/established.
>
> Sorry about all noise I'm producing on your list but I'm puzzled...
>
> Cheers,
>
> mathias
>
> PS : except for my misunderstanding of CT, service chains are working
> magnificently, thank you again ; )
>
> --------------------------------------------------------------------------
>
>
> table ip filter_them_all {
>   chain ip_log_svc_administrative_services/ssh {
>     counter packets 0 bytes 0 log prefix "Accept ip SVC for
> 'administrative services/ssh': " group 2
>     counter packets 0 bytes 0 accept
>   }
>   chain svc-ssh-inp {
>     iif vdi-lan             ip daddr 10.91.62.172/32 ct state new jump
> ip_log_svc_administrative_services/ssh
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state new jump
> ip_log_svc_administrative_services/ssh
>     counter packets 0 bytes 0 log prefix "SSH INP KO." group 2
>     counter packets 0 bytes 0 drop
>   }
>   chain svc-ssh-fwd {
>     # these don't seem to work. YET!
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state new
>               log prefix "ACCEPT NEW FORWARD for ssh" group 2
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state new
>               accept
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state
> {established, related} log prefix "ACCEPT REL/EST FORWARD for ssh"
> group 2
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state
> {established, related} accept
>     # these two are working and STILL can't be omitted
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 log prefix
> "ACCEPT FORWARD for ssh" group 2
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 accept
>     counter packets 0 bytes 0 log prefix "SSH FWD KO." group 2
>     counter packets 0 bytes 0 drop
>   }
>   chain svc-ssh-out {
>     # these are never used
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state new log
> prefix "ACCEPT NEW OUTPUT for ssh" group 2
>     iif vdi-lan oif svc-web ip daddr 10.207.184.0/24 ct state new accept
>     counter packets 0 bytes 0 log prefix "SSH OUT KO." group 2
>     counter packets 0 bytes 0 drop
>   }
>   chain svc-dns-req {
>     ip daddr 10.195.171.240/32 accept
>   }
>   chain svc-dns-res {
>     ip saddr 10.195.171.240/32 accept
>   }
>   chain input {
>     type filter hook input priority filter; policy drop;
>     ct state {established,related} accept
>     tcp dport 22 jump svc-ssh-inp
>     udp dport 53 jump svc-dns-req
>     counter packets 0 bytes 0 log prefix "REFUSED INPUT packet as it
> reached the end of filtering rules stack." group 2
>     counter packets 0 bytes 0 drop
>   }
>   chain forward {
>     type filter hook forward priority filter; policy drop;
>     ct state {established,related} accept
>     tcp dport 22 jump svc-ssh-fwd
>     udp dport 53 jump svc-dns-req
>     counter packets 0 bytes 0 log prefix "REFUSED FORWARD packet as it
> reached the end of filtering rules stack." group 2
>     counter packets 0 bytes 0 drop
>   }
>   chain output {
>     type filter hook output priority filter; policy drop;
>     ct state {established,related} accept
>     tcp dport 22 jump svc-ssh-out
>     udp sport 53 jump svc-dns-res
>     counter packets 0 bytes 0 log prefix "REFUSED OUTPUT packet as it
> reached the end of filtering rules stack." group 2
>     counter packets 0 bytes 0 drop
>   }
> }
>
> --------------------------------------------------------------------------
>
>
>