Add os-iptables-stateful script for managing iptables

Applies iptables configuration based on an input file and the current
iptables state. This script is used to perform idempotent operations,
eg to prevent adding duplicate rules.

Sample input:

-N stunnel-INPUT
-A stunnel-INPUT -p tcp -m tcp --dport 4433 -j REJECT
-A stunnel-INPUT -j RETURN
-I INPUT -p tcp -j stunnel-INPUT

Unlike 'iptables-restore --noflush' the script is idempotent.

Change-Id: I8eef1361ea90647507cf596f7bfc81815e32a96e
Partially implements: blueprint os-iptables-scripts
This commit is contained in:
Stuart McLaren 2014-04-23 14:13:36 +00:00
parent 2cedc6f99c
commit 63fb151eb7
1 changed files with 103 additions and 0 deletions

View File

@ -0,0 +1,103 @@
#!/bin/bash
# Copyright 2014 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
set -eu
set -o pipefail
SCRIPT_NAME=$(basename $0)
function show_usage () {
cat << EOF
usage: '$SCRIPT_NAME INPUTFILE'
Script to configure iptables.
Positional arguments:
INPUTFILE File containing required configuration details.
An input file is parsed and iptables rules are configured accordingly.
Rules are applied idempotently (ie duplicate rules are not created)
and non-destructively (existing rules are not deleted/recreated).
The input file is essentially set of iptables command arguments, with
the restriction that each line should start with one of:
'-A', '-D', '-I', '-N', '-F' or '-X'.
Lines beginning with '#' and lines containing only whitespace are ignored.
Sample input file contents:
-N stunnel-INPUT
-A stunnel-INPUT -p tcp --dport 5000 -j REJECT
-A stunnel-INPUT -j RETURN
-I INPUT -p tcp -j stunnel-INPUT
EOF
exit 1
}
function check() {
check_chain_name ${@:2}
iptables $@ > /dev/null 2>&1
}
function check_chain_name() {
# Verify that a chain name is supplied
grep -qEv '^[[:space:]]*-|^[[:space:]]*$' < <(echo $@)
if [ $? -ne 0 ]; then
echo "$SCRIPT_NAME: bad input (no chain) \"$LINE\""
exit 1
fi
}
function apply() {
iptables $@
echo "$SCRIPT_NAME: iptables $@"
}
[ $# -ne 1 ] && show_usage
FILE=$1
if [ ! -r $FILE ]; then
echo "$SCRIPT_NAME: Cannot read input file ${FILE}."
exit 1
fi
while read LINE
do
CMD=${LINE:0:2}
ARGLIST=${LINE:2}
case "$CMD" in
-A | -I)
check -C $ARGLIST || apply $LINE
;;
-D)
check -C $ARGLIST && apply $LINE
;;
-F | -X)
check -L $ARGLIST && apply $LINE
;;
-N)
check -L $ARGLIST || apply $LINE
;;
*)
echo "$SCRIPT_NAME: bad input \"$LINE\""
exit 1
;;
esac
done < <(grep -Ev "^[[:space:]]*$|^#" $FILE)