Back to Table of Contents
UFW is an acronym for Uncomplicated Firewall. If UFW is uncomplicated, then what's a complicated firewall? UFW greatly simplifies iptables and ip6tables and is actually a wrapper around them, alleviating the potential missteps of making a mistake. Still not convinced? Then please reference these iptables examples.
By default, UFW is installed on Ubuntu but is disabled. UFW has configuration files that can be edited. These files are located in:
$ sudo ls /etc/ufw
But one notable file not in /etc/ufw
is in the /etc/default
folder.
Open it.
$ sudo vim /etc/default/ufw
We are not using IPv6, so are disabling it here.
# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback
# accepted). You will need to 'disable' and then 'enable' the firewall for
# the changes to take affect.
IPV6=no
When we send commands to UFW and UFW configures iptables on behalf of us, scripts are written to disk and can be found in:
$ sudo ls /lib/ufw
For what we are doing, we need not make changes to the generated iptables scripts. But for individuals interested in iptables, the scripts can be educational so after finishing these UFW examples, feel free to browse at the contents of the *.rules
files.
The help command.
$ sudo ufw help
Get the status. Append the verbose command for more information.
$ sudo ufw status
Status: inactive
By default on Ubuntu, UFW is disabled. Let's enable UFW.
$ sudo ufw enable
By default all incoming requests are blocked and all outgoing requests are allowed.
View the status.
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
We can also view the raw iptables.
$ sudo ufw show raw | less
For this scenario, both nginx and openssh-server have been installed.
We expect port 22 and 80 to be active. What other ports are open?
$ netstat -ntulp | grep LISTEN
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 10.10.11.20:5666 0.0.0.0:* LISTEN -
tcp6 0 0 :::111 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
Port 111 is for rcpbind and port 5666 is a Nagios NRPE client.
We also see IPv6 ports are active for SSH, nginx and rcpbind. We could disable these within the configurations but we won't do that since we've already disallowed IPv6 in UFW.
Allow SSH and http requests.
$ sudo ufw limit 22/tcp
$ sudo ufw allow 80/tcp
Note:
limit
refers to connection rate limiting to help prevent brute-force login attacks. Whenlimit
is used, by default the connection is allowed if there are no more than 6 connections within 30 seconds.
View the status as a numbered list.
$ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp LIMIT IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
Delete by number.
$ sudo ufw delete 2
Add it back.
$ sudo ufw allow 80/tcp
Delete all rules and disable UFW.
$ sudo ufw reset
Note: If the IPv6 value is set to "no" in
/etc/default/ufw
, resetting UFW causes no changes to this value; IPv6 is still disabled.
If this is a production server, especially facing the public internet, I would tighten the host firewall rules further.
- Disallow all outgoing
- Allow outgoing DNS to a DNS server
- Allow outgoing HTTP via a Proxy to the Ubuntu Servers defined in /etc/apt/sources.list
- Allow other outgoing protocols (eg Database Server, SMTP)
By default disallow outgoing traffic.
$ sudo ufw default deny outgoing
Open the outbound connection for DNS. Assume our DNS server is 192.168.1.40.
$ sudo ufw allow out to 192.168.1.40 port 53
UFW nor iptables filters by domain name. It is recommended to point UFW outbound rules to a proxy-server.
Open outbound http and https connections to the proxy server, which we assume is 192.168.1.41.
$ sudo ufw allow out to 192.168.1.41 port 80
$ sudo ufw allow out to 192.168.1.41 port 443
Open other outgoing protocols as needed.
In another scenario, a server has two network interfaces, typical for a DMZ'ed server.
- eth0: 192.168.1.3 belongs to the 192.168.1.0 subnet, which is the corporate network
- eth1: 10.1.1.3 belongs to the 10.1.1.0 subnet, which is the DMZ'ed network
The server I'm referencing has its interfaces set like this:
$ sudo cat /etc/network/interfaces
iface eth0 inet static
address 192.168.1.3
netmask 255.255.255.0
network 192.168.1.0
gateway 192.168.1.1
dns-nameservers 192.168.1.1
auto eth1
iface eth1 inet static
address 10.1.1.3
netmask 255.255.255.0
network 10.1.1.0
gateway 10.1.1.1
dns-nameservers 4.2.2.2
And routes look like this:
$ sudo route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 10.1.1.1 0.0.0.0 UG 0 0 0 eth1
192.168.1.0 * 255.255.255.0 U 0 0 0 eth0
10.1.1.0 * 255.255.255.0 U 0 0 0 eth1
Reset UFW.
$ sudo ufw reset
Enable UFW.
$ sudo ufw enable
Allow SSH from anyone connecting via eth0 interface and who is in the 192.168.1.0/24 subnet.
$ sudo ufw limit in on eth0 from 192.168.1.0/24 to any port 22 proto tcp
Allow HTTP from anyone connecting on on eth0 or eth1
$ sudo ufw allow 80/tcp
View the status.
$ sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp on eth0 LIMIT IN 192.168.1.0/24
[ 2] 80/tcp ALLOW IN Anywhere
For Dual NICS on a DMZ'ed production server, I would tighten the host firewall rules further. This is similar to how a single NIC was configured except the target destination might be on the internal interface or it might be on the public interface.
- Disallow all outgoing
- Allow outgoing DNS to an internal DNS server
- Allow outgoing HTTP via an internal Web-Proxy to the Ubuntu Servers defined in /etc/apt/sources.list
- Allow other outgoing protocols (eg Database Server, SMTP)
By default disallow outgoing traffic. This will deny on both interfaces, eth0 and eth1.
$ sudo ufw default deny outgoing
Open the outbound connection for DNS. Assume our DNS server is 192.168.1.40 and is accessed through interface eth0.
$ sudo ufw allow out on eth0 to 192.168.1.40 port 53
UFW nor iptables filters by domain name. As expressed before, it is recommended to point UFW outbound HTTP rules to a proxy-server.
Open outbound http and https connections to the internal web-proxy server, which we assume is 192.168.1.41 and is accessed through interface eth0.
$ sudo ufw allow out on eth0 to 192.168.1.41 port 80
$ sudo ufw allow out on eth0 to 192.168.1.41 port 443
# open outbound to a squid proxy server for updates
$ sudo ufw allow out on eth0 to 192.168.1.45 port 3128
Open other outgoing protocols as needed.
We aren't going to use the applications feature right now but it might be something to take advantage of in the future.
List the applications that UFW knows have been installed.
$ sudo ufw app list
The app list is generated by entries found in:
$ sudo ls /etc/ufw/applications.d/
Open one of the files listed in there to see how to create a new application.