Table of Contents

Firewall Part 2

Firewall with iptables

In this part we will cover the topics listed below:

Resetting the Firewall (FLUSH)

Please make sure, that you have console access to your firewall, just in case ;-)

To reset the firewall, you will need to delete all configured rules and set the default policy to accept.

Let's check out, what the result of iptables -F is:

First we list all existing rules/policies

user@firewall01:~ $ sudo iptables -L
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

Now we invoke iptables -F:

user@firewall01:~ $ sudo iptables -F

If you were connected via SSH to the firewall, your connection to the firewall will be lost. This is due to the fact, that your default policy is still set to DROP and no additional rules are in place anymore, allowing SSH from other hosts.

Now you have two possibilities:

  1. Reboot the firewall, as we haven't saved the new configuration.
  2. Gain console access and set the default policy of INPUT & OUTPUT chains to ACCEPT

The commands for option 2 would be:

user@firewall01:~ $ sudo iptaples -P INPUT ACCEPT
user@firewall01:~ $ sudo iptaples -P OUTPUT ACCEPT

Now, access to the firewall should be possible again.

Conclusion: to flush the rules on the firewall from remote, you should first set the default policy to accept again:

user@firewall01:~ $ sudo iptaples -P INPUT ACCEPT
user@firewall01:~ $ sudo iptaples -P OUTPUT ACCEPT
user@firewall01:~ $ sudo iptaples -P FORWARD ACCEPT
user@firewall01:~ $ sudo iptables -F

Create first rules

Access to webserver

To test access to the webserver from the LAN PC, you can try to reach the URL http://192.168.39.2 in a browser.

not working

To access the webserver in the DMZ, we need to enable HTTP (TCP/80) on FORWARD chain.

user@firewall01:~ $ sudo iptables -A FORWARD -p TCP -i ens38 -o ens39 -d 192.168.39.2 --dport 80 -m conntrack --ctstate=NEW -j ACCEPT

Parameters are as follows:

-AAppend to chain
-pprotocol to tcp/udp/icmp…
-iIncoming interface
-oOutgoing interface
-dDestination
--dportPort
-mModule to be loaded (conntrack)
--ctstateConnection state
-jTarget

After this command, access to webserver is granted.

working

Delete rules

One way to delete a rule is to use the line number.

The parameter for iptables to show the line number is --line-number

user@firewall01:~ $ sudo iptables -L --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW
3    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
4    DROP       all  --  anywhere             anywhere             ctstate INVALID

