#!/bin/bash # IPTABLES FIREWALL script for the Linux 2.6 Kernel # by wireddd #debug="1" conffile=/home/wired/firewall.conf # location of various binaries IPTABLES=/sbin/iptables LSMOD=/sbin/lsmod DEPMOD=/sbin/depmod MODPROBE=/sbin/modprobe GREP=/bin/grep AWK=/usr/bin/awk SED=/bin/sed IFCONFIG=/sbin/ifconfig DATE=/bin/date PS=/bin/ps if [ "$debug" ] then MODPROBE="$MODPROBE -n" fi UNIVERSE="0.0.0.0/0" arrBlockedVpnPorts+=("21") arrBlockedVpnPorts+=("80") arrBlockedVpnPorts+=("445") arrBlockedVpnPorts+=("135") arrBlockedVpnPorts+=("137") arrBlockedVpnPorts+=("138") arrBlockedVpnPorts+=("139") arrBlockedVpnPorts+=("2049") # array of kernel modules to load KernelModules+=("ip_tables") KernelModules+=("ip_conntrack") KernelModules+=("ip_conntrack_ftp") KernelModules+=("ip_conntrack_irc") KernelModules+=("iptable_nat") KernelModules+=("ip_nat_ftp") KernelModules+=("ip_nat_irc") toLower() { echo $1 | tr "[:upper:]" "[:lower:]" } toUpper() { echo $1 | tr "[:lower:]" "[:upper:]" } trimWhiteSpace() { x=$1 # Remove leading whitespace: while [[ $x = [$' \t\n']* ]]; do x=${x#[$' \t\n']}; done # And now trailing: while [[ $x = *[$' \t\n'] ]]; do x=${x%[$' \t\n']}; done echo $x } IpAndNetmasktoNetwork() { # expects $1 to be an ip address # expects $2 to be a netmask IP1="${1%.*.*.*}" IP2="${1%.*.*}" IP2="${IP2#*.}" IP3="${1%.*}" IP3="${IP3#*.*.}" IP4="${1#*.*.*.}" NM1="${2%.*.*.*}" NM2="${2%.*.*}" NM2="${NM2#*.}" NM3="${2%.*}" NM3="${NM3#*.*.}" NM4="${2#*.*.*.}" let "ipdec=$IP4 + (256*$IP3) + (256*256*$IP2) + (256*256*256*$IP1)" let "nmdec=$NM4 + (256*$NM3) + (256*256*$NM2) + (256*256*256*$NM1)" let "ipnet=$ipdec%$nmdec" count=0 let "nmtemp=$nmdec" while [ $nmtemp -eq $nmdec ] do let "count+=1" let "nmtemp >>= $count+1" let "nmtemp <<= $count+1" done ipnet=$ipdec let "ipnet >>= $count" let "ipnet <<= $count" let "bits=32-$count" let "IPNET1=$ipnet/256/256/256" let "IPNET2=($ipnet-($IPNET1*256*256*256))/256/256" let "IPNET3=($ipnet-($IPNET1*256*256*256)-($IPNET2*256*256))/256" let "IPNET4=($ipnet-($IPNET1*256*256*256)-($IPNET2*256*256)-($IPNET3*256))" ipnet="$IPNET1.$IPNET2.$IPNET3.$IPNET4/$bits" echo $ipnet } addtolog () { if [ -z $2 ] || [ $2 -le $LogLevel ] then if [ "$debug" ] then echo "`$DATE $dateformat`: firewall script: $1" else echo "`$DATE $dateformat`: firewall script: $1" >> $LogFile fi fi } readconf () { sectionName="" typeName="" while read raw do raw="`trimWhiteSpace "$raw"`" line="$raw" line="`toLower "$line"`" if [ -n "$line" ] then if [ "${line:0:1}" != "#" ] then if [ -n "$sectionName" ] then if [ -n "$typeName" ] then if [ "$line" == "end type" ] then typeName="" elif [ "$typeName" == "ip" ] then arrBlockedIPs+=("$line") elif [ "$typeName" == "ports" ] then arrBlockedExtIPPorts+=("`toUpper "$line"`") else echo "Warning: bad data in conf: $line" fi else if [ "$line" == "end section" ] then sectionName="" elif [ "${line:0:5}" == "type " ] then typeName="${line:5}" elif [ "$sectionName" == "blocked" ] then echo "Warning: bad data in conf: $line" elif [ "$sectionName" == "forward" ] then arrPortsToForward+=("${line:8}") fi fi else if [ "${line:0:1}" != "#" ] then if [ "${line:0:8}" == "section " ] then sectionName="${line:8}" elif [ "${line:0:9}" == "loglevel " ] then LogLevel="${line:9}" elif [ "${raw:0:8}" == "logfile " ] then LogFile="${line:8}" elif [ "${raw:0:7}" == "intinf " ] then INTIF="${line:6}" elif [ "${raw:0:7}" == "extinf " ] then EXTIF="${line:6}" elif [ "${line:0:11}" == "dateformat " ] then dateformat="${raw:11}" elif [ "${line:0:6}" == "intip " ] then INTIP="${raw:6}" elif [ "${line:0:6}" == "extip " ] then EXTIP="${raw:6}" elif [ "${line:0:7}" == "intnet " ] then INTNET="${raw:7}" elif [ "${line:0:6}" == "intnm " ] then INTNM="${raw:6}" else echo "Warning: bad data in conf: $line" fi fi fi fi fi if [ -z "$dateformat" ] then dateformat="+%Y.%m.%d_%T" fi if [ -z "$INTIP" ] then INTIP="`/sbin/ifconfig $INTIF | $GREP 'inet addr' | $AWK '{print $2}' | $SED -e 's/.*://'`" fi if [ -z "$INTNM" ] then INTNM="`/sbin/ifconfig $INTIF | $GREP 'inet addr' | $AWK '{print $4}' | $SED -e 's/.*://'`" fi if [ -z "$EXTIP" ] then EXTIP="`/sbin/ifconfig $EXTIF | $GREP 'inet addr' | $AWK '{print $2}' | $SED -e 's/.*://'`" fi if [ -z "$INTNET" ] then INTNET="`IpAndNetmasktoNetwork "$INTIP" "$INTNM"`" fi done < $conffile } loadKernelModules () { addtolog "Loading Kernel Modules" 2 # probe all modules /sbin/depmod -a if [ $? -ne 0 ] then addtolog "Command Failed: /sbin/depmod -a" exit 1 fi for ModuleToLoad in "${KernelModules[@]}" do if [ -z "` $LSMOD | $GREP $ModuleToLoad | $AWK {'print $1'} `" ] then if [ -z "`$MODPROBE -l $ModuleToLoad`" ] then addtolog "FATAL ERROR: Module Not Found: $ModuleToLoad" exit 1 fi $MODPROBE -q $ModuleToLoad if [ $? -ne 0 ] then addtolog "FATAL ERROR: Module Failed To Load: $ModuleToLoad" exit 1 fi fi done } enableIpForwarding () { addtolog "Enabling IP forwarding" 2 echo "1" > /proc/sys/net/ipv4/ip_forward echo "1" > /proc/sys/net/ipv4/ip_dynaddr } buildIpTablesRules () { addtolog "Building iptables Rules" 2 # Clear any existing rules and setting default policy to DROP arrIpTablesArg+=("-P INPUT DROP") arrIpTablesArg+=("-P OUTPUT DROP") arrIpTablesArg+=("-P FORWARD DROP") arrIpTablesArg+=("-F INPUT ") arrIpTablesArg+=("-F OUTPUT ") arrIpTablesArg+=("-F FORWARD ") arrIpTablesArg+=("-F -t nat") # Flush the user chain.. if it exists if [ "$debug" -o "`$IPTABLES -L | $GREP drop-and-log-it`" ] then arrIpTablesArg+=("-F drop-and-log-it") fi # Delete all User-specified chains arrIpTablesArg+=("-X") # Reset all IPTABLES counters arrIpTablesArg+=("-Z") # Creating a DROP chain arrIpTablesArg+=("-N drop-and-log-it") arrIpTablesArg+=("-A drop-and-log-it -j LOG --log-level info ") arrIpTablesArg+=("-A drop-and-log-it -j REJECT") addtolog "Building iptables Rules: INPUT rulesets" 4 ######### INPUT CHAIN ############ # add rules to block ip addresses from array for BlockedIP in "${arrBlockedIPs[@]}" do arrIpTablesArg+=(" -A INPUT -s $BlockedIP -j drop-and-log-it") done # add rules to block Incoming connections to ports on the External Ip address for BlockedExtIPPort in "${arrBlockedExtIPPorts[@]}" do read proto port <<< "$BlockedExtIPPort" if [ -z "$proto" -o -z "$port" ] then addtolog "Warning: Blocked Port Syntax Error: $BlockedExtIPPort" else arrIpTablesArg+=("-A INPUT -d $EXTIP -p $proto --dport $port -j drop-and-log-it") fi done # loopback interfaces are valid. arrIpTablesArg+=("-A INPUT -i lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT") ##----------------------------------------------------------------- #iptables -A INPUT -i eth0 -s 192.168.10.121 -j drop-and-log-it # build rules for blocking vpn ports for BlockedPort in "${arrBlockedVpnPorts[@]}" do arrIpTablesArg+=("-A INPUT -i tun+ -p TCP --dport $BlockedPort -j REJECT") done arrIpTablesArg+=("-A INPUT -i tun+ -d 192.168.10.38 -j ACCEPT") #iptables -A FORWARD -i tun+ -j ACCEPT # local interface, local machines, going anywhere is valid arrIpTablesArg+=("-A INPUT -i $INTIF -s $INTNET -d $UNIVERSE -j ACCEPT") # remote interface, claiming to be local machines, IP spoofing, get lost arrIpTablesArg+=("-A INPUT -i $EXTIF -s $INTNET -d $UNIVERSE -j drop-and-log-it") # remote interface, any source, going to permanent PPP address is valid arrIpTablesArg+=("-A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -j ACCEPT") # Allow any related traffic coming back to the MASQ server in arrIpTablesArg+=("-A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state --state ESTABLISHED,RELATED -j ACCEPT") # OPTIONAL: Uncomment the following two commands if plan on running # an Apache Web site on the firewall server itself # #echo -e " - Allowing EXTERNAL access to the WWW server" #iptables -A INPUT -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -p tcp -s $UNIVERSE -d $EXTIP --dport 80 -j ACCEPT #iptables -A INPUT -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -s $UNIVERSE -d 192.168.10.12 -p tcp --dport 80 -j ACCEPT arrIpTablesArg+=("-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT") arrIpTablesArg+=("-A INPUT -m state --state NEW -i ! $EXTIF -j ACCEPT") arrIpTablesArg+=("-A INPUT -i $EXTIF -d 255.255.255.255 -p udp --dport 68 -j ACCEPT") # Catch all rule, all other incoming is denied and logged. arrIpTablesArg+=("-A INPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it") addtolog "Building iptables Rules: OUTPUT rulesets" 4 ########## OUTPUT CHAIN ############### # loopback interface is valid. arrIpTablesArg+=("-A OUTPUT -o lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT") arrIpTablesArg+=("-A OUTPUT -o tun+ -s 192.168.10.38 -j ACCEPT") # local interfaces, any source going to local net is valid arrIpTablesArg+=("-A OUTPUT -o $INTIF -s $EXTIP -d $INTNET -j ACCEPT") # local interface, any source going to local net is valid arrIpTablesArg+=("-A OUTPUT -o $INTIF -s $INTIP -d $INTNET -j ACCEPT") # outgoing to local net on remote interface, stuffed routing, deny arrIpTablesArg+=("-A OUTPUT -o $EXTIF -s $UNIVERSE -d $INTNET -j drop-and-log-it") # anything else outgoing on remote interface is valid arrIpTablesArg+=("-A OUTPUT -o $EXTIF -s $EXTIP -d $UNIVERSE -j ACCEPT") # Catch all rule, all other outgoing is denied and logged. arrIpTablesArg+=("-A OUTPUT -s $UNIVERSE -d $UNIVERSE -j drop-and-log-it") addtolog "Building iptables Rules: FORWARD rulesets" 4 ############# FORWARD CHAIN ############## # build rules for port forwarding for PortToForward in "${arrPortsToForward[@]}"; do read host proto port <<< "$PortToForward" arrIpTablesArg+=("-A FORWARD -i $EXTIF -m state --state NEW,ESTABLISHED,RELATED -s $UNIVERSE -d $host -p $proto --dport $port -j ACCEPT") done for PortToForward in "${arrPortsToForward[@]}"; do read host proto port <<< "$PortToForward" arrIpTablesArg+=("-t nat -A PREROUTING -p $proto --dport $port -i $EXTIF -j DNAT --to $host") done # forwarding rules for vpn route arrIpTablesArg+=("-A FORWARD -i tun+ -o $INTIF -j ACCEPT") arrIpTablesArg+=("-A FORWARD -i $INTIF -o tun+ -j ACCEPT") arrIpTablesArg+=("-A FORWARD -i tun+ -o $EXTIF -j drop-and-log-it") arrIpTablesArg+=("-A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT") arrIpTablesArg+=("-A FORWARD -i $INTIF -o $EXTIF -j ACCEPT") # Catch all rule, all other forwarding is denied and logged. arrIpTablesArg+=("-A FORWARD -j drop-and-log-it") # Enable SNAT (MASQUERADE) functionality on $EXTIF arrIpTablesArg+=("-t nat -A POSTROUTING -o $EXTIF -j SNAT --to $EXTIP") #limit upload speed #iptables -t mangle -A FORWARD -s 192.168.10.0/24 -j MARK --set-mark 3 #iptables -t mangle -A FORWARD -s $EXTIP -j MARK --set-mark 3 #limit download speed #iptables -t mangle -A FORWARD -s ! 192.168.10.0/24 -d 192.168.1.0/24 -j MARK --set-mark 4 #iptables -t mangle -A FORWARD -s ! 192.168.10.0/24 -d $EXTIP -j MARK --set-mark 4 addtolog "Building iptables Rules: Complete" 3 } loadIpTablesRules () { addtolog "Loading iptables rules" 2 for IpTablesArg in "${arrIpTablesArg[@]}" do if [ $debug ] then echo "$IPTABLES $IpTablesArg" else $IPTABLES $IpTablesArg if [ $? -ne 0 ] then addtolog "Command Failed: $IPTABLES $IpTablesArg" exit 1 fi fi done addtolog "Loading iptables Rules: Complete" 3 } loadNoip2 () { if [ ! "`$PS aux | $GREP noip2 | $GREP -v grep`" ] then /usr/local/bin/noip2 if [ $? -ne 0 ] then addtolog "Failed to load noip2" else addtolog "noip2 Loaded" 2 fi else addtolog "noip2 is allready running" 4 fi } #------- INIT -------- readconf addtolog "Running" 1 buildIpTablesRules if [ -z "$debug" ] then loadKernelModules fi loadIpTablesRules if [ -z "$debug" ] then enableIpForwarding fi loadNoip2 addtolog "Complete" 1 exit 0