Make iptables configuration persistent using custom service file with additional features like configurable wait time, so you can safely interrupt execution and test mode that will disable firewall after defined period of time.
LSB init script
Create /etc/init.d/iptables-firewall
service file. Edit firewall_start
function to apply custom iptables configuration.
#!/bin/sh ### BEGIN INIT INFO # Provides: iptables-firewall # Required-Start: mountkernfs $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: iptables firewall # Description: local iptables firewall ### END INIT INFO . /lib/lsb/init-functions # Limit PATH PATH="/sbin:/usr/sbin:/bin:/usr/bin" # Time (in seconds) to change your mind and stop operation WAIT_FOR="15" # Time (in minutes) to wait before stop action (test action) TEST_FOR="5" # Source configuration if [ -f "/etc/default/iptables-firewall" ]; then . /etc/default/iptables-firewall fi # iptables configuration firewall_start() { # 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 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 } # internal # check if command is available check_for_command(){ command -v "$1" 1>/dev/null 2>&- } # check if commands are available check_commands(){ commands="iptables at" status=0 for command in $commands; do if ! check_for_command "$command"; then log_action_msg "Command $command is not available" status=1 fi done if [ "$status" -ne "0" ]; then log_action_begin_msg "Starting iptables firewall" log_action_end_msg 1 exit 1 fi } # check if user is root check_user_permissions() { if [ "$(id -u)" -ne "0" ]; then log_action_begin_msg "Insufficient permissions" log_action_end_msg 1 exit 1 fi } # wait for $WAIT_FOR seconds wait_before_execution() { log_action_msg "Waiting for $WAIT_FOR seconds" sleep $WAIT_FOR } # check environment check_commands check_user_permissions # execute action case "$1" in start|restart) wait_before_execution log_action_begin_msg "Starting firewall" firewall_stop firewall_start log_action_end_msg 0 ;; stop) wait_before_execution log_action_begin_msg "Stopping firewall" firewall_stop log_action_end_msg 0 ;; test) wait_before_execution log_action_msg "Scheduling iptables firewall to stop in $TEST_FOR minutes" sudo at now +2 minutes <<EOF $(readlink -f $0) stop EOF if [ "$?" -gt "0" ]; then log_action_begin_msg "Error: firewall will not stop in $TEST_FOR minutes" log_action_end_msg 1 exit 1 fi log_action_msg "Loading firewall rules" firewall_stop firewall_start log_action_begin_msg "Testing iptables firewall" log_action_end_msg 0 ;; show) iptables -L -v -n ;; show-nat) iptables -t nat -L -v -n ;; esac
Ensure that init script owned by root.
$ sudo chown root:root /etc/init.d/iptables-firewall
Ensure that script is executable.
$ sudo chmod 755 /etc/init.d/iptables-firewall
Enable service at boot.
$ sudo update-rc.d iptables-firewall defaults update-rc.d: using dependency based boot sequencing
Usage
Try to start firewall service as regular user.
$ /etc/init.d/iptables-firewall start [FAIL] Insufficient permissions...failed.
Try to start firewall service without at
command.
$ /etc/init.d/iptables-firewall start [info] Command at is not available. [FAIL] Starting iptables firewall...failed.
Stop firewall service.
$ sudo /etc/init.d/iptables-firewall stop [info] Waiting for 15 seconds. [ ok ] Stopping firewall...done.
Start firewall service.
$ sudo /etc/init.d/iptables-firewall start [info] Waiting for 15 seconds. [ ok ] Starting firewall...done.
Restart firewall service.
sudo /etc/init.d/iptables-firewall restart [info] Waiting for 15 seconds. [ ok ] Starting firewall...done.
Show current iptables configuration.
$ sudo /etc/init.d/iptables-firewall show Chain INPUT (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 ctstate INVALID 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 37 2524 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 0 0 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 23 2196 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 0 0 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 0 0 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 0 0 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 */ 0 0 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] " 0 0 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 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-out-drop] " 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Show current iptables configuration for nat
table.
$ sudo /etc/init.d/iptables-firewall show-nat Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
Test firewall service for 5 minutes.
$ sudo /etc/init.d/iptables-firewall test [info] Waiting for 15 seconds. [info] Scheduling iptables firewall to stop in 5 minutes. warning: commands will be executed using /bin/sh job 7 at Tue Jan 2 00:53:00 2018 [info] Loading firewall rules. [ ok ] Testing iptables firewall...done.