#!/bin/bash # IPTKNOCK version 3.0.1 - Netfilter/IPtables multiple-port knocking. # Copyright (C) 2005 Matous Jan Fialka. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # or visit the GNU/GPL site at "http://www.gnu.org/licenses/gpl.html". function ec () { echo '/sbin/iptables ' "$@" ; } IPT=ec RULES=iptknock.rules RULES=$(<$RULES) CHAIN="INPUT" PREFX="KNOCK" RULES=${RULES// /} RULES=${RULES// /} RULES=${RULES// /} RULES=${RULES//fi/|} PARSE_ERASE="then log" for ERASE in $PARSE_ERASE ; do eval "RULES=\${RULES//$ERASE/}" done PARSE_PARTS="if from in open for" for PART in $PARSE_PARTS ; do eval "RULES=\${RULES//$PART/&}" done RULES=${RULES//on/@} RULES=${RULES//and/;} RULES=${RULES//or/;} RULEN=0 IFS="|" for RULE in $RULES ; do RULEN=$(($RULEN+1)) while IFS="&" read RULE_NAME KNOCK_CONNECTIONS REMOTE_HOSTS TO_SET \ ALLOW_SET ALLOW_CONNECTIONS ALLOW_SECONDS LOGGING ; do TO_CHAIN=${TO_SET//@*/} TO_INTERFACE=${TO_SET//*@/} if [ ! -z "$TO_INTERFACE" ] ; then STR_TO_INTERFACE="-i $TO_INTERFACE" fi ALLOW_CHAIN=${ALLOW_SET//@*/} ALLOW_INTERFACE=${ALLOW_SET//*@/} if [ ! -z "$ALLOW_INTERFACE" ] ; then STR_ALLOW_INTERFACE="-i $ALLOW_INTERFACE" fi HOSTN=0 OLD_IFS=$IFS IFS=";" for REMOTE_HOST in $REMOTE_HOSTS ; do HOSTN=$(($HOSTN+1)) PHASE=0 for KNOCK_CONNECTION in $KNOCK_CONNECTIONS ; do PHASN=0 while IFS="/" read KNOCK_PROTOCOL KNOCK_PORTS ; do PHASN=$(($PHASN+1)) done while IFS="/" read KNOCK_PROTOCOL KNOCK_PORTS ; do OLD_IFS2=$IFS IFS="," for KNOCK_PORT in $KNOCK_PORTS ; do PHASE=$(($PHASE+1)) if [ $PHASE -eq 1 ] ; then eval $IPT -A $TO_CHAIN $STR_TO_INTERFACE \ -p $KNOCK_PROTOCOL -s $REMOTE_HOST --dport $KNOCK_PORT \ -m recent --name $RULEN-$HOSTN-$PHASE --set fi if [ $PHASE -gt $PHASN ] ; then $IPT -N $RULEN-$HOSTN-IN-$(($PHASE+1)) $IPT -A $RULEN-$HOSTN-IN-$(($PHASE+1)) \ -m recent --name $RULEN-$HOSTN-$(($PHASE)) --remove $IPT -A $RULEN-$HOSTN-IN-$(($PHASE+1)) \ -m recent --name $RULEN-$HOSTN-$(($PHASE+1)) --set $IPT -A $RULEN-$HOSTN-IN-$(($PHASE+1)) \ -j LOG --log-prefix "$RULE_NAME-$RULEN-$HOSTN-IN-$(($PHASE+1)) " fi eval $IPT -A $TO_CHAIN $STR_TO_INTERFACE \ -p $KNOCK_PROTOCOL -s $REMOTE_HOST --dport $KNOCK_PORT \ -m recent --rcheck --name $RULEN-$HOSTN-$PHASE \ -j $RULEN-$HOSTN-IN-$(($PHASE+1)) done IFS=$OLD_IFS2 done <<< $KNOCK_CONNECTION done for ALLOW_CONNECTION in $ALLOW_CONNECTIONS ; do while IFS="/" read ALLOW_PROTOCOL ALLOW_PORTS ; do OLD_IFS3=$IFS IFS="," for ALLOW_PORT in $ALLOW_PORTS ; do eval $IPT -A $ALLOW_CHAIN $STR_ALLOW_INTERFACE \ -p $ALLOW_PROTOCOL -s $REMOTE_HOST --dport $ALLOW_PORT \ -m recent --seconds $ALLOW_SECONDS \ --rcheck --name $RULEN-$HOSTN-$(($PHASE+1)) \ -j ACCEPT done IFS=$OLD_IFS3 done <<< $ALLOW_CONNECTION done done IFS=$OLD_IFS done <<< $RULE done