#!/bin/sh
### BEGIN INIT INFO
# Provides:          iptables
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# X-Start-Before:    fail2ban
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Applies iptables ruleset
# Description:       Applies all rules found in /etc/iptables.d
#                    and saves/restores previous status
### END INIT INFO

# Originally written by:
#   Nico Schottelius
#   Zürisee, Mon Sep  2 18:38:27 CEST 2013
#
# 2013 Nico Schottelius (nico-cdist at schottelius.org)
# 2020 Matthias Stecher (matthiasstecher at gmx.de)
#
# This file is distributed with cdist and licenced under the
# GNU GPLv3+ WITHOUT ANY WARRANTY.


# Read files and execute the content with the given commands
#
# Arguments:
#  1:    Directory
#  2..n: Commands which should be used to execute the file content
gothrough() {
    cd "$1" || return
    shift

    # iterate through all rules and continue if it's not a file
    for rule in *; do
        [ -f "$rule" ] || continue
        echo "Appling iptables rule $rule ..."

        # execute it with all commands specificed
        ruleparam="$(cat "$rule")"
        for cmd in "$@"; do
            # Command and Rule should be split.
            # shellcheck disable=SC2046
            command $cmd $ruleparam
        done
    done
}

# Shortcut for iptables command to do IPv4 and v6
# only applies to the "reset" target
iptables() {
    command iptables "$@"
    command ip6tables "$@"
}

basedir=/etc/iptables.d
status4="${basedir}/.pre-start"
status6="${basedir}/.pre-start6"

case $1 in
    start)
        # Save status
        iptables-save > "$status4"
        ip6tables-save > "$status6"

        # Apply our ruleset
        gothrough "$basedir"     iptables
        #gothrough "$basedir/v4"  iptables  # conflicts with $basedir
        gothrough "$basedir/v6"  ip6tables
        gothrough "$basedir/all" iptables  ip6tables
    ;;

    stop)
        # Restore from status before, if there is something to restore
        if [ -f "$status4" ]; then
            iptables-restore < "$status4"
        fi
        if [ -f "$status6" ]; then
            ip6tables-restore < "$status6"
        fi
    ;;
    restart)
        "$0" stop &&  "$0" start
    ;;
    reset)
        for table in INPUT FORWARD OUTPUT; do
            iptables -P "$table" ACCEPT
            iptables -F "$table"
        done
        for table in PREROUTING POSTROUTING OUTPUT; do
            iptables -t nat -P "$table" ACCEPT
            iptables -t nat -F "$table"
        done
    ;;
esac
