[clug] iptables-diff?

jm jeffm at ghostgun.com
Fri Jul 26 03:31:36 UTC 2019


For anyone interested this is what I ended up with...


Jeff.

-----

#!/bin/bash
################################################################################
# This scripts compares the loaded iptables rule set and that stored in the
# file /etc/iptables.rules. Indicating a difference, or not, by its exit
code.
# It only examines the rules for nat and filter. It ignores all
comments, and
# blank lines in the file. Only processing those lines which between
"*nat" and
#  "COMMIT", or "*filter" and "COMMIT" which start with "-A". It does not
# understand the rules so rules must be normalised to that outputed by
# iptables-save.
#
# Return
#   0 - There is a difference between the loaded rule set and that in
the file.
#   1 - No change detected
#
################################################################################

IPTABLES_FILE="/etc/iptables.rules"
VERBOSE=1

extract_chain_names () {
    # parameters: table, rules
    # returns: names
    table=$1
    rules=$2
    EXTRACT_NAMES='/^\*'"${table}"'/,/^COMMIT$/ {if (/^-A/)
{chain[$2]++}} END {for (c in chain) {print c}}'
    names=$(echo "${rules}" | awk "${EXTRACT_NAMES}" | sort)
    return 0
}

diff_chain () {
    # parameters: chain name, current rules, proposed rules
    name=$1
    current=$2
    proposed=$3

    cur_chain=$(echo "${current}"|awk '/^\-A '"${chain}"'/ {print $0}')
    prop_chain=$(echo "${proposed}" |awk '/^\-A '"${chain}"'/ {print $0}')
    if [ "${VERBOSE}" -eq "1" ]; then
    diff <( echo "${cur_chain}" ) <( echo "${prop_chain}" )
    else
    diff <( echo "${cur_chain}" ) <( echo "${prop_chain}" ) > /dev/null
    fi
}

# Proposed filter chains
proposed_rules=$(cat "${IPTABLES_FILE}")
current_rules=$(/sbin/iptables-save)

extract_chain_names "filter" "${proposed_rules}"
prop_filter_chains="${names}"

extract_chain_names "nat" "${proposed_rules}"
prop_nat_chains="${names}"

extract_chain_names "filter" "${current_rules}"
cur_filter_chains="${names}"

extract_chain_names "nat" "${current_rules}"
cur_nat_chains="${names}"

diff <(echo "${prop_filter_chains}") <(echo "${cur_filter_chains}") >
/dev/null
rc=$?

## Check if the same filter rules exist. If there is a change here then
iptables
## has changed

# diff Exit status is 0 if inputs are the same, 1 if different, 2 if
trouble.
# Should only change on exit code 1 (different)
if [ "$rc" -eq 1 ]; then
    exit 0
fi

## Check if the same nat rules exist. If there is a change here then
iptables
## has changed
diff <(echo "${prop_nat_chains}") <(echo "${cur_nat_chains}") > /dev/null
rc=$?

# Should only change on exit code 1 (different)
if [ "$rc" -eq 1 ]; then
    exit 0
fi

## Proceed to extracting each rule set.
for chain in $cur_filter_chains $cur_nat_chains; do
    diff_chain "${chain}" "${current_rules}" "${proposed_rules}"
    rc=$?
    if [ "$rc" -eq 1 ];then
    exit 0
    fi
done

exit 1




More information about the linux mailing list