On Sat, 3 Feb 2024, Florian Westphal wrote:
Text is rather unstable, I would not rely on it.
json ought to be stable, netlink is stable (its the api after all).
Thanks. I implemented my first prototype on the JSON output, and only for
netfilter for now. You can give it a ruleset, desired verdict and extra
constraints and it will find a packet that achieves the desired verdict if
it exists.
Here are some examples:
nftables_analysis$ for i in test_data/*.nft; do echo "#### $i"; cat $i; ./find_satisfying_packet.py --json-ruleset $i.json -c tcp.dport==1234; done
#### test_data/complex1.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
meta nfproto ipv6 tcp sport 53 meta length == 200 iif > 0 ip6 saddr fe80::fca5:f7ff:febc:97a4 tcp dport 1234 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=-1
ip.saddr=-1
ip6.daddr=0
ip6.saddr=338288524927261089672224126588925286308
meta.iif=1
meta.l4proto=6
meta.length=200
meta.nfproto=10
tcp.dport=1234
tcp.sport=53
udp.dport=-1
udp.sport=-1
#### test_data/complex2.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
meta nfproto ipv6 tcp dport 1234 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=-1
ip.saddr=-1
ip6.daddr=0
ip6.saddr=0
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=10
tcp.dport=1234
tcp.sport=0
udp.dport=-1
udp.sport=-1
#### test_data/source_iface.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
iif enp0s31f6 tcp dport 1234 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=0
ip.saddr=0
ip6.daddr=-1
ip6.saddr=-1
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=2
tcp.dport=1234
tcp.sport=0
udp.dport=-1
udp.sport=-1
#### test_data/source_ip2.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 1234 jump helper
tcp dport 1234 accept
}
chain helper {
ip saddr 10.61.7.4 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=0
ip.saddr=171771652
ip6.daddr=-1
ip6.saddr=-1
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=2
tcp.dport=1234
tcp.sport=0
udp.dport=-1
udp.sport=-1
#### test_data/source_ip.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 1234 ip saddr 10.61.7.4 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=0
ip.saddr=171771652
ip6.daddr=-1
ip6.saddr=-1
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=2
tcp.dport=1234
tcp.sport=0
udp.dport=-1
udp.sport=-1
#### test_data/source_port_ipv6.nft
#!/usr/sbin/nft -f
table ip my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 1234 drop
}
}
table ip6 my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 1234 tcp sport 53 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=-1
ip.saddr=-1
ip6.daddr=0
ip6.saddr=0
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=10
tcp.dport=1234
tcp.sport=53
udp.dport=-1
udp.sport=-1
#### test_data/source_port.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 1234 tcp sport 53 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=0
ip.saddr=0
ip6.daddr=-1
ip6.saddr=-1
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=2
tcp.dport=1234
tcp.sport=53
udp.dport=-1
udp.sport=-1
#### test_data/source_port_range.nft
#!/usr/sbin/nft -f
table inet my_filter {
chain input {
type filter hook input priority 0; policy accept;
tcp sport {50-55} tcp dport 1234 accept
tcp dport 1234 drop
}
}
Satified
ip.daddr=0
ip.saddr=0
ip6.daddr=-1
ip6.saddr=-1
meta.iif=0
meta.l4proto=6
meta.length=0
meta.nfproto=2
tcp.dport=1234
tcp.sport=50
udp.dport=-1
udp.sport=-1
I put the code to https://github.com/lindi2/nftables_analysis
(MIT license, do whatever you want but I would appreciate bug fixes so
that I can make it more reliable and maybe implement iptables support
later as well)
-Timo