I was approaching this from an operational standpoint and never considered the debugging use case.
The entire script is parsing nft already, and only printing when matching on what is in the actual table. The JSON that NFT spits out is very hard to work with.
{'rule': {'family': 'ip', 'table': 'vyos_filter', 'chain': 'VYOS_FORWARD_filter', 'handle': 25, 'comment': 'ipv4-FWD-filter-1234', 'expr': [{'match': {'op': '==', 'left': {'payload': {'protocol': 'ip', 'field': 'daddr'}}, 'right': '1.1.1.2'}}, {'match': {'op': '==', 'left': {'payload': {'protocol': 'tcp', 'field': 'dport'}}, 'right': '@P_P1000'}}, {'match': {'op': '==', 'left': {'payload': {'protocol': 'ip', 'field': 'saddr'}}, 'right': '1.1.1.1'}}, {'match': {'op': '==', 'left': {'payload': {'protocol': 'tcp', 'field': 'sport'}}, 'right': 1}}, {'match': {'op': '==', 'left': {'meta': {'key': 'iifname'}}, 'right': 'eth1'}}, {'match': {'op': '==', 'left': {'meta': {'key': 'oifname'}}, 'right': 'eth2'}}, {'counter': {'packets': 0, 'bytes': 0}}, {'accept': None}]}}
I parse that output into something that is easier to work with later:
{'source_ip': '1.1.1.1', 'destination_ip': '1.1.1.2', 'source_port': 1, 'destination_port': '@P_P1000', 'action': 'accept', 'comment': 'ipv4-FWD-filter-1234', 'protocols': ['ip', 'tcp'], 'iifname': 'eth1', 'oifname': 'eth2'}
I can have it store some additional values (family/table/chain/handle) that would make calling that specific rule later easy:
{'source_ip': '1.1.1.1', 'destination_ip': '1.1.1.2', 'source_port': 1, 'destination_port': '@P_P1000', 'action': 'accept', 'comment': 'ipv4-FWD-filter-1234', 'protocols': ['ip', 'tcp'], 'iifname': 'eth1', 'oifname': 'eth2', 'family': 'ip', 'table': 'vyos_filter', 'chain': 'VYOS_FORWARD_filter', 'handle': 25}
Here’s what it looks like after that change:
vyos@vyos# run show firewall packet-info source-ip 1.1.1.1 destination-ip 1.1.1.2 source-port 1 destination-port 1000 protocol tcp
------------------------------------------------
--------------- Phase 1: Routing ---------------
------------------------------------------------
Source:
Route | 0.0.0.0/0
Protocol | static
VRF | default
Next Hop(s) | 10.0.101.1
Exit Interface(s) | eth0.101
Destination:
Route | 0.0.0.0/0
Protocol | static
VRF | default
Next Hop(s) | 10.0.101.1
Exit Interface(s) | eth0.101
------------------------------------------------
----------------- Phase 2: NAT -----------------
------------------------------------------------
Source NAT matched on rule 100
------------------------------------------------
Configured:
set nat source rule 100 destination address '1.1.1.2'
set nat source rule 100 destination port '1000'
set nat source rule 100 outbound-interface name 'eth2'
set nat source rule 100 protocol 'tcp'
set nat source rule 100 source address '1.1.1.1'
set nat source rule 100 source port '1'
set nat source rule 100 translation address 'masquerade'
--------------------------------
Active Rule:
oifname "eth2" ip saddr 1.1.1.1 tcp sport 1 tcp dport 1000 ip daddr 1.1.1.2 counter packets 0 bytes 0 masquerade
------------------------------------------------
--------------- Phase 3: Firewall --------------
------------------------------------------------
Matching Rule Found:
Rule Information
---------------------------------
ipv4 Firewall "forward filter"
Rule | 1234
Description |
Action | accept
Protocol | tcp
Packets | 0
Bytes | 0
Conditions | ip daddr 1.1.1.2 tcp dport @P_P1000 ip saddr 1.1.1.1 tcp sport 1
| iifname "eth1" oifname "eth2" accept
------------------------------------------------
----------------- Phase 4: PBR -----------------
------------------------------------------------
Policy Route matched on rule 10 of policy route TEST2
------------------------------------------------
Configured:
set policy route TEST2 rule 10 destination address '1.1.1.2'
set policy route TEST2 rule 10 destination port '1000'
set policy route TEST2 rule 10 protocol 'tcp'
set policy route TEST2 rule 10 source address '1.1.1.1'
set policy route TEST2 rule 10 source port '1'
--------------------------------
Active Rule:
ip daddr 1.1.1.2 ip saddr 1.1.1.1 tcp sport 1 tcp dport 1000 counter packets 0 bytes 0 return