Ruleset debug/tracing: Difference between revisions

From nftables wiki
Jump to navigation Jump to search
(add see also section with external links)
 
(14 intermediate revisions by one other user not shown)
Line 7: Line 7:
* monitor the trace events from the nft tool
* monitor the trace events from the nft tool


= enabling nftrace =
= Enabling nftrace =


To enable nftrace in a packet, use a rule with this statement:
To enable nftrace in a packet, use a rule with this statement:
Line 17: Line 17:


Of course, you may only enable nftrace for a given matching packet.
Of course, you may only enable nftrace for a given matching packet.
In the example below, we only enable nftrace for tcp packets using the loopback interface:
In the example below, we only enable nftrace for tcp packets:


<source lang="bash">
<source lang="bash">
iif lo ip protocol tcp meta nftrace set 1
ip protocol tcp meta nftrace set 1
</source>
</source>


Adjusting nftrace to only your subset of desired packets is key to properly debug the ruleset, otherwise you may get a lot of debug/tracing information which may be overwhelming.
Adjusting nftrace to only your subset of desired packets is key to properly debug the ruleset, otherwise you may get a lot of debug/tracing information which may be overwhelming.


The following example shows how to enable tracing for your existing ruleset:
= Use a chain to enable tracing =
 
The recommended way to enable tracing is to add a chain for this purpose.
 
Register a ''trace_chain'' to enable tracing. If you already have a prerouting chain, then make sure your ''trace_chain'' priority comes ''before'' your existing prerouting chain.


<source lang="bash">
<source lang="bash">
% nft add chain filter trace_chain { type filter hook prerouting priority -600\; }
% nft add chain filter trace_chain { type filter hook prerouting priority -301\; }
% nft add rule filter trace_chain meta nftrace set 1
% nft add rule filter trace_chain meta nftrace set 1
</source>
</source>


This is registering a ''trace_chain'' chain at priority -600 which contains a rule to enable tracing. If you already have a prerouting chain, then make sure the ''trace_chain'' priority comes ''before'' your existing prerouting chain.
This example assumes you have an existing raw prerouting chain (at priority -300), hence, this is registering a trace chain right before this chain (at priority -301).


Once you are done with rule tracing, you can just delete this chain to disable it:
Once you are done with rule tracing, you can just delete this chain to disable it:
Line 53: Line 57:
Each trace event is assigned an 'id' for you to easily follow different packets in the same trace session.
Each trace event is assigned an 'id' for you to easily follow different packets in the same trace session.


= complete example =
= Complete example =
 
Here is complete example of this debug/tracing mechanism in work.
 
Assuming you have this ruleset:
 
<source lang="bash">
table ip filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related counter packets 2 bytes 292 accept
                ct state new tcp dport 22 counter packets 0 bytes 0 accept
        }
}
</source>
 
Load this ruleset:
 
<source lang="bash">
% nft -f ruleset.nft
</source>
 
Then, add a chain that enables tracing:
 
<source lang="bash">
% nft add chain ip filter trace_chain { type filter hook prerouting priority -1\; }
</source>


Here are a couple of complete examples of this debug/tracing mechanism in work.
This registers the ''trace_chain'' before the existing ''input'' chain.


Simple tracing test:
And the rule to enable the tracing:
 
<source lang="bash">
% nft add rule ip filter trace_chain meta nftrace set 1
</source>
 
Simple tracing test, by pinging one host:
 
<source lang="bash">
% ping -c 1 8.8.8.8
</source>
 
You run on a different terminal:


<source lang="bash">
<source lang="bash">
% nft add rule inet filter input iif lo counter nftrace set 1 accept
% nft monitor trace
% nft monitor trace
trace id 530fa6dd inet filter input packet: iif lo
trace id a95ea7ef ip filter trace_chain packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640
trace id 530fa6dd inet filter input rule iif lo accept (verdict accept)
trace id a95ea7ef ip filter trace_chain rule meta nftrace set 1 (verdict continue)
trace id 87a375ea inet filter input packet: iif lo
trace id a95ea7ef ip filter trace_chain verdict continue
trace id 87a375ea inet filter input rule iif lo accept (verdict accept)
trace id a95ea7ef ip filter trace_chain policy accept  
trace id a95ea7ef ip filter input packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640
trace id a95ea7ef ip filter input rule ct state established,related counter packets 168 bytes 53513 accept (verdict accept)
</source>
</source>


Tracing two different kind of packets at the same monitor session:
The trace id uniquely identifies a packet. The trace describes the packet entering the chain initially.


