Initial import

This commit is contained in:
Christoph 2017-02-21 02:29:25 +01:00
commit a0290e96c9

665
iptables_manage_chain.sh Executable file
View File

@ -0,0 +1,665 @@
#!/usr/bin/env bash
ipt=`which /sbin/iptables`
default_iptables_chain=custom-`hostname -s`
function usage() {
echo
[ -n "$1" ] && echo -e "Error: $1\n"
cat<<EOF
Usage: `basename $0` [Options] [iptables-chain]
This scripts handles iptables chain. If no chain is given on the command-line,
the script uses the default chain '$default_iptables_chain'
Note:
Only one option is allowed with exception of using '-L' in conjunction with
option '-N' (creates a new chain with logging).
Options:
-a <ip-address[/mask]>
Adds the given address to chain. Address can be either a network name,
a hostname, a network IP address (with /mask), or a plain IP address.
If no chain ist given on the command line, (default) chain '$default_iptables_chain'
will be used.
If no chain for adding the address exists, a chain will be created.
Prints an error, if the given IP address already exist in chain.
-F
Cleanup (flush) the chain. All entries for blocking ip-addresises will
be removed from chain
-f <htaccess-file>
Reads 'Deny from <address>' directives from apache style .htaccess file
and adds each found address to chain.
If no chain for adding the address exists, a chain will be created.
-h
Prints this help.
-L
Only affected in conjuction with '-N'. If '-L' is given, an additional
chains for logging the bloccking action into file '/var/log/debug' will
be created.
-N
Creates a new chain. If no chain is given on the command-line,
chain '$default_iptables_chain' will be created.
Prints an error, if chain already exist.
-S
Show a list of dropped ip-addresses by chain. If no chain is given on
the command-line, chain '$default_iptables_chain' will be listed.
Prints an error, if chain does not exist.
-X
Deletes a chain. If no chain is given on the command-line,
chain '$default_iptables_chain' will be deleted.
Prints an error, if chain does not exist.
-x <ip-address[/mask]>
Deletes the given address from chain. Address can be either
a network name, a hostname, a network IP address (with /mask), or a plain
IP address. If no chain ist given on the command line, (default) chain
'$default_iptables_chain' will be used.
Prints an error, if chain does not exist.
Prints also an error, if the given IP address does not exist in chain.
Example:
Create a new chain with logging enabled using default name ($default_iptables_chain)
`basename $0` -L -N
Create a new chain called 'drop-custom' without logging enabled:
`basename $0` -N drop-custom
Add address(es) to block '54.72.0.0/13' (Amazon) to chain 'drop-custom'
`basename $0` -a 54.72.0.0/13 drop-custom
Read addresses to block, given as directive in apache style from, file. Add
these addresse to (default) chain '$default_iptables_chain'
`basename $0` -f /vservers/nd/var/www/html/projekte/nd/htdocs/.htaccess
EOF
exit 1
}
get_help=false
add_to_chain=false
cleanup_chain=false
read_htaccess_file=false
log_firewall=false
create_chain=false
list_chain=false
drop_chain=false
delete_from_chain=false
while getopts a:Ff:hLNSXx: opt ; do
case $opt in
a) add_to_chain=true
_ban_address=$OPTARG
;;
F) cleanup_chain=true
;;
f) read_htaccess_file=true
htaccess_file=$OPTARG
;;
h) get_help=true
usage
;;
L) log_firewall=true
;;
N) create_chain=true
;;
S) list_chain=true
;;
X) drop_chain=true
;;
x) delete_from_chain=true
_unban_address=$OPTARG
;;
\?) usage
esac
done
shift `expr $OPTIND - 1`
if $add_to_chain ; then
if $create_chain || $list_chain \
|| $drop_chain || $delete_from_chain \
|| $read_htaccess_file || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $create_chain ; then
if $add_to_chain || $list_chain \
|| $drop_chain || $delete_from_chain \
|| $read_htaccess_file || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $list_chain ; then
if $add_to_chain || $create_chain \
|| $drop_chain || $delete_from_chain \
|| $read_htaccess_file || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $drop_chain ; then
if $add_to_chain || $create_chain \
|| $list_chain || $delete_from_chain \
|| $read_htaccess_file || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $delete_from_chain ; then
if $add_to_chain || $create_chain \
|| $list_chain || $drop_chain \
|| $read_htaccess_file || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $read_htaccess_file ; then
if $add_to_chain || $create_chain \
|| $list_chain || $drop_chain \
|| $delete_from_chain || $cleanup_chain ; then
usage "To many arguments!"
fi
elif $cleanup_chain ; then
if $add_to_chain || $create_chain \
|| $list_chain || $drop_chain \
|| $delete_from_chain || $read_htaccess_file ; then
usage "To many arguments!"
fi
fi
if ! $add_to_chain && ! $create_chain \
&& ! $list_chain && ! $drop_chain \
&& ! $delete_from_chain \
&& ! $read_htaccess_file && ! $cleanup_chain ; then
usage "No options given!"
fi
iptables_chain=$1
iptables_chain=${iptables_chain:=$default_iptables_chain}
if [ "$iptables_chain" = "$default_iptables_chain" ]; then
echo -e "\n\tNo chain wa given. Using default chain '$iptables_chain'"
else
echo -e "\n\tUsing iptables chain: $iptables_chain"
fi
## --- Some functions
## ---
## Check if a given array (parameter 2) contains a given string (parameter 1)
containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
get_address () {
if [ "$#" != "1" ]; then
return 1
fi
_given=$1
_ip=${_given%/*}
if [ "$_ip" != "$_given" ]; then
_mask=${_given##*/}
fi
_ip_1=$(echo ${_ip} | tr "." " " | awk '{ print $1 }')
_ip_2=$(echo ${_ip} | tr "." " " | awk '{ print $2 }')
_ip_3=$(echo ${_ip} | tr "." " " | awk '{ print $3 }')
_ip_4=$(echo ${_ip} | tr "." " " | awk '{ print $4 }')
if [ -z "$_ip_4" ]; then
if [ -n "$_mask" ]; then
return 1
fi
_ip_4=0
_mask=24
if [ -z "$_ip_3" ]; then
_ip_3=0
_mask=16
if [ -z "$_ip_2" ]; then
_ip_2=0
_mask=8
fi
fi
elif [ "$_ip_4" = "0" ]; then
if [ -z "$_mask" -o "$_mask" = "32" ] ; then
_mask=24
fi
fi
_check_address="$_ip_1.$_ip_2.$_ip_3.$_ip_4"
if [ -n "$_mask" ]; then
_check_address="${_check_address}/$_mask"
fi
_ip_address=`sipcalc $_check_address | grep -e "Network address" | awk '{print$4}'`
if [ -z "$_ip_address" ]; then
echo -e "\n\tWrong enty\n"
return 1
elif [ -n "$_mask" ]; then
_ip_address="${_ip_address}/$_mask"
fi
echo "$_ip_address"
return 0
}
create_chain () {
$ipt -N $iptables_chain > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
$ipt -A $iptables_chain -j RETURN > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
#$ipt -I INPUT -p tcp -m multiport --dports http,https -j $iptables_chain > /dev/null 2>&1
$ipt -I INPUT -p all -j $iptables_chain > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
if $log_firewall ; then
$ipt -N ${iptables_chain}-log > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
$ipt -I ${iptables_chain}-log -j LOG --log-prefix "$iptables_chain: " --log-level debug > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
$ipt -A ${iptables_chain}-log -j DROP > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
fi
return 0
}
remove_chain () {
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -F ${iptables_chain}-log > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
fi
#$ipt -D INPUT -p tcp -m multiport --dports http,https -j $iptables_chain > /dev/null 2>&1
$ipt -D INPUT -p all -j $iptables_chain
if [ "$?" != "0" ]; then
return 1
fi
$ipt -F $iptables_chain > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -X ${iptables_chain}-log > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
fi
$ipt -X $iptables_chain > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
return 0
}
flush_chain () {
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -F ${iptables_chain}-log > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
fi
$ipt -F $iptables_chain > /dev/null 2>&1
if [ "$?" != "0" ]; then
return 1
fi
return 0
}
echononl(){
echo X\\c > /tmp/shprompt$$
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
echo "$*\\c" 1>&2
else
echo -e -n "$*" 1>&2
fi
rm /tmp/shprompt$$
}
info (){
echo ""
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
echo ""
}
warn (){
echo ""
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
echo ""
}
error (){
echo ""
echo -e "\t[ \033[31m\033[1mError\033[m ]: $*"
echo ""
}
echo_ok() {
echo -e "\033[60G[ \033[32mok\033[m ]"
}
echo_failed(){
echo -e "\033[60G[ \033[1;31mfailed\033[m ]"
}
echo_skipped() {
echo -e "\033[60G[ \033[33m\033[1mskipped\033[m ]"
}
## ---
## --- END: functions
echo
if $create_chain ; then
echononl "\tCreate Chain '$iptables_chain'.."
if `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_skipped
warn "Chain '$iptables_chain' already exists"
else
create_chain
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
echo
exit
fi
if $cleanup_chain ; then
echononl "\tFlush Chain '$iptables_chain'.."
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_failed
error "Chain '$iptables_chain' does not exist!"
else
flush_chain
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
echo
exit
fi
if $drop_chain ; then
echononl "\tDrop Chain '$iptables_chain'.."
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_skipped
warn "Chain '$iptables_chain' does not exist!"
else
remove_chain
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
echo
exit
fi
if $list_chain ; then
echononl "\tList of dropped IPs (Chain '$iptables_chain').."
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_failed
error "Chain '$iptables_chain' does not exist!"
else
echo_ok
echo
_tmp_file=`mktemp`
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -n -L $iptables_chain | grep -i -e "^${iptables_chain}-log\ " > $_tmp_file
else
$ipt -n -L $iptables_chain | grep -i -e "^DROP\ " > $_tmp_file
fi
if [ -z "`cat $_tmp_file`" ]; then
warn "No IPs to drop in Chain '$iptables_chain"
else
while IFS='' read -r line || [[ -n $line ]]; do
echo -e "\t$line"
done < $_tmp_file
rm -f $_tmp_file
fi
echo
fi
echo
exit
fi
if $add_to_chain ; then
ban_address=`get_address $_ban_address`
if [ "$?" != "0" ];then
error "Given address may be wrong"
exit 1
fi
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
warn "Chain '$iptables_chain' does not exist. Trying to create one.."
echononl "\tCreate chain '$iptables_chain'.."
create_chain
if [ "$?" = "0" ]; then
echo_ok
echo
else
echo_failed
echo
exit 1
fi
fi
## - Create empty array
## -
_ip_banned_arr=()
echononl "\tAdd IP '$ban_address' to chain '$iptables_chain'.."
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_skipped
error "Chain '$iptables_chain' does not exist!"
else
_ips_banned=`iptables -n -L $iptables_chain | grep -i -e "^DROP\ " | awk '{print$4}'`
for _ip in $_ips_banned ; do
_ip_banned_arr+=($_ip);
done
if containsElement "$ban_address" "${_ip_banned_arr[@]}" ; then
echo_skipped
warn "Chain '$iptables_chain' contains already IP 'ban_address'"
else
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -I $iptables_chain 1 -s $ban_address -j ${iptables_chain}-log
else
$ipt -I $iptables_chain 1 -s $ban_address -j DROP
fi
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
fi
echo
exit
fi
if $delete_from_chain ; then
unban_address=`get_address $_unban_address`
if [ "$?" != "0" ];then
error "Given address may be wrong"
exit 1
fi
## - Create empty array
## -
_ip_banned_arr=()
echononl "\tRemove IP '$unban_address' from chain '$iptables_chain'.."
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
echo_skipped
warn "Chain '$iptables_chain' does not exist!"
else
## - Read list of already blocked addresses
## -
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
_ips_banned=`iptables -n -L $iptables_chain | grep "${iptables_chain}-log" | awk '{print$4}'`
else
_ips_banned=`iptables -n -L $iptables_chain | grep -i -e "^DROP\ " | awk '{print$4}'`
fi
for _ip in $_ips_banned ; do
_ip_banned_arr+=($_ip);
done
## - Check if given address is in list of blocked addresses. If
## - address is not blocked, nothing to do..
## -
if ! containsElement "$unban_address" "${_ip_banned_arr[@]}" ; then
echo_skipped
warn "Chain '$iptables_chain' does not caontain IP '$unban_address'"
else
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -D $iptables_chain -s $unban_address -j ${iptables_chain}-log
else
$ipt -D $iptables_chain -s $unban_address -j DROP
fi
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
fi
echo
exit
fi
if $read_htaccess_file ; then
if [ ! -f "$htaccess_file" ]; then
error "File '$htaccess_file' not found!"
exit 1
fi
if ! `$ipt -n -L $iptables_chain > /dev/null 2>&1` ; then
warn "Chain '$iptables_chain' does not exist. Trying to create one.."
echononl "\tCreate chain '$iptables_chain'.."
create_chain
if [ "$?" = "0" ]; then
echo_ok
echo
else
echo_failed
echo
exit 1
fi
fi
## - Read adresses from htaccess file
## -
_ips_to_ban=`cat $htaccess_file | grep -e "^\s*Deny from " | awk '{print$3}'`
for _ban_address in $_ips_to_ban ; do
echononl "\tAdd IP '$_ban_address' to chain '$iptables_chain'.."
ban_address=`get_address $_ban_address`
if [ "$?" != "0" ];then
echo_failed
error "Given address may be wrong"
continue
fi
## - Read list of already blocked addresses
## -
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
_ips_banned=`iptables -n -L $iptables_chain | grep "${iptables_chain}-log" | awk '{print$4}'`
else
_ips_banned=`iptables -n -L $iptables_chain | grep -i -e "^DROP\ " | awk '{print$4}'`
fi
## - Check if given address is in list of blocked addresses. If
## - address is already in that list, nothing to do..
## -
for _ip in $_ips_banned ; do
_ip_banned_arr+=($_ip);
done
if containsElement "$ban_address" "${_ip_banned_arr[@]}" ; then
echo_skipped
warn "Chain '$iptables_chain' contains already IP 'ban_address'"
else
if `$ipt -n -L ${iptables_chain}-log > /dev/null 2>&1` ; then
$ipt -I $iptables_chain 1 -s $ban_address -j ${iptables_chain}-log > /dev/null 2>&1
else
$ipt -I $iptables_chain 1 -s $ban_address -j DROP > /dev/null 2>&1
fi
if [ "$?" = "0" ]; then
echo_ok
else
echo_failed
fi
fi
done
echo
exit 0
fi
exit 0
for _ip in ${_ip_banned_arr[@]} ; do
echo $_ip
done
exit 0