3

iptables has the statistic module that allows doing operations on packets based on a probability, how would I go about and do this with nftables?

Avamander
  • 193
  • 1
  • 11

1 Answers1

3

numgen

nftables has all features in place, but for some unknown reason, it's not documented in any version of the nft manpage.

The kernel side handling this, nft_numgen has been available since Linux 4.9 and the userland side since the nftables 0.7 release:

  • Add number generation support. Useful for round-robin packet mark setting, eg.

    # nft add rule filter prerouting meta mark set numgen inc mod 2
    

    You can also specify an offset to indicate from what value you want to start from.

    The modulus provides the scale of the counting sequence. You can
    also use this from maps, eg.

    # nft add rule nat prerouting \
          dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 }
    

    So this is distributing new connections in a round-robin fashion
    between 192.168.10.100 and 192.168.20.200. Don't forget the special NAT chain semantics: Only the first packet evaluates the rule, follow up packets rely on conntrack to apply the NAT information.

    You can also emulate flow distribution with different backend weights using intervals, eg.

    # nft add rule nat prerouting \
          dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200 }
    

There's also support for random numbers. Example: replacing in a previous example inc (used for round-robin) with random:

nft add rule nat prerouting dnat to numgen random mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 }

Further documentation and related stuff:


Back to the question

The random number is a 32 bits integer (big enough to ignore modulus bias) on which is applied a modulus. Its value can then be compared. To drop 5% of all non-local incoming IPv4 packets that would then be:

#!/usr/sbin/nft -f

flush ruleset

table ip filter {
    chain input {
        type filter hook input priority 0; policy accept;
        iif "lo" accept
        numgen random mod 100 < 5 drop
    }
}

Example when pinging from its host a container with this ruleset:

# ping -q -f 10.0.3.66
PING 10.0.3.66 (10.0.3.66) 56(84) bytes of data.
^C
--- 10.0.3.66 ping statistics ---
34351 packets transmitted, 32592 received, 5% packet loss, time 19744ms
rtt min/avg/max/mdev = 0.004/0.017/0.481/0.018 ms, ipg/ewma 0.574/0.017 ms
A.B
  • 9,037
  • 2
  • 19
  • 37
  • Thank you so much for your answer, I hope they'll add this module to the list of things `iptables-translate` can translate to save others the trouble when they're trying to simulate packet loss with nftables. – Avamander Jun 20 '19 at 00:37