Configuring nftables on Ubuntu 18.04

On the Ubuntu 18.04 virtual machines that we'll be using, the default nftables.conf file is nothing more than a meaningless placeholder. The file you need, which you'll copy over to replace the default nftables.conf file, is elsewhere. Let's check it out. 

First, we'll go into the directory where the sample configurations are stored and list the sample configuration files:

cd /usr/share/doc/nftables/examples/syntax
ls -l

You should see something similar to the following:

donnie@munin:/usr/share/doc/nftables/examples/syntax$ ls -l
total 60
-rw-r--r-- 1 root root 150 Feb 2 2018 arp-filter
-rw-r--r-- 1 root root 218 Feb 2 2018 bridge-filter
-rw-r--r-- 1 root root 208 Feb 2 2018 inet-filter
. . .
. . .
-rw-r--r-- 1 root root 475 Feb 2 2018 README
-rw-r--r-- 1 root root 577 Feb 2 2018 workstation
donnie@munin:/usr/share/doc/nftables/examples/syntax

If you view the contents of the workstation file, you'll see that it's the same as the old default nftables.conf file on Ubuntu 16.04.

Next, we'll copy the workstation file over to the /etc directory, changing its name to nftables.conf (note that this will overwrite the old nftables.conf file, which is what we want):

sudo cp workstation /etc/nftables.conf

For either Ubuntu 16.04 or Ubuntu 18.04, here's the breakdown of what you'll see in the /etc/nftables.conf file that you'll be using:

  • #!/usr/sbin/nft -f: Although you can create normal Bash shell scripts with nftables commands, it's better to use the built-in scripting engine that's included with nftables. That way, we can make our scripts more human-readable, and we don't have to type nft in front of everything we want to execute.
  • flush ruleset: We want to start with a clean slate, so we'll flush out any rules that may have already been loaded.
  • table inet filter: This creates an inet family filter, which works for both IPv4 and IPv6. The name of this table is filter, but it could just as well have been something a bit more descriptive.
  • chain input: Within the first pair of curly brackets, we have a chain called input. (Again, the name could have been something more descriptive.)
  • type filter hook input priority 0;: Within the next pair of curly brackets, we define our chain and list the rules. This chain is defined as a filter type. hook input indicates that this chain is meant to process incoming packets. Because this chain has both a hook and a priority, it will accept packets directly from the network stack.
  • Finally, we have the standard rules for a very basic host firewall, starting with the Input Interface (iif) rule, which allows the loopback interface to accept packets.
  • Next is the standard connection tracking (ct) rule, which accepts traffic that's in response to a connection request from this host.
  • Then, there's a commented-out rule to accept Secure Shell and both secure and nonsecure web traffic. ct state new indicates that the firewall will allow other hosts to initiate connections to our server on these ports.
  • The ipv6 rule accepts neighbor discovery packets, allowing IPv6 functionality.
  • The counter drop rule at the end silently blocks all other traffic and counts both the number of packets and the number of bytes that it blocks. (This is an example of how you can have one nftables rule perform multiple different actions.)

If all you need on your Ubuntu server is a basic, no-frills firewall, your best bet is to just edit this /etc/nftables.conf file so that it suits your own needs. For starters, let's set this up to match the setup that we created for the iptables section. In other words, let's say that this is a DNS server, and we need to allow connections to port 22 and port 53. Remove the comment symbol from in front of the tcp dport line, get rid of ports 80 and 443, and add port 53. The line should now look like this:

tcp dport { 22, 53 } ct state new accept

Note how you can use one nftables rule to open multiple ports.

DNS also uses port 53/udp, so let's add a line for it:

udp dport 53 ct state new accept

When you're only opening one port, you don't need to enclose that port number within curly brackets. When opening multiple ports, just include the comma-separated list within curly brackets, with a blank space after each comma, before the first element, and after the last element.

Load the configuration file and view the results:

donnie@ubuntu-nftables:/etc$ sudo systemctl reload nftables
donnie@ubuntu-nftables:/etc$ sudo nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
iif "lo" accept
ct state established,related accept
tcp dport { ssh, domain } ct state new accept
udp dport domain ct state new accept
icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
counter packets 1 bytes 32 drop
}
}
donnie@ubuntu-nftables:/etc$

The counter drop rule is another example of how an nftables rule can do multiple things. In this case, the rule drops and counts unwanted packets. So far, the rule has blocked one packet and 32 bytes. To demonstrate how this works, let's say that we want to make a log entry when packets are dropped. Just add the log keyword to the drop rule, like so:

counter log drop

To make these messages easier to find, add a tag to each log message, like this:

counter log prefix "Dropped packet: " drop

Now, when you need to peruse the /var/log/kern.log file to see how many dropped packets you've had, just search for the Dropped packet text string.

Now, let's say that we want to block certain IP addresses from reaching the Secure Shell port of this machine. Do so this, we can edit the file, placing a drop rule above the rule that opens port 22. The relevant section of the file would look like this:

tcp dport 22 ip saddr { 192.168.0.7, 192.168.0.10 } log prefix "Blocked SSH packets: " drop

tcp dport { 22, 53 } ct state new accept

After we reload the file, we'll be blocking SSH access from two different IPv4 addresses. Any attempts to log in from either of those two addresses will create a /var/log/kern.log message with the Blocked SSH packets tag. Note that we've placed the drop rule ahead of the accept rule because if the accept rule gets read first, the drop rule won't have an effect.

Next, we need to allow the desired types of ICMP packets, like so:

ct state new,related,established icmp type { destination-unreachable, time-exceeded, parameter-problem } accept

ct state established,related,new icmpv6 type { destination-unreachable, time-exceeded, parameter-problem } accept

In this case, you need separate rules for ICMPv4 and ICMPv6.

Finally, we'll block invalid packets by adding a new prerouting chain to the filter table, like so:

chain prerouting {
type filter hook prerouting priority 0;

ct state invalid counter log prefix "Invalid Packets: " drop

tcp flags & (fin|syn|rst|ack) != syn ct state new counter log drop
}

Now, we can save the file and close the text editor.

Due to formatting constraints, I can't show the entire completed file here. To see the whole file, download the code file from the Packt website, and look in the Chapter 4 directory. The example file you seek is the nftables_example_1.conf file.

Now, let's load up the new rules:

sudo systemctl reload nftables

Another really cool thing to note is how we've mixed IPv4 (ip) rules with IPv6 (ip6) rules in the same configuration file. Also, unless we specify otherwise, all the rules that we create will apply to both IPv4 and IPv6. That's the beauty of using an inet-type table. For simplicity and flexibility, you'll want to use inet tables as much as possible, rather than separate tables for IPv4 and IPv6.

Most of the time, when all you need is just a simple host firewall, your best bet would be to just use this nftables.conf file as your starting point, and edit the file to suit your own needs. However, there's also a command-line component that you may find useful.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.78.106