3

Sort of the similar question as this - Routing table hits? - except that I don't use iptables and looking for normal routing hits in kernel routing table.

But my usecase is finding how many packets are being forwarded via the default route in my firewall, in order to make sure it's useless before I delete it. The responses to the mentioned question include inspecting the cache, but is it possible that some packets will be forwarded without hitting the cache?

In addition, after inspecting the cache the command recommended (route -neeC) just terminates and I'd like to inspect default route "lookup hits" for a long period (~24 hours). Any recommendations on how to do that?

Cheers.

7
  • 1
    What about a tcpdump pcap file and filter?
    – Lenniey
    Nov 27, 2019 at 11:37
  • @Lenniey , pcap doesn't help me as it doesn't show the route used. Think about a scenario where I have a default gateway pointing at 1.1.1.1, but also another 10 routes pointing at 1.1.1.1. A capture will show me many packets going there but not the route used to determine the next hop. Nov 27, 2019 at 12:16
  • Yeah, filter the target IP to your gateway and the source IP != your IP. If you don't use NAT or anything, this should show you packets not originating from your machine, but targeting your gateway.
    – Lenniey
    Nov 27, 2019 at 12:44
  • But this is a firewall, it functions as a router. There's no traffic originating from my machine, and traffic targeting the gateway could be sourced in addresses that are using the default route and some addresses that are using specific routes. Nov 27, 2019 at 13:20
  • Why does it matter if you delete the default gateway, if "10 routes are pointing to 1.1.1.1"?
    – Lenniey
    Nov 27, 2019 at 14:46

2 Answers 2

3

The linux routing cache for IPv4 has been removed in Linux 3.6 (leaving only the use of an optimized LPC-trie). There's thus no way with a Linux system with an OS from after 2012 to get routing cache statistics.


An easy way to tag the usage of the default route is to place a realm value on this route. A packet matching this route (rather than a more specific route using the same gateway) will be identified as being with the given realm value. So if the default route was 192.0.2.1 via eth0, the route would be set for example like this:

ip route add default via 192.0.2.1 proto static realm 10

Or you could change a previous default route (without realm) by replacing add with change, without disruption.

This realm tag can then be reused at least in two other network subsystems: tc filter ... route or nftables' nft ... meta rtclassid.


Traffic Control

tc is quite crude and usually working at the interface level. The easiest way to attach a filter is to use the prio qdisc, the simplest classful qdisc. Its specific priority properties won't be actually used. So following on the previous example:

tc qdisc add dev eth0 root handle 1: prio

Now add the filter with an empty action (and with a pref order and a continue control to allow additional similar filters if needed), just to have statistics on it:

tc filter add dev eth0 parent 1: protocol ip pref 1 route to 10 action continue

Now every ip packet matching route realm 10, will be shown in statistics by using tc -s filter show dev eth0. Example:

# tc -s filter show dev eth0
filter parent 1: protocol all pref 1 route chain 0 
filter parent 1: protocol all pref 1 route chain 0 fh 0xffff000a to 10 
    action order 1: gact action continue
     random type none pass val 0
     index 1 ref 1 bind 1 installed 48 sec used 4 sec
    Action statistics:
    Sent 12230 bytes 79 pkt (dropped 0, overlimits 0 requeues 0) 
    backlog 0b 0p requeues 0

Note: both forwarded and locally originated packets are matching, which could be a problem for measurements.


nftables

nftables here won't be used to do any kind of firewalling, but just to increment some counters.

nftables installs only requested netfilter's hooks, rather than all available, thus usually having a lesser footprint than iptables. Here we just need a rule matching the realm - that's the role of the rtclassid expression - with a counter on it. If it's for locally originated packets, then just use the output hook. The forward hook will match only forwarded packets.

nft add table ip mystats
nft add chain ip mystats forward '{ type filter hook forward priority 0; policy accept; }'
nft add rule ip mystats forward meta rtclassid 10 counter

Which would give for example later:

# nft list ruleset
table ip stats {
    chain forward {
        type filter hook forward priority filter; policy accept;
        meta rtclassid 10 counter packets 1453 bytes 118264
    }
}

Zeroing the value is possible only if storing it in a named object, the ruleset would be instead (to load with nft -f file):

table ip mystats {
    counter defaultroutecount { }

    chain forward {
        type filter hook forward priority filter; policy accept;
        meta rtclassid 10 counter name "defaultroutecount"
    }
}

Then nft list counters or nft reset counters will display (or display and reset) its content.

1
  • Thank you so much! What an amazing answer. Great news! Dec 10, 2019 at 8:16
1

You can use:

iptables -vL

or for forwarding:

iptables -t nat -vL

to see the number of packets per matching rule.

2
  • 2
    But I don't have iptables enabled and not using any rules... Nov 27, 2019 at 10:48
  • 1
    Ah.. ok, in that case try having a look into /proc/net/fib_triestat (maybe save the state at time X and compare with the state at time X + 24h). You can find more info here: vincent.bernat.ch/en/blog/2017-ipv4-route-lookup-linux
    – Zatarra
    Nov 27, 2019 at 12:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .