2

I'm trying to figure out how to allow ICMP pings to a server with nftables without being subject to flood attacks.

Here's my initial config:

table inet firewall {
    chain incoming {
        type filter hook input priority 0; policy drop;

        # established/related connections
        ct state { established, related } accept

        # ICMP
        ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
        ip protocol icmp icmp type { destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept

        # ICMP ping dealt with separately to rate limit
        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 1/second accept
        ip protocol icmp icmp type echo-request limit rate 1/second accept
    }
}

However, flooding with ping -f [IP_ADDRESS] shows most packets getting through. Certainly more than one per second.

If I remove the ct state { established, related } accept rule I get 99% packet loss when trying to flood.

So it seems like the first request establishes a connection and subsequent pings ride in on that rule and it doesn't seem to matter if I put the ct rule after the icmp rule.

Any way to allow established connections but still rate limit pings?

kjs3
  • 155
  • 2
  • 5
  • Have you tried `tc`? You can throttle an interface or limit the rate. – Tux_DEV_NULL Oct 11 '17 at 07:24
  • @Tux_DEV_NULL, what is this `tc` you speak of? I don't see any mention of that in the docs. https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Matches – kjs3 Oct 13 '17 at 22:08
  • tc is traffic contron in linux: http://tldp.org/HOWTO/Traffic-Control-HOWTO/intro.html and http://tldp.org/HOWTO/Traffic-Control-HOWTO/software.html#s-iproute2-tc – Tux_DEV_NULL Oct 15 '17 at 19:50

2 Answers2

3

Try this solution:

table inet firewall {
    chain incoming {
        type filter hook input priority 0; policy drop;

        # ICMP ping dealt with separately to rate limit
        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 1/second accept
        ip6 nexthdr icmpv6 icmpv6 type echo-request counter drop
        ip protocol icmp icmp type echo-request limit rate 1/second accept
        ip protocol icmp icmp type echo-request counter drop

        # established/related connections
        ct state { established, related } accept

        # ICMP
        ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
        ip protocol icmp icmp type { destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept

    }
}

You should explicitly drop the packets, those exceeded ratelimit, to prevent accept they by rules below.

Anton Danilov
  • 5,082
  • 2
  • 13
  • 23
0

Late, but I just stumbled over the same problem and google has led me here... the problem is indeed that ICMP echo/reply is handled by conntrack, see https://www.frozentux.net/iptables-tutorial/chunkyhtml/x1582.html.

You can use something like watch -n1 conntrack -L to supervise the contents of the connection tracking table in real time (default only shows IPv4, IPv6 can be shown via -f ipv6 option)

The important thing is that you have to formulate the limiter as an over condition, where stuff gets dropped before the ct state statement and blanket accept the incoming ping request after the connection tracking statement as well.

What this does:

  • the first incoming ICMP request packet ("NEW" in ct lingo) is accepted via the normal rule
  • all follow up packets of the "ESTABLISHED" ct state are allowed by connection tracking
  • but all packets still have to pass the limit rate over ... rule first, so the limiter still works as expected

code:

   table inet firewall {
            
       chain incoming {

            type filter hook input priority 0; policy drop;
            
            # icmp echo rate limits
            ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second drop
            ip protocol icmp icmp type echo-request limit rate over 1/second drop


            # established/related connections
            ct state { established, related } accept
    

            # accept ICMP ping

            ip6 nexthdr icmpv6 icmpv6 type echo-request accept
            ip protocol icmp icmp type echo-request accept
        }
   }
T Nierath
  • 101
  • 2