<source lang="bash">
<source lang="bash">
% nft filter input tcp dport 10000 nftrace set 1
trace id a95ea7ef ip filter trace_chain packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640
% nft filter input icmp type echo-request nftrace set 1
% nft -nn monitor trace
trace id e1f5055f ip filter input packet: iif eth0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 ip saddr 192.168.122.1 ip daddr 192.168.122.83 ip tos 0 ip ttl 64 ip id 32315 ip length 84 icmp type echo-request icmp code 0 icmp id 10087 icmp sequence 1
trace id e1f5055f ip filter input rule icmp type echo-request nftrace set 1 (verdict continue)
trace id e1f5055f ip filter input verdict continue
trace id e1f5055f ip filter input
trace id 74e47ad2 ip filter input packet: iif vlan0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 vlan pcp 0 vlan cfi 1 vlan id 1000 ip saddr 10.0.0.1 ip daddr 10.0.0.2 ip tos 0 ip ttl 64 ip id 49030 ip length 84 icmp type echo-request icmp code 0 icmp id 10095 icmp sequence 1
trace id 74e47ad2 ip filter input rule icmp type echo-request nftrace set 1 (verdict continue)
trace id 74e47ad2 ip filter input verdict continue
trace id 74e47ad2 ip filter input
trace id 3030de23 ip filter input packet: iif vlan0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 vlan pcp 0 vlan cfi 1 vlan id 1000 ip saddr 10.0.0.1 ip daddr 10.0.0.2 ip tos 16 ip ttl 64 ip id 59062 ip length 60 tcp sport 55438 tcp dport 10000 tcp flags == syn tcp window 29200
trace id 3030de23 ip filter input rule tcp dport 10000 nftrace set 1 (verdict continue)
trace id 3030de23 ip filter input verdict continue
trace id 3030de23 ip filter input
</source>
</source>
Then, the packet travel through the ruleset.
= See also =
Some external tools can automate all the steps described here, see:
* https://github.com/aborrero/nftables-tracer (python based)
* https://github.com/aojea/nftrace (golang based)

Latest revision as of 14:13, 16 October 2024

Since nftables v0.6 and linux kernel 4.6, ruleset debug/tracing is supported.

This is an equivalent of the old iptables method -J TRACE, but with some great improvements.

The steps to enable debug/tracing is the following:

  • give support in your ruleset for it (set nftrace in any of your rules)
  • monitor the trace events from the nft tool

Enabling nftrace

To enable nftrace in a packet, use a rule with this statement:

meta nftrace set 1

After all, nftrace is part of the metainformation of a packet.

Of course, you may only enable nftrace for a given matching packet. In the example below, we only enable nftrace for tcp packets:

ip protocol tcp meta nftrace set 1

Adjusting nftrace to only your subset of desired packets is key to properly debug the ruleset, otherwise you may get a lot of debug/tracing information which may be overwhelming.

Use a chain to enable tracing

The recommended way to enable tracing is to add a chain for this purpose.

Register a trace_chain to enable tracing. If you already have a prerouting chain, then make sure your trace_chain priority comes before your existing prerouting chain.

% nft add chain filter trace_chain { type filter hook prerouting priority -301\; }
% nft add rule filter trace_chain meta nftrace set 1

This example assumes you have an existing raw prerouting chain (at priority -300), hence, this is registering a trace chain right before this chain (at priority -301).

Once you are done with rule tracing, you can just delete this chain to disable it:

% nft delete chain filter trace_chain

monitoring tracing events

In nftables, getting the debug/tracing events is a bit different from the iptables world. Now, we have an event-based monitor for the kernel to notify the nft tool.

The basic syntax is:

% nft monitor trace

Each trace event is assigned an 'id' for you to easily follow different packets in the same trace session.

Complete example

Here is complete example of this debug/tracing mechanism in work.

Assuming you have this ruleset:

table ip filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related counter packets 2 bytes 292 accept
                ct state new tcp dport 22 counter packets 0 bytes 0 accept
        }
}

Load this ruleset:

% nft -f ruleset.nft

Then, add a chain that enables tracing:

% nft add chain ip filter trace_chain { type filter hook prerouting priority -1\; }

This registers the trace_chain before the existing input chain.

And the rule to enable the tracing:

% nft add rule ip filter trace_chain meta nftrace set 1

Simple tracing test, by pinging one host:

% ping -c 1 8.8.8.8

You run on a different terminal:

% nft monitor trace
trace id a95ea7ef ip filter trace_chain packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640 
trace id a95ea7ef ip filter trace_chain rule meta nftrace set 1 (verdict continue)
trace id a95ea7ef ip filter trace_chain verdict continue 
trace id a95ea7ef ip filter trace_chain policy accept 
trace id a95ea7ef ip filter input packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640 
trace id a95ea7ef ip filter input rule ct state established,related counter packets 168 bytes 53513 accept (verdict accept)

The trace id uniquely identifies a packet. The trace describes the packet entering the chain initially.

trace id a95ea7ef ip filter trace_chain packet: iif "enp0s25" ether saddr 00:0d:b9:4a:49:3d ether daddr 3c:97:0e:39:aa:20 ip saddr 8.8.8.8 ip daddr 192.168.2.118 ip dscp cs0 ip ecn not-ect ip ttl 115 ip id 0 ip length 84 icmp type echo-reply icmp code net-unreachable icmp id 9253 icmp sequence 1 @th,64,96 24106705117628271805883024640

Then, the packet travel through the ruleset.

See also

Some external tools can automate all the steps described here, see: