From 6a34b1697ea9f1955ee3b75809b3cd388790a8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Schneider?= Date: Tue, 21 Jun 2011 14:21:52 +0200 Subject: [PATCH] Add port knocking and support save and load rules * Support port knocking * Add a test option * Add save and load of the rules * Modify states to support last iptables version * Add logrotate support for the Debian packages --- Makefile | 2 +- README | 16 +++++-- debian/eofirewall.logrotate | 9 ++++ firewall | 87 ++++++++++++++++++++++++++--------- firewall.conf | 8 +++- iptables.conf => rsyslog.conf | 0 6 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 debian/eofirewall.logrotate rename iptables.conf => rsyslog.conf (100%) diff --git a/Makefile b/Makefile index 6cc21b8..3f38207 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,6 @@ all: install: install -d -m 0755 -o root -g root $(DESTDIR)/etc/init.d $(DESTDIR)/etc/rsyslog.d/ install -m 0640 -o root -g root $(NAME).conf $(DESTDIR)/etc/ - install -m 0640 -o root -g root iptables.conf $(DESTDIR)/etc/rsyslog.d + install -m 0640 -o root -g root rsyslog.conf $(DESTDIR)/etc/rsyslog.d install -m 0755 -o root -g root $(NAME) $(DESTDIR)/etc/init.d diff --git a/README b/README index 3b0d7ad..4e298bf 100644 --- a/README +++ b/README @@ -1,4 +1,14 @@ -= INSTALLATION = - * Install rsyslog += Installation = + * Requrie: rsyslog, logrotate and iptables * make install - * use /etc/init.d/firewall [stop | start | restart] + += Usage = + +First launch test your configuration: + /etc/init.d/firewall test +Second save this change (this will load your rules and save it): + /etc/init.d/firewall save +You need to use save at least one time. + +/etc/init.d/firewall stop: will flush your rules +/etc/init.d/firewall start|restore: will load your saved rules diff --git a/debian/eofirewall.logrotate b/debian/eofirewall.logrotate new file mode 100644 index 0000000..95c99d3 --- /dev/null +++ b/debian/eofirewall.logrotate @@ -0,0 +1,9 @@ +/var/log/iptables.log { + weekly + rotate 6 + compress + delaycompress + missingok + create 640 root adm +} + diff --git a/firewall b/firewall index 951d074..4545010 100755 --- a/firewall +++ b/firewall @@ -12,14 +12,6 @@ NAME="firewall" -if [ -f "/etc/firewall.conf" ]; then - source /etc/firewall.conf -else - echo "No configuration file /etc/firewall.conf" - exit 1 -fi - - abort() { message=$@ @@ -29,6 +21,12 @@ abort() exit 1 } +if [ -f "/etc/firewall.conf" ]; then + source /etc/firewall.conf +else + abort "No configuration file /etc/firewall.conf" +fi + clean() { $IPTABLES -F @@ -76,7 +74,7 @@ forward_port() echo "!! WARNING you must add a LAN interface (LAN_INT) for a port forward" else echo "+ Forward $port to $destination for protocol $proto" - $IPTABLES -A FORWARD -i $WAN_INT -o $LAN_INT -p $proto -s $source -d $dest_ip --dport $dest_port -m state ! --state INVALID -j ACCEPT + $IPTABLES -A FORWARD -i $WAN_INT -o $LAN_INT -p $proto -s $source -d $dest_ip --dport $dest_port -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT $IPTABLES -t nat -A PREROUTING -i $WAN_INT -p $proto -s $source -d $IP --dport $port -j DNAT --to $destination fi fi @@ -100,7 +98,7 @@ open_port() source=$1 for port in $(echo $ports | sed 's/,/ /g'); do echo "+ Open port $port from $source to $destination for protocol $proto" - $IPTABLES -A INPUT -i $WAN_INT -p $proto -s $source -d $destination --dport $port -m state ! --state INVALID -j ACCEPT + $IPTABLES -A INPUT -i $WAN_INT -p $proto -s $source -d $destination --dport $port -m state --state NEW -j ACCEPT critical_return done } @@ -111,7 +109,7 @@ port_redirection() echo "! Bad syntax for port redirection : $*" return fi - + if=$1 proto=$2 srcport=$3 @@ -121,6 +119,28 @@ port_redirection() iptables -t nat -A PREROUTING -i $if -p $proto --dport $srcport -j REDIRECT --to-port $destport } +port_knocking() +{ + if [ $# != 2 ]; then + echo "! Bad syntax for port knocking : $*" + return + fi + + port=$1 + knock_ports=$2 + + iptables -N toc2 + iptables -A toc2 -m recent --name toc1 --remove + iptables -A toc2 -m recent --name toc2 --set + iptables -N toc3 + iptables -A toc3 -m recent --name toc2 --remove + iptables -A toc3 -m recent --name toc3 --set + for port in $(echo $knock_ports | sed 's/,/ /g'); do + iptables -A INPUT -i $WAN_INT -p tcp --dport $port -m recent --set --name toc1 + done + iptables -A INPUT -i $WAN_INT -p tcp --dport $port -m recent --rcheck --seconds 15 --name toc3 -m state --state NEW -j ACCEPT +} + start() { echo "Starting: Firewall" @@ -139,14 +159,14 @@ start() $IPTABLES -A OUTPUT -o lo -j ACCEPT echo "+ Allow WAN outgoing traffic" - $IPTABLES -A OUTPUT -o $WAN_INT -p all -m state ! --state INVALID -j ACCEPT - $IPTABLES -A INPUT -i $WAN_INT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT + $IPTABLES -A OUTPUT -o $WAN_INT -p all -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT + $IPTABLES -A INPUT -i $WAN_INT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT critical_return if [ $LAN == 1 ]; then echo "+ Allow WAN outgoing traffic from lan" - $IPTABLES -A FORWARD -i $LAN_INT -o $WAN_INT -p all -m state ! --state INVALID -j ACCEPT + $IPTABLES -A FORWARD -i $LAN_INT -o $WAN_INT -p all -m state ESTABLISHED,RELATED,NEW -j ACCEPT $IPTABLES -A FORWARD -i $WAN_INT -o $LAN_INT -p all -m state --state RELATED,ESTABLISHED -j ACCEPT echo "+ Allow local network" @@ -154,7 +174,7 @@ start() $IPTABLES -A INPUT -i $LAN_INT -p all -j ACCEPT for ALLOW_INT in $ALLOW_INTS; do echo "+ Allow WAN outgoing traffic for interface $ALLOW_INT" - $IPTABLES -A FORWARD -i $ALLOW_INT -o $WAN_INT -p all -m state ! --state INVALID -j ACCEPT + $IPTABLES -A FORWARD -i $ALLOW_INT -o $WAN_INT -p all -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT $IPTABLES -A FORWARD -i $WAN_INT -o $ALLOW_INT -p all -m state --state RELATED,ESTABLISHED -j ACCEPT echo "+ Allow local network" @@ -222,6 +242,11 @@ start() open_port $args done + ## Port knocking + for args in "${PORT_KNOCK[@]}"; do + port_knocking $args + done + ## Port forwading for args in "${TRAFFICS[@]}"; do forward_port $args @@ -279,19 +304,39 @@ stop() } case "$1" in - start) - start || exit 1 + start|restore) + if [ -f /etc/network/iptables-save ]; then + iptables-restore < /etc/network/iptables-save + echo "Firewall: rules loaded" + else + abort "!! No iptables rules saved please use test and save script options" + fi ;; stop) - stop || exit 1 + stop || exit 1 ;; - restart|force-reload) + test) + echo "You have 30 seconds to test your new rules" + start || exit 1 + echo "... Please test your rules" + sleep 30 + echo "---- The test is finished ----" + if [ -f /etc/network/iptables-save ]; then + iptables-restore < /etc/network/iptables-save + echo "Old rules restored" + else stop - start || exit 1 + echo "Rules flushed" + fi + echo "If you are happy with this new rules please use save option" + ;; + save) + start || exit 1 + iptables-save > /etc/network/iptables-save ;; *) N=/etc/init.d/$NAME - abort "Usage: $N {start|stop|restart|force-reload}" >&2 + abort "Usage: $N {start|restore|save|test|stop}" >&2 ;; esac diff --git a/firewall.conf b/firewall.conf index 2325402..5ce3764 100644 --- a/firewall.conf +++ b/firewall.conf @@ -20,9 +20,15 @@ ALLOW_INTS='' ## Open ports # "source [destination] protocole {porta|portx:porty},[portx:porty,porta,portb,...]" ... # The default destination is the IP ! -# example : OPEN_PORTS=("0.0.0.0/0 tcp 22" "42.42.42.0/24 42.42.42.42 tcp ssh,imap,imaps,1024:2048,32") +# example : OPEN_PORTS=("0.0.0.0/0 tcp 22" +# "42.42.42.0/24 42.42.42.42 tcp ssh,imap,imaps,1024:2048,32") OPEN_PORTS=("0.0.0.0/0 tcp ssh") +## Port knocking +# "port knock_ports_combinaison" +# example : PORT_KNOCK("22 121,4353,4242,111") +PORT_KNOCK=() + ## Port forwarding # "source port destination:port protocol" "source port destination:port protocol" ... # example : TRAFFICS=("0.0.0.0/0 80 192.168.0.42:80 tcp" "42.42.42.42 4242 192.168.0.43:22 tcp") diff --git a/iptables.conf b/rsyslog.conf similarity index 100% rename from iptables.conf rename to rsyslog.conf