Table of Contents

Firewall Part 1

Firewall with iptables

This part will cover basic configuration of the firewall

Prerequisite

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

Network drawing

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

Linux as Router

To reach the DMZ or Internet from LAN, the firewall needs to be set up as a router.

Ping Test LAN – DMZ

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

Enable ip forwarding

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.

Ping Test LAN – DMZ

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

Ping Test DMZ – LAN

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

List all iptables rules and policies

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

Install iptables-persistent

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

Allow all traffic from interface 'lo'

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

Anti lock out rule for SSH

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

Save created rules

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

Set default policy to ''DROP''

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

Test SSH connection to firewall

Pinging the firewall or DMZ should not be possible anymore, but SSH to firewall should work.

End of part one

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: