Workshop: Lock down your Linux system with Firewalld and OpenSnitch

Double Protection

© Lead Image courtesy of Sofia Tolstaya, the author's 10-year-old daughter

© Lead Image courtesy of Sofia Tolstaya, the author's 10-year-old daughter

Article from Issue 232/2020

For maximum security, you'd better watch traffic in both directions. This hands-on workshop takes you through the steps of setting up firewalls for outgoing as well as incoming traffic.

Linux has a great selection of firewalls for securing stand-alone computers or whole networks. Small LANs usually depend on small routers for security. But what if your Linux machine is exposed on the network and you don't have control over the upstream router or gateway? What if you're working behind one of the millions of smaller routers with out-of-date firmware or missing security patches?

If you're really serious about building a perfectly secure, network-attached Linux workstation, you'll need to fortify the system from two directions: with a host-based firewall for managing incoming connections and with a per-application firewall for controlling outbound traffic. This hands-on workshop will show you how to fortify your system using Firewalld and the OpenSnitch application firewall.

Limiting the Incoming Flow

Network security starts with limiting access to your host from the outer world. One of the most advanced and popular tools for limiting incoming traffic is Firewalld [1], a modern and flexible firewall that replaced the legacy Iptables software a few years ago. Firewalld was introduced as a default network security solution in Fedora 18 and RHEL 7, and consequently, in CentOS 7 as well. The Firewalld firewall is now included in many other mainstream Linux distributions, such as openSUSE and Arch.

Firewalld has many benefits over Iptables and other old-fashioned tools for accessing the netfilter feature of the Linux kernel. Previous firewall tools required manual and precise rules for blocking or allowing certain ports and network addresses, which were not trivial and caused a lot of headache once the host's network configuration changed. Firewalld is more flexible, allowing you to add system services to zones and assign a zone to a network interface. A user does not need to know which port is associated with a service because Firewalld comes with over 140 presets for many, if not all, Linux services.

By assigning services to zones, users can create a custom set of rules for various use cases and conditions. By default, Firewalld has 9 zones that differ by the level of trust to a network. Several interfaces can be assigned to a zone, but only one zone can be assigned to an interface. Firewalld applies all changes on the fly, so you won't need to restart when changing zones, services, or ports. Although Firewalld has no mechanism of auto-changing zones, you can use the zone system to adapt to changing network conditions. For instance, a laptop connected to a wired Ethernet network would probably use the eno1 interface, and a public Wi-Fi interface might use wlan0. You could assign each of these interfaces to different zones: eno1 could be in the work zone, which includes SSH access, and wlan0 will belong to the public zone, which does not.

Firewalld (Figure 1) has a couple of graphical front-ends, specifically a GTK3-based GUI, which you will find in Gnome Software, and a Qt5-based interface bundled with Yast in openSUSE and SuSE Linux Enterprise. For this article, I will use the command-line utility known as firewall-cmd, which works everywhere (Figure 2).

Figure 1: By default, Firewalld is very distrustful, but you can whitelist services that you want to allow.
Figure 2: Firewall-cmd is an easy and powerful command-line tool.

Check to see if the firewall is running:

$ sudo firewall-cmd --state

If it is not, enable and launch it with:

$ sudo systemctl enable firewalld && sudo systemctl start firewalld

Say you want to open TCP port 80 to allow access to your network's web server from remote hosts:

$ sudo firewall-cmd --add-port=80/tcp

If no zone is specified, the preceding command applies to the current zone, which should be public according to the Firewalld defaults. If you are unsure, you can check the default zone with:

$ sudo firewall-cmd --get-default-zone

By default, all network interfaces are assigned to the default zone. You can find out what zones your current network interface has been assigned with the following command:

$ sudo firewall-cmd --get-active-zones

Assume the current zone is public. The following command would allow you to view the zone configuration:

$ sudo firewall-cmd --zone=public --list-all

The output will probably list dhcpv6-client as the only allowed service. Most of the other parameters for public are empty by default, which means that nothing else is allowed. Not a good zone for further experiments in our sandbox. To transition the current network interface to another zone, enter:

$ sudo firewall-cmd --zone=trusted --change-interface=eno1

Note that changing zones changes the set of services that will be allowed. To tailor the zone for the needs of your network, you might wish to add services to the zone. For a list of available services, enter:

$ sudo firewall-cmd --get-service

You can also examine the contents of  usr/lib/firewalld/services for a list of available services. Suppose I want to add the IPP service to the home zone for enabling remote printing to the CUPS server via the Internet Printing Protocol:

$ sudo firewall-cmd --zone=home --add-service=ipp

Other use cases require accessing your home PC from the outer world for the sake of remote administration, granting access to BitTorrent downloads, and other common scenarios.


On small home LANs, a home router usually performs network address translation, but it is also possible to set up a Linux computer as a router and then configure Firewalld to perform port forwarding and masquerading for incoming connections.

A router would need two network interfaces: one for the Internet (eno0) and another for the internal LAN (eno1).

To assign different zones to the two interfaces, enter:

$ sudo nmcli c mod eno0 internet
$ sudo nmcli c mod eno1 lan
$ sudo firewall-cmd --get-active-zones