Chain FORWARD (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    DROP       all  --  anywhere             anywhere             ctstate INVALID
4    ACCEPT     tcp  --  anywhere             192.168.39.2         tcp dpt:http ctstate NEW

Chain OUTPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
2    DROP       all  --  anywhere             anywhere             ctstate INVALID

One can also list configured rules for a specific chain:

user@firewall01:~ $ sudo iptables --line-numbers -L FORWARD
Chain FORWARD (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    DROP       all  --  anywhere             anywhere             ctstate INVALID
4    ACCEPT     tcp  --  anywhere             192.168.39.2         tcp dpt:http ctstate NEW

To delete the just created rule for the webserver, you need this command:

user@firewall01:~ $ sudo iptables -D FORWARD 4

It tells iptables to delete the 4th rule in FORWARD chain.

user@firewall01:~ $ sudo iptables --line-numbers -L FORWARD
Chain FORWARD (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    DROP       all  --  anywhere             anywhere             ctstate INVALID

And access to webserver is gone again

Basic logging

Now, that we have the first rule in place, you might want to see, if that rule gets hit by some traffic.

To log traffic for a specific rule, you need to add the same rule above with target LOG.

If you already added the rule for the webserver again, you need to put the logging rule above that one.

So this is the staus we are starting from.

user@firewall01:~ $ sudo iptables -L FORWARD --line-number
Chain FORWARD (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    DROP       all  --  anywhere             anywhere             ctstate INVALID
4    ACCEPT     tcp  --  anywhere             192.168.39.2         tcp dpt:http ctstate NEW

To add the logging rule above that line, we need to insert it at line 4 to shift existing rule to 5

user@firewall01:~ $ sudo iptables -I FORWARD 4 -p TCP -i ens38 -o ens39 -d 192.168.39.2 --dport 80 -j LOG --log-level info --log-prefix "IPT "

Additionally you can define the log-level and log-prefix.

--loglevelinfo
--log-prefix“IPT “

That makes live easier for the next step.

the result should look like this

user@firewall01:~ $ sudo iptables -L FORWARD --line-number
Chain FORWARD (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    DROP       all  --  anywhere             anywhere             ctstate INVALID
4    LOG        tcp  --  anywhere             192.168.39.2         tcp dpt:http LOG level info prefix "IPT "
5    ACCEPT     tcp  --  anywhere             192.168.39.2         tcp dpt:http ctstate NEW

After reloading the website in browser, you should see entries like this in /var/log/syslog

user@firewall01:~ $ sudo tail -f /var/log/syslog

May  7 07:22:44 firewall01 kernel: [ 1856.681823] IPT IN=ens38 OUT=ens39 MAC=00:0c:29:fc:1e:ee:00:0c:29:cc:c4:9f:08:00 SRC=192.168.38.2 DST=192.168.39.2 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=20834 DF PROTO=TCP SPT=55474 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0

To log all DROPed packages, we create a new chain and log everything. These commands need to be the last commands, as it appends a new target for the INPUT and OUTPUT chain, to forward all packets, which did not match a rule, to the LOGGING chain, log them and DROP them.

user@firewall01:~ $ sudo iptables -N LOGGING
user@firewall01:~ $ sudo iptables -A INPUT -j LOGGING
user@firewall01:~ $ sudo iptables -A LOGGING -j LOG --log-prefix "IPT I-Drop: " --log-level info
user@firewall01:~ $ sudo iptables -A LOGGING -j DROP
user@firewall01:~ $ sudo iptables -A OUTPUT -j LOGGING
user@firewall01:~ $ sudo iptables -A LOGGING -j LOG %%--%%log-prefix "IPT O-Drop: " --log-level info
user@firewall01:~ $ sudo iptables -A LOGGING -j DROP
iptables -N LOGGINGcreate a new chain
iptables -A INPUT -j LOGGINGappend logging rule to INPUT chain
iptables -A LOGGING -j LOG –log-prefix “IPT I-Drop: ” --log-level infowrite to log with params
iptables -A LOGGING -j DROPDROP packets

Redirect iptables logs

Log to seperate file

The default target for iptables log is /var/log/syslog. To save the logs to a different location, we need to create a new config file for rsyslog.

user@firewall01:~ $ sudo cat /etc/rsyslog.d/10-iptables.conf
:msg, contains, "IPT " /var/log/iptables.log
& stop

This file will tell rsyslog to redirect every log entry with 'IPT ' to /var/log/iptables.log and stop processing this line any further.

After adding this file, rsyslog needs to be restarted.

user@firewall01:~ $ sudo systemctl restart rsyslog && sudo systemctl status rsyslog
● rsyslog.service - System Logging Service
     Loaded: loaded (/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2022-05-07 08:01:23 UTC; 34ms ago
TriggeredBy: ● syslog.socket
       Docs: man:rsyslogd(8)
             man:rsyslog.conf(5)
             https://www.rsyslog.com/doc/
   Main PID: 1460 (rsyslogd)
      Tasks: 4 (limit: 992)
     Memory: 1.0M
        CPU: 15ms
     CGroup: /system.slice/rsyslog.service
             └─1460 /usr/sbin/rsyslogd -n -iNONE

Mai 07 08:01:23 firewall01 systemd[1]: Starting System Logging Service...
Mai 07 08:01:23 firewall01 rsyslogd[1460]: imuxsock: Acquired UNIX socket '/run/systemd/journal/syslog' (fd 3) from systemd.  [v8.2112.0]
Mai 07 08:01:23 firewall01 systemd[1]: Started System Logging Service.
Mai 07 08:01:23 firewall01 rsyslogd[1460]: rsyslogd's groupid changed to 113
Mai 07 08:01:23 firewall01 rsyslogd[1460]: rsyslogd's userid changed to 107
Mai 07 08:01:23 firewall01 rsyslogd[1460]: [origin software="rsyslogd" swVersion="8.2112.0" x-pid="1460" x-info="https://www.rsyslog.com"] start

Now you will have the logs in a different file:

user@firewall01:~ $ sudo tail -f /var/log/iptables.log 

May  7 08:04:39 firewall01 kernel: [ 4371.482415] IPT IN=ens38 OUT=ens39 MAC=00:0c:29:fc:1e:ee:00:0c:29:cc:c4:9f:08:00 SRC=192.168.38.2 DST=192.168.39.2 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=43447 DF PROTO=TCP SPT=55480 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0

Log to different hosts

To redirect the logs to a different log server, the config file needs to be altered as follows:

user@firewall01:~ $ sudo cat /etc/rsyslog.d/10-iptables.conf
:msg, contains, "IPT " @192.168.38.2:514
& stop       

And rsyslog needs to be restarted

On the destination host (log server) we need to enable the UDP listener on port 514

user@lan01:~ $ sudo vi /etc/rsyslog.conf

find these two lines and remove the comment sign

# module(load="imudp")
# input(type="imudp" port="514")

After that, rsyslog needs a restart.

Check, if UDP listener is started:

user@lan01:~ $ sudo netstat -tulpen | grep 514
udp        0      0 0.0.0.0:514    0.0.0.0:*      0     55105      3450/rsyslogd       
udp6       0      0 :::514         :::*           0     55106      3450/rsyslogd

If netstat is not installed on your system, try this command

user@lan01:~ $ sudo ss -lupn | grep 514
UNCONN 0      0            0.0.0.0:514        0.0.0.0:*    users:(("rsyslogd",pid=840,fd=5))        
UNCONN 0      0               [::]:514           [::]:*    users:(("rsyslogd",pid=840,fd=6))

Wonderful ;-)

On the log server, we want the logs in a different file then /var/log/syslog, so we create /etc/rsyslog.d/10-iptables.conf

user@lan01:~ $ sudo vi /etc/rsyslog.d/10-iptables.conf

Insert these two lines

:msg, contains, "IPT " /var/log/iptables.log
& stop

and restart rsyslog

As a result of all this, we should now see logs coming into /var/log/iptables.log.

End of part two

Firewall Part 1 - Firewall Part 2 - Firewall Part 3 - Firewall Part 4

Please stay tuned for the Third part, where we cover these topics:

The fourth part will cover: