#!/bin/bash DEBUG=0 ADD_COMMENT=1 PERMIT='ACCEPT' DENY='DROP' IN=$1 [ ! -f "$IN" ] && echo "Usage : $0 [rule file] [add to iptables command] [-d]" && exit 1 ADD_TO_IPTABLES_CMD=$2 [ "$2" == "-d" -o "$3" == "-d" ] && DEBUG=1 function get_word() { echo "$1"|awk "{print \$$2}" } function is_valid_ip() { ip="$1" if [ "$( echo "$ip"| egrep -c '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' )" == "1" ] then for i in $( seq 1 4 ) do O=$( echo "$ip"|cut -d '.' -f $i ) [ $O -lt 0 -o $O -gt 254 ] && echo $i && return $i done echo 0 return 0 fi echo 1 return 1 } function convert_mask() { mask="$1" if [ "$( echo "$mask"| egrep -c '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' )" == "1" ] then NETMASK="" for i in $( seq 1 4 ) do O=$( echo "$mask"|cut -d '.' -f $i ) [ $O -lt 0 -o $O -gt 255 ] && echo "" && return $i let o=255-O NETMASK="$NETMASK.$o" done echo $NETMASK|sed 's/^\.//' return 0 fi echo "" return 1 } function convert_netmask_to_cidr() { mask="$1" if [ "$( echo "$mask"| egrep -c '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' )" == "1" ] then CIDR=0 for i in $( seq 1 4 ) do O=$( echo "$mask"|cut -d '.' -f $i ) if [ "$O" == "0" ] then continue elif [ "$O" == "128" ] then let CIDR=CIDR+1 elif [ "$O" == "192" ] then let CIDR=CIDR+2 elif [ "$O" == "224" ] then let CIDR=CIDR+3 elif [ "$O" == "240" ] then let CIDR=CIDR+4 elif [ "$O" == "248" ] then let CIDR=CIDR+5 elif [ "$O" == "252" ] then let CIDR=CIDR+6 elif [ "$O" == "254" ] then let CIDR=CIDR+7 elif [ "$O" == "255" ] then let CIDR=CIDR+8 else echo "" return $i fi done echo $CIDR return 0 fi echo "" return 1 } function convert_ip_mask_to_arg() { IP="$1" MASK="$2" CIDR="$( convert_netmask_to_cidr "$MASK" )" if [ "$CIDR" == "" ] then echo "Error converting netmask $MASK to CIDR (Result : $CIDR | Code : $?). Stop." > /dev/stderr echo "" return 1 elif [ "$CIDR" == "32" ] then echo "$IP" elif [ "$CIDR" == "0" -a "$IP" == "0.0.0.0" ] then echo "0/0" else echo "$IP/$CIDR" fi } function print_acl_details() { echo "ACL : $line Action : $ACL_ACTION Protocole : $ACL_PROTO Groupe : $ACL_GROUP Source : $ACL_SRC_NET/$ACL_SRC_MASK Source services : '$ACL_SRC_PORTS' Destination : $ACL_DST_NET/$ACL_DST_MASK Destination services : '$ACL_DST_PORTS'" } function convert_2_iptables_cmd() { MULTIPORTS=0 CMD="iptables -I FORWARD $ADD_TO_IPTABLES_CMD" [ "$ACL_PROTO" != 'ip' ] && CMD="$CMD -p $ACL_PROTO" SRC="$( convert_ip_mask_to_arg "$ACL_SRC_NET" "$ACL_SRC_MASK" )" [ "$SRC" == "" ] && echo "ERROR : Fail to convert source" > /dev/stderr && return 1 [ "$SRC" != "0/0" ] && CMD="$CMD -s $SRC" if [ "$ACL_SRC_PORTS" != "any" ] then if [ $( echo "$ACL_SRC_PORTS"|sed 's/ /\n/'|wc -l ) -gt 1 ] then MULTIPORTS=1 PORTS="" for p in $ACL_SRC_PORTS do PORTS=",$PORTS" done CMD="$CMD -m multiport --sports $( echo "$PORTS"|sed 's/^,//' )" else CMD="$CMD --sport $ACL_SRC_PORTS" fi fi DST="$( convert_ip_mask_to_arg "$ACL_DST_NET" "$ACL_DST_MASK" )" [ "$DST" == "" ] && echo "ERROR : Fail to convert destination" > /dev/stderr && return 1 [ "$DST" != "0/0" ] && CMD="$CMD -d $DST" if [ "$ACL_DST_PORTS" != "any" ] then if [ $( echo "$ACL_DST_PORTS"|sed 's/ /\n/'|wc -l ) -gt 1 ] then PORTS="" for p in $ACL_DST_PORTS do PORTS=",$PORTS" done [ $MULTIPORTS -eq 0 ] && CMD="$CMD -m multiport" CMD="$CMD --dports $( echo "$PORTS"|sed 's/^,//' )" else CMD="$CMD --dport $ACL_DST_PORTS" fi fi if [ "$ACL_ACTION" == "permit" ] then CMD="$CMD -j $PERMIT" elif [ "$ACL_ACTION" == "deny" ] then CMD="$CMD -j $DENY" else echo "ERROR : Action '$ACL_ACTION' not recognized" > /dev/stderr return 1 fi echo $CMD } IFS=" " for line in $( cat "$IN"|egrep "^access-list " ) do # Reset word="" ACL_ACTION="" ACL_PROTO="" ACL_GROUP="" ACL_SRC_NET="" ACL_SRC_MASK="" ACL_SRC_PORTS="" ACL_DST_NET="" ACL_DST_MASK="" ACL_DST_PORTS="" field=2 ACL_GROUP="$( get_word "$line" $field )" field=3 ACL_ACTION="$( get_word "$line" $field )" if [ "$ACL_ACTION" != "permit" -a "$ACL_ACTION" != "deny" ] then echo "ERROR : Action not recognized in $( print_acl_details )" continue fi field=4 ACL_PROTO="$( get_word "$line" $field )" field=5 ACL_SRC_NET="$( get_word "$line" $field )" if [ "$ACL_SRC_NET" == "any" ] then ACL_SRC_NET="0.0.0.0" ACL_SRC_MASK="0.0.0.0" elif [ "$ACL_SRC_NET" == "host" ] then let field=field+1 ACL_SRC_NET="$( get_word "$line" $field )" [ $( is_valid_ip "$ACL_SRC_NET" ) -ne 0 ] && echo "ERROR : Source host IP address not recognized in $( print_acl_details )" && continue ACL_SRC_MASK="255.255.255.255" elif [ "$( is_valid_ip "$ACL_SRC_NET" )" == "0" ] then let field=field+1 ACL_SRC_MASK="$( get_word "$line" $field )" ACL_SRC_MASK=$( convert_mask "$ACL_SRC_MASK" ) [ "$ACL_SRC_MASK" == "" ] && echo "ERROR : Source mask not recognized in $( print_acl_details )" && continue else echo "ERROR : Source net not recognized in ACL, pass : $line" continue fi let field=field+1 word="$( get_word "$line" $field )" if [ "$word" == "eq" ] then ACL_SRC_PORTS="" while [ true ] do let field=field+1 word="$( get_word "$line" $field )" [ "$word" == "" -o "$word" == "host" -o "$word" == "any" -o "$( is_valid_ip "$word" )" == "0" ] && break ACL_SRC_PORTS="$ACL_SRC_PORTS $word" done if [ "$ACL_SRC_PORTS" == " " ] then ACL_SRC_PORTS="any" else ACL_SRC_PORTS=$( echo "$ACL_SRC_PORTS"|sed 's/^ //' ) fi else ACL_SRC_PORTS="any" fi if [ "$word" == "any" ] then ACL_DST_NET="0.0.0.0" ACL_DST_MASK="0.0.0.0" elif [ "$word" == "host" ] then let field=field+1 ACL_DST_NET="$( get_word "$line" $field )" [ $( is_valid_ip "$ACL_DST_NET" ) -ne 0 ] && echo "ERROR : Destination host IP address not recognized in $( print_acl_details )" && continue ACL_DST_MASK="255.255.255.255" elif [ "$( is_valid_ip "$word" )" == "0" ] then ACL_DST_NET="$word" let field=field+1 ACL_DST_MASK="$( get_word "$line" $field )" if [ "$ACL_DST_MASK" == "" ] then ACL_DST_MASK="255.255.255.255" else ACL_DST_MASK=$( convert_mask "$ACL_DST_MASK" ) [ "$ACL_DST_MASK" == "" ] && echo "ERROR : Destination mask not recognized in $( print_acl_details )" && continue fi fi let field=field+1 word="$( get_word "$line" $field )" if [ "$word" == "" ] then ACL_DST_PORTS="any" elif [ "$word" == "eq" ] then ACL_DST_PORTS="" while [ true ] do let field=field+1 word="$( get_word "$line" $field )" [ "$word" == "" ] && break ACL_DST_PORTS="$ACL_DST_PORTS $word" done ACL_DST_PORTS=$( echo "$ACL_DST_PORTS"|sed 's/^ //' ) else echo "ERROR : Destination port(s) specification not recognized (word = $word) in $( print_acl_details )" continue fi [ $DEBUG -eq 1 ] && print_acl_details [ $ADD_COMMENT -eq 1 ] && echo "# ACL : $line" convert_2_iptables_cmd echo done