This part will cover basic configuration of the firewall
This is not an in depth tutorial for all the tools or programms I use in this article.
Basic knowledge of the following is essential
This is the scenario I am going to use as example.
These machines can be setup in the virtualization environment of your choice.
+----------+
| Internet |
+----------+
|
|
|
+---------------+ +---------------+ +----------------+
| |192.168.39.0/24| |192.168.38.0/24| |
| DMZ Webserver |---------------| firewall |---------------| LAN PC |
| ububtu server |.2 .1| ubuntu server |.1 .2| ubuntu desktop |
+---------------+ +---------------+ +----------------+
Network configuration of dmz01
user@dmz01:~ $ sudo cat /etc/netplan/00-installer-config.yaml #This is the network config written by 'subiquity' network: version: 2 ethernets: ens33: dhcp4: false addresses: - 192.168.39.2/24 routes: - to: default via: 192.168.39.1 nameservers: addresses: [8.8.8.8]
Network configuration of fw01
user@fw01:~ $ sudo cat /etc/netplan/00-installer-config.yaml #This is the network config written by 'subiquity' network: ethernets: ens33: dhcp4: true version: 2
user@fw01:~ $ sudo cat /etc/netplan/10-ens38.yaml network: ethernets: ens38: dhcp4: false addresses: - 192.168.38.1/24 nameservers: addresses: - 8.8.8.8 - 8.8.4.4 version: 2
user@fw01:~ $ sudo cat /etc/netplan/20-ens39.yaml network: ethernets: ens39: dhcp4: false addresses: - 192.168.39.1/24 nameservers: addresses: - 8.8.8.8 - 8.8.4.4 version: 2
Network on LAN PC is done via Network Manager in GUI
To reach the DMZ or Internet from LAN, the firewall needs to be set up as a router.
pinging LAN interface of firewall is working:
user@lan01:~ $ sudo ping 192.168.38.1 -c 2 PING 192.168.38.1 (192.168.38.1) 56(84) bytes of data. 64 bytes from 192.168.38.1: icmp_seq=1 ttl=64 time=0.672 ms 64 bytes from 192.168.38.1: icmp_seq=2 ttl=64 time=1.15 ms --- 192.168.38.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1028ms rtt min/avg/max/mdev = 0.672/0.909/1.147/0.237 ms
pinging DMZ interface of firewall is also working:
user@lan01:~ $ sudo ping 192.168.39.1 -c 2 PING 192.168.39.1 (192.168.39.1) 56(84) bytes of data. 64 bytes from 192.168.39.1: icmp_seq=1 ttl=64 time=0.412 ms 64 bytes from 192.168.39.1: icmp_seq=2 ttl=64 time=0.468 ms --- 192.168.39.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1030ms rtt min/avg/max/mdev = 0.412/0.440/0.468/0.028 ms
but pinging the webserver in DMZ is not working, as ip forwarding is not enabled yet.
user@lan01:~ $ sudo ping 192.168.39.2 -c 2 PING 192.168.39.2 (192.168.39.2) 56(84) bytes of data. --- 192.168.39.2 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1023ms
We now need to enable ip forwarding (routing) on the firewall. There are different ways to achieve this, but I decided to go with the following:
Edit the file /etc/sysctl.conf
Search with your favorite editor for
# net.ipv4.ip_forward = 1
remove the '#' at beginning of line, or if the line is not present, add the line to that file
Save and close file
To enable the changes, you need to run the following command:
user@fw01:~ $ sudo sysctl -p /etc/sysctl.conf
After enabling ip forwarding, we are now able to ping the webserver on DMZ network.
pinging the webserver in DMZ should now work from LAN
user@lan01:~ $ sudo ping 192.168.39.2 -c 2 PING 192.168.39.2 (192.168.39.2) 56(84) bytes of data. 64 bytes from 192.168.39.2: icmp_seq=1 ttl=63 time=0.865 ms 64 bytes from 192.168.39.2: icmp_seq=2 ttl=63 time=0.914 ms --- 192.168.39.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.865/0.889/0.914/0.024 ms
pinging the LAN PC from webserver in DMZ should also work now:
user@lan01:~ $ sudo ping 192.168.38.2 -c 2 PING 192.168.38.2 (192.168.38.2) 56(84) bytes of data. 64 bytes from 192.168.38.2: icmp_seq=1 ttl=63 time=0.819 ms 64 bytes from 192.168.38.2: icmp_seq=2 ttl=63 time=0.761 ms --- 192.168.38.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1013ms rtt min/avg/max/mdev = 0.761/0.790/0.819/0.029 ms
To list all rules and policies, you need to invoke the following command as 'root'
user@fw01:~ $ sudo iptables -L
The output would look like this
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
As you can see, there are no rules yet defined and all policies are set to accept
To save the configured rules, we need the following package installed:
user@fw01:~ $ sudo apt install iptables-persistent
For saving the rules to get them loaded after reboot, this command needs to be triggered
user@fw01:~ $ sudo iptables-save | sudo tee /etc/iptables/rules.v4
As linux uses the lo interface for local processes to communicate to the outside and local processes, everything on FORWARD & INPUT chain should be allowed for interface lo
user@fw01:~ $ sudo iptables -A FORWARD -i lo -o lo -j ACCEPT user@fw01:~ $ sudo iptables -A INPUT -i lo -j ACCEPT
We need to ACCEPT all packets which are RELATED to, or belong to already ESTABLISHED connections.
INVALID packets shall be dropped.
user@hfw01:~ $ sudo iptables -A FORWARD -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT user@fw01:~ $ sudo iptables -A FORWARD -m conntrack --ctstate=INVALID -j DROP user@fw01:~ $ sudo iptables -A INPUT -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT userfw01:~ $ sudo iptables -A INPUT -m conntrack --ctstate=INVALID -j DROP user@fw01:~ $ sudo iptables -A OUTPUT -m conntrack --ctstate=RELATED,ESTABLISHED -j ACCEPT user@fw01:~ $ sudo iptables -A OUTPUT -m conntrack --ctstate=INVALID -j DROP
For administration purposes, this rule should be in place, before you set the policies to DROP, otherwise there would be no access to the firewall via network.
This rule will allow all connections on port 22 on any interface of the firewall. Later on, we will narrow this down to some management ips
user@fw01:~ $ sudo iptables -A INPUT -p tcp --dport=22 -m conntrack --ctstate=NEW -j ACCEPT
Now it's time to try saving the rules, to check if everything works as expected.
user@fw01:~ $ sudo iptables-save | sudo tee /etc/iptables/rules.v4
Make sure, that the file has the correct timestamp
user@fw01:~ $ sudo ls -l /etc/iptables/rules.v4 -rw-r--r-- 1 root root 1715 Mai 11 10:36 /etc/iptables/rules.v4
The file should look similar to this output, including all the changes made so far.
user@fw01:~ $ sudo cat /etc/iptables/rules.v4 # Generated by iptables-save v1.8.7 on Wed May 4 19:57:20 2022 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -m conntrack --ctstate INVALID -j DROP -A FORWARD -i lo -o lo -j ACCEPT -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -m conntrack --ctstate INVALID -j DROP -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -m conntrack --ctstate INVALID -j DROP COMMIT # Completed on Wed May 4 19:57:20 2022
After successful reboot, check, if all rules are still configured.
If so, we can set the default policy of all chains to drop.
user@fw01:~ $ sudo iptables -P INPUT DROP user@fw01:~ $ sudo iptables -P OUTPUT DROP user@fw01:~ $ sudo iptables -P FORWARD DROP
The output of
user@fw01:~ $ sudo iptables -L
should now look like this, where the default policy is set to DROP for all chains:
Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ctstate NEW ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DROP all -- anywhere anywhere ctstate INVALID Chain FORWARD (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DROP all -- anywhere anywhere ctstate INVALID Chain OUTPUT (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DROP all -- anywhere anywhere ctstate INVALID
Pinging the firewall or DMZ should not be possible anymore, but SSH to firewall should work.
Firewall Part 1 - Firewall Part 2 - Firewall Part 3 - Firewall Part 4
Please stay tuned for the second part, where we cover these topics:
The third part will cover these topics:
The fourth part will cover:
The fifth part will cover: