Make iptables configuration persistent using systemd file with additional possibility to disable firewall after defined period of time.
Shell script
Create /sbin/iptables-firewall.sh
shell script. Edit firewall_start
function to apply custom iptables configuration.
#!/bin/bash # Configure iptables firewall # Limit PATH PATH="/sbin:/usr/sbin:/bin:/usr/bin" # iptables configuration firewall_start() { # 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 everything 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 } # clear iptables configuration firewall_stop() { iptables -F iptables -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT } # execute action case "$1" in start|restart) echo "Starting firewall" firewall_stop firewall_start ;; stop) echo "Stopping firewall" firewall_stop ;; esac
Ensure that shell script owned by root.
$ sudo chown root:root /sbin/iptables-firewall.sh
Ensure that script is executable.
$ sudo chmod 750 /sbin/iptables-firewall.sh
systemd configuration
Create iptables-firewall
service.
$ cat << EOF | sudo tee /etc/systemd/system/iptables-firewall.service [Unit] Description=iptables firewall service After=network.target [Service] Type=oneshot ExecStart=/sbin/iptables-firewall.sh start RemainAfterExit=true ExecStop=/sbin/iptables-firewall.sh stop StandardOutput=journal [Install] WantedBy=multi-user.target EOF
Create iptables-firewall-test
service.
$ cat << EOF | sudo tee /etc/systemd/system/iptables-firewall-test.service [Unit] Description=iptables firewall service test BindsTo=iptables-firewall.service After=iptables-firewall.service [Service] Type=oneshot ExecStart=/usr/bin/systemd-run --on-active=180 --timer-property=AccuracySec=1s /bin/systemctl stop iptables-firewall.service StandardOutput=journal [Install] WantedBy=multi-user.target EOF
Reload systemd manager configuration.
$ sudo systemctl daemon-reload
Usage
Test iptables firewall using iptables-firewall-test
service.
$ sudo systemctl start iptables-firewall-test
It will start iptables-firewall
service.
$ sudo systemctl status iptables-firewall
● iptables-firewall.service - iptables firewall service Loaded: loaded (/etc/systemd/system/iptables-firewall.service; disabled; vendor preset: enabled) Active: active (exited) since Tue 2018-01-02 07:14:42 CST; 2min 32s ago Process: 772 ExecStart=/sbin/iptables-firewall.sh start (code=exited, status=0/SUCCESS) Main PID: 772 (code=exited, status=0/SUCCESS) Tasks: 0 (limit: 4915) CGroup: /system.slice/iptables-firewall.service Jan 02 07:14:41 debian systemd[1]: Starting iptables firewall service... Jan 02 07:14:41 debian iptables-firewall.sh[772]: Starting firewall Jan 02 07:14:42 debian systemd[1]: Started iptables firewall service.
It will also schedule temporary timer to stop iptables-firewall
service after 3 minutes.
$ sudo systemctl list-timers
NEXT LEFT LAST PASSED UNIT Tue 2018-01-02 07:17:42 CST 2min 21s left n/a n/a run-rb4c64fbca4ee4c Tue 2018-01-02 10:58:01 CST 3h 42min left Mon 2018-01-01 18:54:12 CST 12h ago apt-daily.timer Wed 2018-01-03 06:29:06 CST 23h left Tue 2018-01-02 06:10:06 CST 1h 5min ago apt-daily-upgrade.t Wed 2018-01-03 06:59:14 CST 23h left Tue 2018-01-02 06:59:14 CST 16min ago systemd-tmpfiles-cl 4 timers listed. Pass --all to see loaded but inactive timers, too.
Enable iptables-firewall
service at boot.
$ sudo systemctl enable iptables-firewall
Start iptables-firewall
service.
$ sudo systemctl start iptables-firewall
There is nothing more than standard systemd operations. Use iptables-firewall-test
service to test iptables configuration, but remember that it will stop iptables-firewall
service after 3 minutes.