The netfilter facility has been part of the Linux kernel since kernel version 2.4.
The basic ability of netfilter is packet filtering, network address translation, and port translation- it can be used to build firewall capability into the kernel - and this can be anything from a simple packet filtering firewall for desktop computers through firewalls for server protection and up to Enterprise level network firewalls.
There are several kernel modules which can be utilised to build up the packet filtering, NAT and PAT mechanisms - different distributions of Linux install their chosen modules - it may be possible to add more to get more specialised forms of packet filtering.
A significant group of modules are the conntrack modules which track outflowing packets and block or allow inflowing packets based on the tracking record - thus creating a stateful firewall.
In order to "programme" netfilter there are a number of userspace tools available - the original one was and still is iptables - this is a command line tool which can be used on the go, or can be used in shell scripts.
Iptables provides the ability to save a firewall configuration into a file, and then restore this configuration either manually through the command line or during the boot up of Linux.
There are three files recognised by the command line environment - they are frequently found in /sbin -
iptables
iptables-save
iptables-restore
They are used as follows
iptables is used in the command line instructions to create chains and rules
iptables-save is used to export the current firewall configuration to a text file
iptables-restore is used to import the previously saved firewall configuration from a text file
A firewall configuration set up using iptables is volatile - the configuration will be lost after a restart - hence the existence of iptables-save and iptables-restore.
----------------------
A newer command line tool is nftables which includes a wider range of commands available - it has been available since kernel version 3.13.
It provides a single unified interface to replace the four separate interfaces of iptables, ip6tables, arptables, and ebtables
It is now recommended that nftables is used in preference to iptables.
I haven`t ever used it so can`t add much more information.
----------------------
Another userspace tool for configuring netfilter firewalls is firewalld - this is a command line tool but it has a GUI tool associated with it.
Early versions of firewalld were based on iptables - newer versions are based on nftables.
My only experience of firewalld was trying to install it on the Linux installation on a Chromebook - the installation didn`t really go to plan, and it didn`t work once it was installed.
However it is the default firewall configuration tool on Linux distributions such as Red Hat, Centos, Fedora, and SUSE - and others.
----------------------
Another userspace tool for configuring netfilter firewalls is ufw - this is another command line tool, but there is an associated graphical userspace tool called gufw which talks to ufw and allows for the creation of simple rules.
Although it a command line tool, ufw is actually built on iptables - the commands used are ufw versions of the iptables commands.
However ufw is very different from iptables in that by default it creates an extensive framework of chains and rules, and any user created rules are slotted into this framework.
Developed by the developers of Ubuntu linux, ufw is the default userspace tool for configuring the firewall on the Ubuntu and Mint distributions of Linux, and is optional on Arch and Debian.
After installing ufw on the Linux installation on a Chromebook, I became increasingly concerned about ufw - and the thought that kept cropping up is obfuscation - and what is ufw actually doing.
Installing ufw on the Linux installation on the Chromebook was quite straighforward using apt - the command
sudo apt install ufw
was all that was required.
However the result is a bit surprising - as ufw had spread its tentacles through the Linux file structure - with files installed in the following locations -
/etc/ufw/ - 10 files in total - 2 init files, 2 config files, 6 ruleset files
/etc/default/ufw - 1 file - a high level configuration file
/lib/ufw/ - another 2 init files
In addition it set up the required boot up initialisation files in
/etc/init.d
and
/etc/rcS.d
So apt did a good job of installing ufw.
But does ufw really need
three configuration files
four initialisation files
six ruleset files
Again - it all rather points towards obfuscation.
After the installation of ufw on the Linux installation on the Chromebook I found that ufw had created something like 80 chains - over 40 for ipv4 and just under 40 for ipv6.
On a Linux Mint computer that uses ufw and is a few years old there are a similar number of chains for ipv4, so all these chains has been the norm for quite a while.
The default position is that many of these chains have no rules assigned to them - by definition a chain is a group of rules - so having chains with no rules is a bit of a puzzle as to why they exist.
But their existence does make it harder to try and work out the packet flow through the firewall.
Ufw is a command line interface, and as far as I can see there are no ufw commands which allow for the setting up of, or the removal of chains - so this chain framework can`t be altered through the command line or through gufw.
While I don`t claim to fully understand all the coding in this file, it seems that the chain structure is created by the initilisation file /lib/ufw/ufw-init-functions.
The default rules for IPv4 that ufw sets up are created by four different files -
/lib/ufw/ufw-init-functions
/etc/ufw/before.rules
/etc/ufw/after.rules
/etc/ufw/user.rules
The default rules for IPv6 that ufw sets up are created by four different files -
/lib/ufw/ufw-init-functions
/etc/ufw/before6.rules
/etc/ufw/after6.rules
/etc/ufw/user6.rules
Based on my previous experience of using ufw and gufw, any user created rules that were set up using gufw are added into the /etc/ufw/user.rules and /etc/ufw/user6.rules files.
However I can`t say with certainty that all rules created through gufw are entered into the /etc/ufw/user.rules and /etc/ufw/user6.rules files - it may depend on what the rules are doing.
----------------------
By default, ufw doesn`t use the built-in chains in the filter table of INPUT, OUTPUT, FORWARD to do any kind of packet filtering - each of these built-in chains is used as a router to access six ufw created chains in the ufw framework - these six ufw created chains are tried in sequence to see if there is a route through the firewall for each packet.
It isn`t a technique I have ever seen before - it does make it a lot more difficult to see the flow through the firewall for both wanted and unwanted packets - is this more obfuscation ?
There is a configuration setting that allows for the changing of some aspects of this default behaviour, so that the built-in chains are or can be used for packet filtering - however I haven`t done it and don`t know the full implications of doing it.
The more I looked into ufw the more I was concerned about what I was seeing.
My first concern is that ufw has no idea what the firewall is being used for - it could be a firewall for a desktop computer or laptop - it could be a firewall for a server - it could be a firewall that is part of a network infrastructure.
The requirements of a firewall for these different uses are quite different - so trying to create a firewall structure that can work in all these different situations doesn`t seem to be possible - either it will not work, or there will be unwanted routes through the firewall.
----------------------
The second ufw created chain that the built-in INPUT chain routes traffic to is the ufw-before-input chain.
The first rule in this chain concerns local produced traffic.
The second rule in this chain uses conntrack to identify related and established packets, and immediately passes all this traffic through and out of the firewall into the host machine with no other type of filtering.
Now stateful firewalls are a great invention, but they are not infallible - any malicious packets that can matched to a conntrack entry will be allowed in.
One of the powers of netfilter and iptables is the ability to have a chain that does some kind of packet filtering - then pass the traffic to another chain that does some other kind of filtering - then pass the traffic to another chain that does another kind of filtering - and so on.
So it is possible to create a firewall that does multiple levels of packet filtering as well as the stateful filtering - and ufw is not doing this.
One of the problems of stateful only filtering is that if some malware like ransomware gets installed on the machine, the firewall will let out the packets trying to set up a connection to a remote server and conntrack will record it, then the traffic from the server will be allowed back in through the firewall and the malware can then function as it was designed to do.
----------------------
Subsequent rules in the ufw-before-input chain allow several other types of packet through the firewall, such as multiple types of ICMP, DHCP, mDNS, and UPNP.
The last rule in the ufw-before-input chain is to route the remaining traffic to the ufw-user-input chain - this is the chain which receives the user created rules created either by gufw or through the command line.
So users who create new rules have no control over any of the above packet filtering as it has already happened before the user created rules have any effect.
I am still strugling to work out if any packet ever arrives in the ufw-user-input chain - and do rules added using gufw actually do anything.
----------------------
In the ufw-before-output chain there is a rule which allows all ESTABLISHED or RELATED packets out of the firewall - this happens before the link down to the ufw-user-output chain - this therefore comes before any user added rules in ufw-user-output.
So once again the question arises as to how much the rules added either by gufw or through the command line are going to be affected.
There is also the question as to why there is provision for stateful packet filtering on the output path of a firewall - it isn`t required or wanted on a firewall for a desktop machine.
----------------------
The ufw framework sets up a situation that some kinds of traffic are not logged - namely NetBIOS on ports 137, 138, 139, and TCP/IP MS Networking on port 445.
NetBIOS is an old and famously insecure network protocol that Microsoft just can`t seem to move away from - it is a much used way as a means of attacking computers.
TCP/IP MS Networking on port 445 is also insecure - the WannaCry and Nimbda malware use it.
Both can be used to attack computers from outside, as well as by malware already on the computer.
Even if you are diligent at looking at firewall logs you will not see anything about these type of packets because they are not getting logged.
----------------------
An advisory posted in January 2017 by US-CERT recommends blocking all versions of Server Message Block (SMB) at the network boundary by blocking TCP port 445 as well as the related protocols on UDP ports 137-138 and TCP port 139.
It is a fairly typical sort of advisory in the cyber security world.
Absolute packet blocking based on ports or addresses is a fairly standard requirement for network firewalls as well as server firewalls and firewalls for destop machines, but I don`t see how you can do this on ufw in its default configuration - the default configuration has too much emphasis on stateful packet filtering and speeding ESTABLISHED or RELATED packets through the firewall without any consideration for the port numbers or addresses of the packets.
Now if you use either gufw or the ufw command line instructions, any rules you add go into the user.rules file, and when ufw is loaded, the rules are put into either the ufw-user-input chain or the ufw-user-output chain as appropriate for the rule.
So as an example of the command line instructions, to block port 445 you could use the command
ufw deny 445
ufw assumes that this is to block incoming packets, and it ends up in the ufw-user-input chain.
You could be more specific and specify the direction -
ufw deny in 445
and the rule will go into the ufw-user-input chain.
The command
ufw deny out 445
will put the rule into the ufw-user-output chain.
Now I have already discussed my concerns about the ufw-user-input chain and the ufw-user-output chain, and pointed out that the links that pushes packets into these two chains are the last rules in the ufw-before-input chain and the ufw-before-output chain - by the time the packets arrive in the ufw-user-input chain or the ufw-user-output chain there has already been a succession of filtering done, including stateful packet filtering - so it is very clear that this would not be absolute blocking of the specified port - it is very conditional on whether or not the packet has already found a route through the firewall.
You could possibly add rules to the relevant default chain, INPUT or FORWARD - but that would entail some significant changes to the configuration of ufw.
Having spent a lot of time looking into the framework and the problems it causes, I wondered about how practical it would be to change the framework to turn ufw into a firewall that I believe is more effective in blocking unwanted packets.
NB - all that follows is for IPv4 only, I don`t need IPv6, and disabled it in ufw.
NB - this was a firewall specifically for a desktop or laptop - it would not be suitable for a firewall for a server, or for a network firewall.
NB - this configuration does not do any logging - logging is disabled in the ufw configuration file.
It required extensive modifications to three files in particular -
/etc/ufw/before.rules
/etc/ufw/after.rules
/lib/ufw/ufw-init-functions
The coding in the first two files is quite straightforward - they are really just lists of rules with numerous comments - so not hard to understand and modify.
The coding in the third file is a lot more complicated and there is a lot of it - I still don`t understand it all, but it wasn`t too difficult to pick out the various rules that I needed to change.
This file creates all the chains - I could have altered the number of chains being setup, but that would have made the modifications to the before.rules and the after.rules files more difficult.
So what I did was alter the way the chains are interconnected - and therefore created a new chain framework.
I ended up only using three of the many chains that the file ufw-init-functions creates - all the rest are just unused.
I continued the ufw practice of not using the three default chains - INPUT, OUTPUT, FORWARD - for any packet filtering.
The default policy for the INPUT, OUTPUT, and FORWARD chains is DROP.
The essence of the firewall is as follows :
All incoming traffic coming into the INPUT chain is passed to the ufw-before-input chain.
The ufw-before-input chain has a sequence of several rules which drop various kinds of unwanted packets.
The ufw-before-input chain then has a number of rules which pass packets with specific port numbers through to the ufw-after-chain.
All remaining packets are then dropped.
The ufw-after-input chain does stateful packet filtering and the wanted packets are accepted.
All blocked packets are then dropped.
All outgoing traffic arriving at the OUTPUT chain is passed to the ufw-before-output chain.
The ufw-before-output chain has multiple rules which do packet filtering based on port numbers - each rule has a target of ACCEPT.
All remaining packets are dropped.
The FORWARD chain is not used.
It took a while to get it all to work, but it does.
The configuration and initialisation of ufw is maintained - ufw can be disabled, enabled, and reloaded just as before.
However I am not sure if it is a good solution to the problems of the default installation of ufw - perhaps a better solution would be to remove ufw entirely and write an iptables shell script instead.
On older versions of ufw and/or on different distributions of Linux the default configurations of ufw load various conntrack kernel modules - the attack surface can be reduced if these modules are not required and the configuration is changed so that the modules are not loaded.
On newer versions of ufw the default configuration policy is that these extra kernel modules are not loaded - the configuration would need to be changed to load these extra modules if they are required.
ufw is developed by, and copyright of, Canonical Ltd.
To their credit, Canonical Ltd have declared ufw to be free software that can be redistributed or modified under the terms of the GNU Genaral Public License version 3 as published by the Free Software Foundation.
Canonical Ltd are the developers of Ubuntu Linux - and this is widely used in workstations and in servers.
So does this mean that there are Ubuntu based workstations and servers out there that have a default configuration of ufw - and the weaknesses that I have described above.
Mint Linux is based on Ubuntu, and uses ufw - so this applies to Mint Linux as well.
Debian allows for the installation of ufw through its package management system called apt - so there may well be Debian based workstations and servers out there using a default installation of ufw.
To a somewhat limited extent the configuration of ufw can be modified through various settings, but there are risks attached by doing so unless you have a good understanding of the default framework and the implications of changing the configuration.
And changing these settings doesn`t really alter the fundamental framework.
The documentation associated with ufw provides plenty of examples of ways to add rules to the default ufw configuration, but the documentation also suggests that this should not be done without a good understanding of what they do - which really means that you have to have a good understanding of the ufw framework and of iptables.
If you have a good understanding of iptables why use ufw ?