Now that the two connections belong to different Firewalld zones, you can start masquerading. The following commands enable the masquerade feature for the internet zone and then forward all remote SSH connections from port 22 to port 2222 of another machine ( inside the internal LAN:

$ sudo firewall-cmd --zone=internet --add-masquerade
$ sudo firewall-cmd --zone=internet --add-forward-port=port=22:proto=tcp:toport=2222:toaddr=

So far all the changes to the Firewalld configuration are temporary and will be lost after the Firewalld service is restarted. To make the changes permanent, add the --permanent parameter to every firewall-cmd command that changes something. It is also possible to save the current setup by converting it to the permanent configuration:

$ sudo firewall-cmd --runtime-to-permanent

A reverse action is sometimes also required: changes made with the --permanent parameter are saved but not applied immediately (which is not obvious). To make permanent changes work for the current session, use the command:

$ sudo firewall-cmd --reload

Firewalld also has some dedicated features for handling outgoing connections (use --direct and --add-rule options), but another tool called OpenSnitch offers a more user-friendly solution for managing outgoing traffic.

Controlling Outgoing Traffic

For security and privacy reasons, many users wish to know what outgoing connections the applications you use and websites you visit want to establish from your machine. Various apps and APIs might try to launch outgoing connections from your computer, including cloud storage clients, weather widgets, and big data collectors.

OpenSnitch [2] is designed to track all outgoing network connections. It is an open source project inspired by Little Snitch, an application firewall for Macs. The value of OpenSnitch is that it reveals all such background network activity and lets you explicitly allow or block each connection (Figure 3).

Figure 3: OpenSnitch reveals background network activity and lets you allow or deny each connection.

OpenSnitch is a work in progress, which is why it is not yet packaged for easy installation in most Linux distributions. Despite that, the software is stable enough and fits well into typical home or office usage scenarios. The steps for installing OpenSnitch are the same for any Linux flavor. If you're working in a recent Ubuntu version, the commands would look like Listing 1.

Listing 1

Setting Up OpenSnitch

$ mkdir -p ~/go/bin && export GOPATH=~/go
$ export PATH=$PATH:$GOPATH/bin
$ sudo apt-get install git libnetfilter-queue-dev libpcap-dev protobuf-compiler python3-pip golang-go
$ go get
$ go get -u
$ $GOPATH/src/
$ python3 -m pip install --user grpcio-tools
$ go get
$ cd $GOPATH/src/

You will probably need to comment out the first line in the ui/requirements.txt file as long as the plain grpcio component (not the one with -tools) is only needed for Python2 and not for the newer Python3. Then complete the installation with:

$ make && sudo make install

OpenSnitch provides a Systemd service that you will need to activate upon startup:

$ sudo systemctl enable opensnitchd && sudo systemctl start opensnitchd

Fire up the OpenSnitch graphical front-end with:

$ opensnitch-ui

A new icon should appear in the system tray area. After any process initiates a connection to a TCP or UDP port, OpenSnitch will throw up a warning window. You will have 15 seconds to review the source and target IP addresses, the process name, port ID, and user ID and make a decision whether you allow or deny the connection. By default, if time runs out and you do nothing, OpenSnitch will allow the connection. Of course, in many situations, you simply need more time to decide what to do with an OpenSnitch warning. Extend the time to any other length by editing the ~/.opensnitch/ui-config.json file.

Although OpenSnitch may look a bit paranoid at first, remember that it was designed to distrust everything. Frequent warnings indicate that OpenSnitch is in the training mode and it's up to you to decide if you will allow or block each connection once, for the current session, or forever.

Using the Firefox web browser for daily surfing reveals that the systemd-resolved service consumes UDP port 53 for DNS name resolution, Mozilla browser integration uses Python3.x to communicate with on TCP 443, Ubuntu's version of NetworkManager runs a custom connectivity checker using TCP 80 and that's almost it – nothing really bad or suspicious. If you allow these typical connections from the very beginning, you will for the most part be able to surf the web without further annoyances.

OpenSnitch will turn up a lot more when you are dealing with desktop integration APIs, weather services, online accounts, remote cloud connectors, and other services. If you run Skype, Dropbox, Google Drive, Windows apps via Wine, or any proprietary software, it always makes sense to keep OpenSnitch up and running. Even if the extended time period is not enough and you prefer to apply OpenSnitch actions once or for this session only, it is easy to trigger the alarm again:

$ sudo systemctl restart opensnitchd

The restart only applies to the per-application firewall and does not interfere with other network processes.

Saving your response as forever creates an appropriate JSON file under /etc/opensnitchd/rules. Just as with Iptables rules, you can modify OpenSnitch rules and even add your own.

OpenSnitch will help you understand how various applications and system services use the network. Many of these services are perfectly normal; the key is to look for rare or unusual or unfamiliar services that might be behaving strangely. Nevertheless, the offending service does not have to be that exotic – you'll find examples of misbehaving Gnome Shell extensions and KDE Plasmoids that somehow want to connect to remote hosts, and you definitely have the right to know what is happening.

OpenSnitch is not just safeguarding software; it diligently collects statistics and keeps track of past incidents. Right-click on the application's icon in the tray and select Statistics. A new window will appear with several tabs for viewing network connection statistics (Figure 4). By default, statistics display on the General tab as a table with timestamps, processes, destinations, protocols, and actions. This tab, along with others (Hosts, Processes, Addresses, Ports and Users), has a small button near the top-right corner of the window that exports the current view to CSV format for further usage. With the help of Statistics, it is possible to analyze past events that you may not have noticed at the time they occurred.

Figure 4: Statistics are everything. See the whole outgoing network activity log within a single tab.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Getting to Know Firewalld

    Managing a firewall can be a hassle, but it’s worse to manage a breach because you didn’t have one.

  • FOSSPicks

    Graham looks at Krita 4.0, FreeTube 0.2.0, OpenSnitch, Yoda, Citybound, GZDoom, and much more!

  • FOSSPicks

    Graham recently found the perfect use for his old Nintendo DS Lite. Thanks to having exactly the same screen resolution, it now runs the brilliant ZXDS Sinclair ZX Spectrum emulator.

  • Cockpit

    Meet Cockpit, an easy management tool that lets you watch your Linux servers from a convenient, web-based interface.

  • Keep All Your Linux Servers in Check

    Use the browser-based Cockpit tool to monitor and administer multiple Linux servers without leaving your desk.

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95