How to log dropped connections from iptables firewall using rsyslog

Log dropped connections from iptables firewall using rsyslog for further analysis and troubleshooting.

Configure rsyslog to use /var/log/firewall.log log file for firewall events.

$ cat << EOF | sudo tee /etc/rsyslog.d/firewall.conf
# Log messages generated by iptables firewall to file
:msg,contains,"[fw-" /var/log/firewall.log
# stop processing it further
& stop
EOF

Apply rsyslog configuration.

$ sudo systemctl restart rsyslog

Rotate log file to prevent to conserve disk space.

$ cat << EOF | sudo tee /etc/logrotate.d/firewall.conf
/var/log/firewall.log
{
  rotate 7
  daily
  missingok
  notifempty
  delaycompress
  compress
  postrotate
  invoke-rc.d rsyslog rotate > /dev/null
  endscript
}
EOF

Create iptables firewall that will allow already established connections, incoming icmp and ssh, outgoing icmp, ntp, dns, ssh, http and https. It will also log invalid packets and those dropped ones.

# Flush rules and delete custom chains
iptables -F
iptables -X

# Define chain to allow particular source addresses
iptables -N chain-incoming-ssh 
iptables -A chain-incoming-ssh -s 192.168.1.149 -j ACCEPT -m comment --comment "local access"
iptables -A chain-incoming-ssh -p tcp --dport 22 -j LOG  --log-prefix "[fw-inc-ssh] " -m limit --limit 6/min --limit-burst 4
iptables -A chain-incoming-ssh -j DROP

# Define chain to log and drop incoming packets
iptables -N chain-incoming-log-and-drop
iptables -A chain-incoming-log-and-drop -j LOG --log-prefix "[fw-inc-drop] " -m limit --limit 6/min --limit-burst 4
iptables -A chain-incoming-log-and-drop -j DROP

# Define chain to log and drop outgoing packets
iptables -N chain-outgoing-log-and-drop
iptables -A chain-outgoing-log-and-drop -j LOG --log-prefix "[fw-out-drop] " -m limit --limit 6/min --limit-burst 4 
iptables -A chain-outgoing-log-and-drop -j DROP

# Drop invalid packets
iptables -A INPUT -m conntrack --ctstate INVALID -j chain-incoming-log-and-drop

# Accept everthing on loopback
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# ACCEPT incoming packets for established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Accept incoming ICMP
iptables -A INPUT -p icmp -j ACCEPT

# Accept incoming SSH
iptables -A INPUT -p tcp --dport 22 -j chain-incoming-ssh

# Accept outgoing packets for established connections
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Accept outgoing DNS
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

# Accept outgoing NTP
iptables -A OUTPUT -p tcp --dport 123 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

# Accept outgoing HTTP/S
iptables -A OUTPUT -p tcp --dport 80  -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT

# Accept outgoing SSH
iptables -A OUTPUT -p tcp --dport 22  -j ACCEPT

# Accept outgoing ICMP
iptables -A OUTPUT -p icmp -j ACCEPT

# Log not accounted outgoing traffic
iptables -A OUTPUT -j chain-outgoing-log-and-drop

# Log not accounted forwarding traffic
iptables -A FORWARD -j chain-incoming-log-and-drop

# Drop everything else
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  DROP

List all firewall rules to verify that executed commands are applied as desired.

$ sudo iptables -L -v -n
Chain INPUT (policy DROP 14 packets, 756 bytes)
 pkts bytes target                       prot opt in     out     source               destination         
    0     0 chain-incoming-log-and-drop  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    0     0 ACCEPT                       all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
  515  188K ACCEPT                       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT                       icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    1    60 chain-incoming-ssh           tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target                       prot opt in     out     source               destination         
    0     0 chain-incoming-log-and-drop  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target                       prot opt in     out     source               destination         
    0     0 ACCEPT                       all  --  *      lo      0.0.0.0/0            0.0.0.0/0           
  380 70413 ACCEPT                       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT                       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    8   530 ACCEPT                       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT                       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:123
    0     0 ACCEPT                       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:123
    2   120 ACCEPT                       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
    0     0 ACCEPT                       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443
    0     0 ACCEPT                       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
    0     0 ACCEPT                       icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    2   120 chain-outgoing-log-and-drop  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-incoming-log-and-drop (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 6/min burst 4 LOG flags 0 level 4 prefix "[fw-inc-drop] "
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-incoming-ssh (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       192.168.1.149        0.0.0.0/0            /* local access */
    1    60 LOG        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 limit: avg 6/min burst 4 LOG flags 0 level 4 prefix "[fw-inc-ssh] "
    1    60 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain chain-outgoing-log-and-drop (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   120 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 6/min burst 4 LOG flags 0 level 4 prefix "[fw-out-drop] "
    2   120 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Sample log entries.

$ sudo tail /var/log/firewall.log 
Dec 31 13:48:24 debian kernel: [29030.017110] [fw-out-drop] IN= OUT=eth0 SRC=192.168.1.131 DST=84.16.240.28 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=63807 DF PROTO=TCP SPT=34610 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 
Dec 31 13:48:25 debian kernel: [29031.040102] [fw-out-drop] IN= OUT=eth0 SRC=192.168.1.131 DST=84.16.240.28 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=63808 DF PROTO=TCP SPT=34610 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 
Dec 31 13:48:29 debian kernel: [29034.614317] [fw-inc-ssh] IN=eth0 OUT= MAC=52:54:00:26:97:1f:b8:27:eb:0e:4e:b6:08:00 SRC=192.168.1.252 DST=192.168.1.131 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=25292 DF PROTO=TCP SPT=55354 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0 

About Milosz Galazka

Milosz is a Linux Foundation Certified Engineer working for a successful Polish company as a system administrator and a long time supporter of Free Software Foundation and Debian operating system. He is also open for new opportunities and challenges.