Firewall
marzec 6th, 2007Przygotowując router VPN pokusiłem się o napisanie prostego firewalla opartego na iptables. Jako naturalne przyjąłem, że interesuje mnie ruch trafiający na INPUT oraz FORWARD natomiast OUTPUT zupełnie nie jest analizowany.
Konieczne było także odseparowanie pliku konfiguracyjnego gdzie w sposób łatwy i szybki można zmieniać ustawienia. Całość działa oczywiście pod kontrolą PLD, więc pokusiłem sie o wykorzystanie /etc/rc.d/init.d/functions
Oto wypociny
co więcej działające
-bash-3.2# pwd && ls -R
/etc/firewall
.:
logs rules settings
./logs:
firewall
./rules:
forward input
Kawałek pliku input
# source_ip ; sourec_int ; tcp_ports ; udp_ports
#
127.0.0.1/32;lo;all;all
0.0.0.0/0;eth0;1194;1194
192.16.0.0/16;tap0;2323;2323
No i oczywiscie regułki dla forward
# input_int ; input_host; output_host; output_int ; tcp_ports ; udp_ports
#
lo;127.0.0.1/32;0.0.0.0/0;any;all;all
any;0.0.0.0/0;127.0.0.1/32;lo;all;all
any;195.95.154.14/32;192.168.0.0/16;any;all;all
Oczywiscie wymagany jest jeszcze plik settings
# domyslna polityka input
DEFAULT_INPUT_POLICY="DROP"
# domyslna polityka input add
DEFAULT_INPUT_ADD="-A"
# domyslna polityka forward
DEFAULT_FORWARD_POLICY="DROP"
# domyslna polityka forward add
DEFAULT_FORWARD_ADD="-A"
# domyslna polityka output
DEFAULT_OUTPUT_POLICY="ACCEPT"
# domyslna polityka output add
DEFAULT_OUTPUT_ADD="-A"
# cala siec DMZ
DMZ_NET="xxx.xxx.xxx.0/24"
DMZ_MASK="255.255.255.0"
DMZ_BCAST="xxx.xxx.xxx.255"
# bramy internetowe
GATES="eth0"
Oraz najbardziej interesująca część … sam skrypt
#!/bin/bash
ROOT_DIR="/etc/firewall"
RULES_DIR=$ROOT_DIR"/rules"
LOGS_DIR=$ROOT_DIR"/logs"
CONF_FILE=$ROOT_DIR"/settings"
#
TABLES="/usr/sbin/iptables"
if [ ! -f $RULES_DIR/forward ]; then
echo ” No forward rules”
exit 3
fi
if [ ! -f $CONF_FILE ]; then
echo ” No config file”
exit 3
else
. $CONF_FILE
fi
. /etc/rc.d/init.d/functions
case “$1″ in
start)
msg_starting “Firewall ”
busy
echo “#!/bin/bash” > $LOGS_DIR/firewall
#
# echo “1″ > /proc/sys/net/ipv4/conf/all/rp_filter
# SYN COOKIES
echo “1″ > /proc/sys/net/ipv4/tcp_syncookies
echo “1″ > /proc/sys/net/ipv4/conf/all/log_martians
echo “1″ > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
#
echo “$TABLES -P INPUT $DEFAULT_INPUT_POLICY > /dev/null” >> $LOGS_DIR/firewall
echo “$TABLES -P FORWARD $DEFAULT_FORWARD_POLICY > /dev/null” >> $LOGS_DIR/firewall
echo “$TABLES -P OUTPUT $DEFAULT_OUTPUT_POLICY > /dev/null” >> $LOGS_DIR/firewall
#
echo “$TABLES $DEFAULT_FORWARD_ADD FORWARD -p icmp –icmp-type echo-request -m limit –limit 1/s -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
echo “$TABLES $DEFAULT_INPUT_ADD INPUT -p icmp –icmp-type echo-request -m limit –limit 1/s -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
# echo “$TABLES $DEFAULT_FORWARD_ADD FORWARD -p tcp –tcp-flags SYN,ACK,FIN,RST RST -m limit –limit 1/s -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
echo “$TABLES $DEFAULT_INPUT_ADD INPUT -p tcp –tcp-flags SYN,ACK,FIN,RST RST -m limit –limit 1/s -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
#
echo “$TABLES $DEFAULT_INPUT_ADD INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
echo “$TABLES $DEFAULT_FORWARD_ADD FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT > /dev/null” >> $LOGS_DIR/firewall
####
INPUT_SOURCES=`grep -v “^#” $RULES_DIR/input | awk -F”;” ‘ { print $1 } ‘`
for CURR_IP in $INPUT_SOURCES; do
CURR_INT=`grep -v “^#” $RULES_DIR/input | grep $CURR_IP | awk -F”;” ‘ { print $2 } ‘`
CURR_TCP=`grep -v “^#” $RULES_DIR/input | grep $CURR_IP | awk -F”;” ‘ { print $3 } ‘`
CURR_UDP=`grep -v “^#” $RULES_DIR/input | grep $CURR_IP | awk -F”;” ‘ { print $4 } ‘`
PREFIX=”$TABLES $DEFAULT_INPUT_ADD INPUT”
#
if [ ! “$CURR_INT” == “any” ]; then
PREFIX=$PREFIX” -i $CURR_INT”
fi
# first tcp ports
if [ ! “$CURR_TCP” == “none” ]; then
if [ “$CURR_TCP” == “all” ]; then
# if all ports
FULL_RULE=$PREFIX” -p tcp -s $CURR_IP -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
else
# for every port
for TCP_PORT in $CURR_TCP; do
FULL_RULE=$PREFIX” -p tcp -s $CURR_IP -m state –state NEW,RELATED,ESTABLISHED –dport $TCP_PORT -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
done
fi
#
fi
#
# udp ports
if [ ! “$CURR_UDP” == “none” ]; then
if [ “$CURR_UDP” == “all” ]; then
# if all ports
FULL_RULE=$PREFIX” -p udp -s $CURR_IP -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
else
# for every port
for UDP_PORT in $CURR_UDP; do
FULL_RULE=$PREFIX” -p udp -s $CURR_IP -m state –state NEW,RELATED,ESTABLISHED –dport $UDP_PORT -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
done
fi
fi
#
done
###
FORWARD_SOURCES=`grep -v “^#” $RULES_DIR/forward`
for LINE in $FORWARD_SOURCES; do
# any;0.0.0.0/0;127.0.0.1/32;lo;all;all
CURR_IN_INT=`echo $LINE | awk -F”;” ‘ { print $1 } ‘`
CURR_IN_IP=`echo $LINE | awk -F”;” ‘ { print $2 } ‘`
CURR_OUT_IP=`echo $LINE | awk -F”;” ‘ { print $3 } ‘`
CURR_OUT_INT=`echo $LINE | awk -F”;” ‘ { print $4 } ‘`
CURR_TCP=`echo $LINE | awk -F”;” ‘ { print $5 } ‘`
CURR_UDP=`echo $LINE | awk -F”;” ‘ { print $6 } ‘`
#
PREFIX=”$TABLES $DEFAULT_FORWARD_ADD FORWARD”
#
if [ ! “$CURR_IN_INT” == “any” ]; then
PREFIX=$PREFIX” -i $CURR_IN_INT”
fi
#
SUFIX=”"
if [ ! “$CURR_OUT_INT” == “any” ]; then
SUFIX=”-o $CURR_OUT_INT”
fi
#
# first TCP
if [ ! “$CURR_TCP” == “none” ]; then
if [ “$CURR_TCP” == “all” ]; then
FULL_RULE=$PREFIX” -s $CURR_IN_IP -p tcp -d $CURR_OUT_IP $SUFIX -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
else
# for every port
for TCP_PORT in $CURR_TCP; do
FULL_RULE=$PREFIX” -s $CURR_IN_IP -p tcp -d $CURR_OUT_IP $SUFIX -m state –state NEW,RELATED,ESTABLISHED –dport $TCP_PORT -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
done
fi
fi
# then UDP
if [ ! “$CURR_UDP” == “none” ]; then
if [ “$CURR_UDP” == “all” ]; then
FULL_RULE=$PREFIX” -s $CURR_IN_IP -p udp -d $CURR_OUT_IP $SUFIX -j ACCEPT > /dev/null”
echo $FULL_RULE >> $LOGS_DIR/firewall
unset FULL_RULE
else
# for every port
for UDP_PORT in $CURR_UDP; do
FULL_RULE=$PREFIX” -s $CURR_IN_IP -p udp -d $CURR_OUT_IP $SUFIX -m state –state NEW,RELATED,ESTABLISHED –dport $UDP_PORT -j ACCEPT > /dev/null”
unset FULL_RULE
done
fi
fi
done
# all forward rule done
###
. $LOGS_DIR/firewall
###
ok
exit 0
;;
# —– —– —–
stop)
msg_stopping “Firewall ”
busy
$TABLES -F > /dev/null
$TABLES -X > /dev/null
$TABLES -t filter -F > /dev/null
$TABLES -t filter -X > /dev/null
$TABLES -t nat -F > /dev/null
$TABLES -t nat -X > /dev/null
$TABLES -t mangle -F > /dev/null
$TABLES -t mangle -X > /dev/null
$TABLES -P INPUT ACCEPT
$TABLES -P FORWARD ACCEPT
$TABLES -P OUTPUT ACCEPT
ok
exit 0
;;
# —– —– —–
restart)
$0 stop
$0 start
exit $?
;;
# —– —– —–
*)
msg_usage “$0 {start|stop|restart|status}”
exit 3
esac
# This must be last line !
# vi:syntax=sh:tw=78:ts=8:sw=4
W skrypcie jest oczywisćie dużo za dużo wpisane i nie ma wszystkich zamierzonych opcji, ale działa ![]()
Jest to już serwer za firewallem (w DMZ), więc nie jest to super zaawansowana brama ale skutecznie ogranicza dostęp.
marzec 8th, 2007 at 8:42 am
O fajnie. GIT
czerwiec 11th, 2008 at 3:28 pm
witam wlasnie pisze prace inzynierska z firewalla i strasznie zaciekawil mnie Twoj programik i chcialbym sie mu blizej przyjrzec bo jest ciekawie napisany .Moglbys przeslac mi go na poczte bede bardzo wdzieczny z gory dziekuje!!! pozdrawiam