Created
April 21, 2016 02:18
-
-
Save zyuskin/45546bce706a3f65a580b6299451f4a0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
RET_ARR=() | |
UNAME=`uname` | |
DEBUG=0 | |
IPTABLES=`which iptables` | |
IPFW="/usr/bin/ipfw" | |
RULES_FILE=/etc/firewall.rules | |
LOG_FILE=/var/log/firewall.log | |
SAVE=yes | |
ALWAYS_SAVE=no | |
[ -f /root/.firewallrc ] && . /root/.firewallrc | |
[ "$EDITOR" = "" ] && EDITOR=mcedit | |
if [ "$UNAME" = "Darwin" ]; then | |
MD5="md5 -r " | |
else | |
MD5="md5sum " | |
fi | |
# Find str $2 in str $1 | |
Pos(){ | |
Str=$1 | |
Arg=$2 | |
i=0 | |
while [ $i -lt ${#Str} ]; do | |
Sim=${Str:$i:1} | |
if [ "$Sim" = "$Arg" ] ; then | |
return $i | |
fi | |
let i=i+1 | |
done | |
return 0 | |
} | |
ExplodeStr(){ | |
RET_ARR=() | |
Str=$1 | |
Sep=$2 | |
i=0 | |
arr=$(echo $Str | tr "$Sep" "\n") | |
for x in $arr; do | |
RET_ARR[$i]=$x | |
let i=i+1 | |
done | |
} | |
log(){ | |
message=$1 | |
echo "$LOGNAME `date` $message" >> $LOG_FILE | |
} | |
set_varible(){ | |
name=$1 | |
value=$2 | |
eval $name=$value | |
} | |
flush(){ | |
if [ "$UNAME" = "Darwin" ] || [ "$UNAME" = "FreeBSD" ]; then | |
$IPFW -f flush | |
else | |
$IPTABLES -F | |
$IPTABLES -F INPUT | |
$IPTABLES -F OUTPUT | |
$IPTABLES -F FORWARD | |
$IPTABLES -F -t nat | |
fi; | |
} | |
established(){ | |
if [ "$UNAME" = "Darwin" ] || [ "$UNAME" = "FreeBSD" ]; then | |
$IPFW add allow all from any to any established | |
else | |
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT | |
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
fi | |
} | |
trusted_int(){ | |
interfases="$1" | |
int_list=${interfases//,/ } | |
for x in $int_list; do | |
rules "allow all from any to me via $x" | |
done; | |
} | |
INPUT(){ | |
_action=$1 | |
_via=$2 | |
_proto=$3 | |
_from=$4 | |
_from_port=$5 | |
_to_port=$6 | |
[ "$_via" != "" ] && _via="-i $_via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port="-m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
echo $_from_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_from_port="-m multiport --sports $_from_port" | |
else | |
[ "$_from_port" = "" ] && _from_port="" || _from_port="--sport $_from_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error input: port set but protocol not tcp or udp"; | |
else | |
echo $_from | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_hosts=${_from//,/ } | |
for _from in $_hosts; do | |
$IPTABLES -A INPUT $_via $_proto -s $_from $_from_port $_to_port -j $_action | |
done; | |
else | |
[ "$_from" != "any" ] && _from="-s $_from" || _from="" | |
$IPTABLES -A INPUT $_via $_proto $_from $_from_port $_to_port -j $_action | |
fi | |
fi | |
} | |
OUTPUT(){ | |
_action=$1 | |
_via=$2 | |
_proto=$3 | |
_to=$4 | |
_to_port=$5 | |
[ "$_via" != "" ] && _via="-o $_via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
[ "$_to" != "any" ] && _to=" -d $_to" || _to="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port="-m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error output: port set but protocol not tcp udp"; | |
else | |
$IPTABLES -A OUTPUT $_via $_proto $_to $_to_port -j $_action | |
fi | |
} | |
FORWARD(){ | |
_action=$1 | |
_via=$2 | |
_proto=$3 | |
_from=$4 | |
_from_port=$5 | |
_to=$6 | |
_to_port=$7 | |
[ "$_via" != "" ] && _via="-i $via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
[ "$_from" != "any" ] && _from="-s $_from" || _from="" | |
[ "$_to" != "any" ] && _to="-d $_to" || _to="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port="-m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
echo $_from_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_from_port="-m multiport --sports $_from_port" | |
else | |
[ "$_from_port" = "" ] && _from_port="" || _from_port="--sport $_from_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error forward: port set but protocol not tcp or udp"; | |
else | |
$IPTABLES -A FORWARD $_via $_proto $_from $_from_port $_to $_to_port -j $_action | |
fi | |
} | |
SNAT(){ | |
_ip=$1 | |
_via=$2 | |
_from=$3 | |
_from_port=$4 | |
_to=$5 | |
_to_port=$6 | |
[ "$_via" != "" ] && _via="-o $via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
[ "$_from" != "any" ] && _from="-s $_from" || _from="" | |
[ "$_to" != "any" ] && _to="-d $_to" || _to="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port="-m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
echo $_from_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_from_port=" -m multiport --sports $_from_port" | |
else | |
[ "$_from_port" = "" ] && _from_port="" || _from_port="--sport $_from_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error forward: port set but protocol not tcp or udp"; | |
else | |
$IPTABLES -t nat -A POSTROUTING $_from $_from_port $_to $_to_port $_via -j SNAT --to-source $_ip | |
fi | |
} | |
MASQ(){ | |
_via=$1 | |
_from=$2 | |
_from_port=$3 | |
_to=$4 | |
_to_port=$5 | |
[ "$_via" != "" ] && _via="-o $via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
[ "$_from" != "any" ] && _from="-s $_from" || _from="" | |
[ "$_to" != "any" ] && _to="-d $_to" || _to="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port="-m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
echo $_from_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_from_port=" -m multiport --sports $_from_port" | |
else | |
[ "$_from_port" = "" ] && _from_port="" || _from_port="--sport $_from_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error forward: port set but protocol not tcp or udp"; | |
else | |
$IPTABLES -t nat -A POSTROUTING $_from $_from_port $_to $_to_port $_via -j MASQUERADE | |
fi | |
} | |
DNAT(){ | |
_dst=$1 | |
_via=$2 | |
_proto=$3 | |
_from=$4 | |
_from_port=$5 | |
_to=$6 | |
_to_port=$7 | |
[ "$_via" != "" ] && _via="-i $via" | |
[ "$_proto" != "all" ] && _proto="-p $_proto" || _proto="" | |
[ "$_from" != "any" ] && _from="-s $_from" || _from="" | |
[ "$_to" != "any" ] && _to="-d $_to" || _to="" | |
echo $_to_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_to_port=" -m multiport --dports $_to_port" | |
else | |
[ "$_to_port" = "" ] && _to_port="" || _to_port="--dport $_to_port" | |
fi | |
echo $_from_port | grep "," > /dev/null 2>&1; po=$? | |
if [ $po -eq 0 ]; then | |
_from_port="-m multiport --sports $_from_port" | |
else | |
[ "$_from_port" = "" ] && _from_port="" || _from_port="--sport $_from_port" | |
fi | |
if [[ "$_to_port" != "" && ("$_proto" != "-p udp" && "$_proto" != "-p tcp") ]]; then | |
echo "Error forward: port set but protocol not tcp"; | |
else | |
if [ "$_to" = "-d me" ]; then | |
_to="" | |
_action="DNAT --to-destination $_dst" | |
else | |
_action="REDIRECT --to-port $_dst" | |
fi | |
$IPTABLES -t nat -A PREROUTING $_via $_proto $_from $_from_port $_to $_to_port -j $_action | |
fi | |
} | |
rules(){ | |
src_str=$1 | |
act="" | |
proto="all" | |
from="any" | |
from_port="" | |
to="any" | |
to_port="" | |
via="" | |
direction="" | |
log="" | |
divert_type="" | |
snat_ip="" | |
dnat_dst="" | |
if [ "$UNAME" = "Darwin" ] || [ "$UNAME" = "FreeBSD" ]; then | |
$IPFW add $src_str | |
return | |
fi; | |
ExplodeStr "$src_str" " " | |
i=0 | |
n=0 | |
for x in $arr; do | |
let i=i+1 | |
let n=i+1 | |
let nn=i+2 | |
if [ "${x}" = "fwd" ] || [ "${x}" = "forward" ]; then | |
act="dnat" | |
dnat_dst=${RET_ARR[i]} | |
elif [ "${x}" == "divert" ]; then | |
act="divert" | |
divert_type=${RET_ARR[i]} | |
snat_ip=${RET_ARR[n]} | |
elif [ "${x}" == "deny" ] || [ "${x}" == "drop" ] || [ "${x}" == "allow" ] || [ "${x}" == "accept" ] || [ "${x}" == "pass" ] || [ "${x}" == "permit" ]; then | |
act=${x}; | |
elif [ "${x}" == "gre" ] || [ "${x}" == "icmp" ] || [ "${x}" == "ip" ] || [ "${x}" == "tcp" ] || [ "${x}" == "udp" ]; then | |
proto=${x}; | |
elif [ "${x}" == "log" ]; then | |
log="log" | |
elif [ "${x}" == "from" ]; then | |
from=${RET_ARR[i]} | |
if [ "${RET_ARR[n]}" != "" ] && [ "${RET_ARR[n]}" != "to" ]; then | |
from_port=${RET_ARR[n]} | |
fi; | |
elif [ "${x}" == "to" ]; then | |
to=${RET_ARR[i]} | |
if [ "${RET_ARR[n]}" != "" ] && [ "${RET_ARR[n]}" != "in" ] && [ "${RET_ARR[n]}" != "out" ] && [ "${RET_ARR[n]}" != "via" ]; then | |
to_port=${RET_ARR[n]} | |
fi; | |
elif [ "${x}" == "in" ] || [ "${x}" == "out" ]; then | |
direction=${x}; | |
elif [ "${x}" == "via" ]; then | |
via=${RET_ARR[i]} | |
fi; | |
done; | |
if [ "$act" == "allow" ] || [ "$act" == "accept" ] || [ "$act" == "pass" ] || [ "$act" == "permit" ]; then | |
action="ACCEPT" | |
elif [ "$act" == "drop" ] || [ "$act" == "deny" ]; then | |
action="DROP" | |
else | |
action="" | |
fi; | |
if [ "$act" = "divert" ]; then | |
if [ "$divert_type" = "nat" ]; then | |
SNAT "$snat_ip" "$via" "$from" "$from_port" "$to" "$to_port" | |
else | |
MASQ "$via" "$from" "$from_port" "$to" "$to_port" | |
fi; | |
elif [ "$act" = "dnat" ]; then | |
DNAT "$dnat_dst" "$via" "$proto" "$from" "$from_port" "$to" "$to_port" | |
elif [ "$from" = "me" ]; then | |
OUTPUT "$action" "$via" "$proto" "$to" "$to_port" | |
elif [ "$to" = "me" ]; then | |
INPUT "$action" "$via" "$proto" "$from" "$from_port" "$to_port" | |
# elif [ "$action" != "" ] && [ "$to" = "any" ] && [ "$from" = "any" ]; then | |
# INPUT "$action" "$via" "$proto" "$from" "$from_port" "$to_port" | |
# OUTPUT "$action" "$via" "$proto" "$to" "$to_port" | |
# FORWARD "$action" "$via" "$proto" "$from" "$from_port" "$to" "$to_port" | |
elif [ "$action" != "" ]; then | |
FORWARD "$action" "$via" "$proto" "$from" "$from_port" "$to" "$to_port" | |
else | |
echo "Unknown command: $src_str" | |
fi; | |
} | |
Usage(){ | |
echo "Usage: firewall [options]" | |
echo " -h: This help" | |
echo " -e: Change firewall rules" | |
echo " -d: Disable/allow to all firewall" | |
echo " -t: Test firewall" | |
echo " -x: Edit firewall script" | |
echo " -l: Print firewall rules file" | |
echo " -i: Print iptables rules" | |
echo "==Simple rules====================" | |
echo "flush" | |
echo "trusted_int lo" | |
echo "established" | |
echo "allow all from me to any" | |
echo "forward 192.168.0.1:22 tcp from any to me via eth0" | |
echo "divert nat from 192.168.0.0/24 to any via eth1" | |
echo "close" | |
exit 0; | |
} | |
EditFirewallScript(){ | |
$EDITOR $0; | |
exit 0; | |
} | |
PrintFirewallRulesFile(){ | |
[ -f $RULES_FILE ] && cat $RULES_FILE || echo "Rules file not found, make '$0' -a to create it." | |
exit 0; | |
} | |
PrintMenu(){ | |
cat $RULES_FILE | |
echo -n "Apply(a), test(t), exit(x) or edit(e)?: " | |
read d | |
[ "$d" = "a" ] && $0 -a | |
[ "$d" = "e" ] && $0 -e | |
[ "$d" = "x" ] && mv -f $RULES_FILE.bak $RULES_FILE | |
[ "$d" = "t" ] && $0 -t | |
} | |
EditRules(){ | |
[ ! -f $RULES_FILE ] && WriteDefaultRules; | |
MD5_BEFORE=`$MD5 $RULES_FILE | awk '{ print $1}'` | |
cp -f $RULES_FILE $RULES_FILE.bak | |
$EDITOR $RULES_FILE | |
MD5_AFTER=`$MD5 $RULES_FILE | awk '{ print $1}'` | |
if [ ! "$MD5_BEFORE" = "$MD5_AFTER" ]; then | |
changes=`diff $RULES_FILE $RULES_FILE.bak` | |
log "Changes: $changes" | |
echo "" >> $LOG_FILE | |
PrintMenu | |
fi | |
exit 0 | |
} | |
PrintIptablesRules(){ | |
if [ "$UNAME" = "Darwin" ] || [ "$UNAME" = "FreeBSD" ]; then | |
$IPFW list | |
else | |
echo ======================================================================================== | |
$IPTABLES -L -nv --line-numbers | |
echo "" | |
$IPTABLES -t nat -L -nv --line-numbers | |
echo ======================================================================================== | |
fi | |
exit 0 | |
} | |
SaveRules(){ | |
if [ "$UNAME" = "Darwin" ] || [ "$UNAME" = "FreeBSD" ]; then | |
$IPFW list | |
else | |
service iptables save | |
fi | |
} | |
[ "$1" = "-h" ] && Usage; | |
[ "$1" = "-x" ] && EditFirewallScript; | |
[ "$1" = "-e" ] && EditRules; | |
[ "$1" = "-l" ] && PrintFirewallRulesFile; | |
[ "$1" = "-i" ] && PrintIptablesRules; | |
[ "$1" = "-t" ] && DEBUG=1; | |
if [ "$1" = "-m" ]; then | |
PrintMenu; | |
exit 0; | |
fi; | |
if [ "$1" = "" ]; then | |
EditRules; | |
fi | |
if [ "$DEBUG" -eq 1 ]; then | |
IPTABLES="echo $IPTABLES" | |
IPFW="echo $IPFW" | |
fi; | |
cat $RULES_FILE | while read line ; do | |
[ "$line" = "" ] && continue; | |
[ "${line:0:1}" = "#" ] && continue; | |
ExplodeStr "$line" " " | |
action=${RET_ARR[0]} | |
# Сброс всех правил | |
if [ "$action" = "flush" ]; then | |
flush | |
elif [ "$action" = "set" ]; then | |
set_varible ${RET_ARR[1]} ${RET_ARR[2]} | |
elif [ "$action" = "trusted_int" ]; then | |
trusted_int "${RET_ARR[1]}"; | |
elif [ "$action" = "established" ]; then | |
established; | |
elif [ "$action" = "open" ]; then | |
rules "allow all from any to me" | |
rules "allow all from me to any" | |
rules "allow all from any to any" | |
elif [ "$action" = "close" ]; then | |
rules "deny all from any to me" | |
rules "deny all from me to any" | |
rules "deny all from any to any" | |
else | |
line=`echo $line` | |
rules "$line" | |
fi; | |
done | |
if [ "$DEBUG" -eq 1 ] && [ "$1" != "-a" ]; then | |
echo -n "Press any key to continue ..." | |
read | |
$0 -m | |
else | |
if [ "$ALWAYS_SAVE" = "yes" ]; then | |
SaveRules | |
else | |
if [ "$SAVE" = "yes" ]; then | |
echo -n "Save firewall rules on system?[y/N]: " | |
read d | |
[ "$d" = "y" ] && SaveRules | |
fi; | |
fi; | |
fi; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment