home.


Tagged: nftables


NFTables: Allow ICMP pings and stop ping floods with rate limiting

If you want to allow ping ICMP echo-requests, and you’re automatically dropping all except a few selected incoming packets, you’ll need to first add a rule:

nft insert rule inet global input ip protocol icmp \
  icmp type echo-request accept

This rule is as normal as of nft insert rule inet global input but then we do ip protocol icmp to say we’re interested in the ICMP packets, then icmp type echo-request accept is very similar to the previous rules tcp dport 8888 accept.

Now we can ping our host.

However, with ping -f, we’re open to ping floods. So let’s remove that rule with list table inet global -a to find its handle and then delete it.

nft insert rule inet global input ip protocol icmp \
  icmp type echo-request limit rate 1/second accept

This is as before, except we’re only allowing 1 a second.

But there may be a problem if you also have ct state established accept anywhere in your table since now the echo-requests have an established state, for reasons of which I am not sure.

To get over this, ensure after the rate limiting rule (position 32 is below the icmp rule in my case) we explicitly drop all icmp packets.

nft insert rule inet global input position 32 ip protocol icmp \
    drop

Notes:

  1. The ip protocol icmp bit is only required in inet tables, not ip – this may well be a bug/infleicity from what I’ve seen in 0.5.0 in 3.16
  2. The ct state established biit messing with rate limiting seems odd – also a bug in 0.5 / 3.16?
unix nftables

NFTables: Basic rules, inserting, deleting, established packets and saving

Now we’ve done the basic NFTables setup, let’s make and state some basic rules.

Let’s make the global table and input ruleset again if we haven’t already:

nft add table inet global
nft add chain inet global input { type filter hook input priority 0 \; }

Let’s first open port 22, since we’re SSHing into our box:

nft add rule inet global input tcp dport 22 accept

Now we can drop all the rest:

nft add rule inet global input drop

Let’s insert an ESTABLISHED rule before the drop rule, or right at the top in our case, that allows our incoming packets – when we request a webpage for example – to receive packets from the external server:

nft insert rule inet global input ct state established accept

(You may want to add the related state to accept if you’re using FTP etc)

Finally let’s insert some standard rules for allowing http etc. We’ll use the positional handle indicators – position 8 in my case – for the insertion place via using nft list table inet global -a.

nft insert rule inet global input position 8 tcp dport {80, 8080, 443} accept

(Note the spaces after each comma)

We can now list the table and get:

table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                ct state established accept # handle 14
                tcp dport { https, http, http-alt} accept # handle 16
                tcp dport ssh accept # handle 8
                drop # handle 4
        }
}

If you wanted to delete the last rule, handle 16, we’d do nft delete rule inet global input handle 16.

Let’s save the ruleset (the -n gives us numbers for the ports) and flush/delete the chain and table:

nft -n list -n table inet global -a > fw.ruleset
nft flush chain inet global input
nft delete chain inet global input
nft delete table inet global

In 3.18 of the kernel and upwards, you can just delete the table without first flushing and deleting the chain, but alas.

Now if we list the tables nft list tables we’ll see nothing, which is what we want. Now let’s load the saved rules back in and list them:

# nft -f fw.ruleset 
# nft list table inet global
table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                ct state established accept 
                tcp dport { https, http, http-alt} accept 
                tcp dport ssh accept 
                drop 
        }
}
unix nftables

NFTables: setup and basic tutorial in Debian

First get an external host with a Linux distribution on it with a recent kernel. I’m using Debian Jessie with 3.16 (later kernels will be fine).

# uname -r
3.16.0-4-amd64

For debian jessie, we’ll need the nftables packages which resides in backports. This should be in your /etc/apt/sources.list

deb http://mirrors.kernel.org/debian/ jessie-backports main contrib

Then we can install nftables. Install apache or whatever also, so we can test out filtering.

# apt-get install nftables apache2

I’m using this version of nftables (Warning: things may change with later verseions)

# nft --version
nftables v0.5 (Support Edward Snowden)

Now test we can see apache by going to the host’s IP address.

Let’s setup nftables by first defining a table – we’ll just call it global – and then a chain, in which we’ll place our rules:

# nft add table inet global
# nft add chain inet global input { type filter hook input priority 0 \; }

(The inet part says this is for both ipv4 and ipv6.)

The add table command is simple enough. Then the chain input is added to the global table, and within the curly brackets we say we’re a filter chain that’s hooking onto the input hook, with a high priority. (the semi-colon is escaped when we use bash)

Next let’s add a rule to allow SSHon port 22:

# nft add rule inet global input tcp dport 22 accept

Again, we’re adding a rule to the global table and the input chain. We then use the accept on the tcp destination port 22. We can how list out commands:

# nft list table inet global
table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                tcp dport ssh accept 
        }
}

Let’s make sure we’re dropping everything else, by adding the drop command to the end of the list:

# nft add rule inet global input drop
# nft list table inet global
table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                tcp dport ssh accept 
                drop 
        }
}

Now if we try to reach apache we’ll find we can no longer. Let’s add a rule that allows it.

First we’ll find the handle with the -a param, then insert the http rule before that.

# nft list table inet global -a
table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                tcp dport ssh accept # handle 2
                drop # handle 3
        }
}
# nft insert rule inet global input position 3 tcp dport 80 accept
# nft list table inet global
table inet global {
        chain input {
                type filter hook input priority 0; policy accept;
                tcp dport ssh accept 
                tcp dport http accept 
                drop 
        }
}

There’s obviously plenty more you can do, but this just sets things up. This also doesn’t save the tables once the system goes down.

unix nftables

Page 1 of 1