Chapter 4: Firewall Setup¶
Throughout this chapter you will need to be root or able to sudo
to become root.
As with any server, you need to make sure that it is secured from the outside world and on your LAN. While our example server only has a LAN interface, it is totally possible to have two interfaces, one each facing your LAN and WAN networks. While we cover iptables
rules in this procedure, we highly recommend using the firewalld
procedure instead (see the note below).
Firewall Set Up - iptables¶
A note regarding Rocky Linux 9.0
Starting with Rocky Linux 9.0, iptables
and all of the associated utilities are officially deprecated. This means that in future versions of the OS, perhaps as early as 9.1, they will disappear altogether. For this reason, you should skip down to the firewalld
procedure below before continuing.
It's actually a good idea to use firewalld
for Rocky Linux 8.6 as well, but we do offer you the option of using iptables
if you really want it.
Before continuing, you will want a firewall set up on your server. This example is using iptables and this procedure to disable firewalld. If you prefer to use firewalld, simply substitute in firewalld rules using the instructions below this section.
Create your firewall.conf script:
vi /etc/firewall.conf
We are assuming an LXD server on a LAN network of 192.168.1.0/24 below. Note, too, that we are accepting all traffic from our bridged interface. This is important if you want your containers to get IP addresses from the bridge.
This firewall script makes no other assumptions about the network services needed. There is an SSH rule to allow our LAN network IP's to SSH into the server. You can very easily have many more rules needed here, depending on your environment. Later, we will be adding a rule for bi-directional traffic between our production server and the snapshot server.
#!/bin/sh
#
#IPTABLES=/usr/sbin/iptables
# Unless specified, the defaults for OUTPUT is ACCEPT
# The default for FORWARD and INPUT is DROP
#
echo " clearing any existing rules and setting default policy.."
iptables -F INPUT
iptables -P INPUT DROP
iptables -A INPUT -i lxdbr0 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
/usr/sbin/service iptables save
Firewall Set Up - firewalld¶
For firewalld rules, we need to use this basic procedure or be familiar with those concepts. Our assumptions are the same as with the iptables rules above: LAN network of 192.168.1.0/24 and a bridge named lxdbr0. To be clear, you might have multiple interfaces on your LXD server, with one perhaps facing your WAN as well. We are also going to create a zone for the bridged and local networks. This is just for zone clarity sake, as the other names do not really apply. The below assumes that you already know the basics of firewalld.
firewall-cmd --new-zone=bridge --permanent
You need to reload the firewall after adding a zone:
firewall-cmd --reload
We want to allow all traffic from the bridge, so let's just add the interface, and then change the target from "default" to "ACCEPT" and we will be done:
Attention
Changing the target of a firewalld zone must be done with the --permanent option, so we might as well just enter that flag in our other commands as well and forgo the --runtime-to-permanent option.
Note
If you need to create a zone that you want to allow all access to the interface or source, but do not want to have to specify any protocols or services, then you must change the target from "default" to ACCEPT. The same is true of DROP and REJECT for a particular IP block that you have custom zones for. To be clear, the "drop" zone will take care of that for you as long as you aren't using a custom zone.
firewall-cmd --zone=bridge --add-interface=lxdbr0 --permanent
firewall-cmd --zone=bridge --set-target=ACCEPT --permanent
firewall-cmd --reload
firewall-cmd --zone=bridge --list-all
you should see something like the following:
bridge (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: lxdbr0
sources:
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
firewall-cmd --new-zone=local --permanent
firewall-cmd --reload
firewall-cmd --zone=local --add-source=127.0.0.1/8 --permanent
firewall-cmd --zone=local --set-target=ACCEPT --permanent
firewall-cmd --reload
firewall-cmd --zone=local --list all
which should show you something like this:
local (active)
target: ACCEPT
icmp-block-inversion: no
interfaces:
sources: 127.0.0.1/8
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Next we want to allow SSH from our trusted network. We will use the source IP's here, just like in our iptables example, and the built-in "trusted" zone. The target for this zone is already "ACCEPT" by default.
firewall-cmd --zone=trusted --add-source=192.168.1.0/24
firewall-cmd --zone=trusted --add-service=ssh
firewall-cmd --runtime-to-permanent
firewall-cmd --reload
trusted (active)
target: ACCEPT
icmp-block-inversion: no
interfaces:
sources: 192.168.1.0/24
services: ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
By default, the "public" zone is enabled and has SSH allowed. We don't want this. Make sure that your zones are correct and that the access you are getting to the server is via one of the LAN IP's (in the case of our example) and is allowed to SSH. You could lock yourself out of the server if you don't verify this before continuing. Once you've made sure you have access from the correct interface, remove SSH from the "public" zone:
firewall-cmd --zone=public --remove-service=ssh
Test access and make sure you aren't locked out. If not, then move your rules to permanent, reload, and list out zone "public" to be sure that SSH is removed:
firewall-cmd --runtime-to-permanent
firewall-cmd --reload
firewall-cmd --zone=public --list-all
There may be other interfaces on your server to consider. You can use built-in zones where appropriate, but if you don't like the names (they don't appear logical, etc.), you can definitely add zones. Just remember that if you have no services or protocols that you need to allow or reject specifically, then you will need to modify the zone target. If it works to use interfaces, as we've done with the bridge, you can do that. If you need more granular access to services, uses source IP's instead.
Author: Steven Spencer
Contributors: Ezequiel Bruni