#!/bin/sh
#avoid brute force and DOS, avbf for ftp and ssh (works the same way with other ports)
#This script works with iptables and ipt_recent module
#author: newbiefan (for asus users)
#contact: hirau@gmx.at
#special credit to: guru Al37919 @ wl500g.info, he inspired me and has done most of the job,
#I just used his thread (ipt_recent) for getting started - the rest is just reading INET ;-)
#credit goes to (and references): axel (posted in linux, security, Tipps
# and to Hergen Harnisch (uni hannover), serversupportforum.de (several users)
# and to clug wiki, ducea.com, landofthefreeish.com, debian-administration.org (article 187)
# and to bluequartz.us (Stephanie Sullivan) and several others
#Licence of this script: GNU GPL2
#
#For your own use, you can remove all the comments, but be aware: this is not a firewall
#Further, it does not block established connections! Please read manual avbf.pdf


ipt=/usr/sbin/iptables
mod_ipt=/lib/modules/2.4.37.9/ipt_recent.o
denyhosts=/opt/etc/hosts.deny
asusip=192.168.178.2
#use reject as you like
rej="REJECT --reject-with icmp-port-unreachable"
rejhur="REJECT --reject-with icmp-host-unreachable"

#check for module ipt_recent
if [ -z "`lsmod | grep ipt_recent`" ] ; then
  echo "Module ipt_recent not loaded, will do it now...."
  /sbin/insmod $mod_ipt ; sleep 2
fi

#emty all chains
$ipt -F
#and delete own chains
$ipt -X
sleep 2

#just make sure, that ips from lan and localhost get never banned and/or firewalled (this is very important in case of AP mode)
$ipt -A INPUT -s 192.168.0.0/16 -j ACCEPT
$ipt -A INPUT -s 127.0.0.1/32 -j ACCEPT

#we block everything of hosts.deny list with netmask, syntax of list: "ip/netmask"
#this allows you to block completely bad networks/provider
if [ -e $denyhosts ] ; then
 for ipnm in `cat $denyhosts` ; do
      $ipt -A INPUT -s $ipnm -j $rejhur
 done
fi

#here we start#########################################################

#we create chains
$ipt -N BRUTE
$ipt -N CONTROL
#$ipt -N BLOCKIT
$ipt -N UBLOCK
################ FILTER INPUT CONNECTIONS ##############################

#The first rule is BLOCKIT, so everything has to go through this chain
#$ipt -A INPUT -j BLOCKIT

#Limiting the incoming icmp ping request:
$ipt -A INPUT -p icmp -m limit --limit  1/s --limit-burst 1 -j ACCEPT
$ipt -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "PING-DROP:"
$ipt -A INPUT -p icmp -j $rej

#Direct NEW connections from ftp/ssh to chain BRUTE  
#$ipt -A INPUT -p tcp -m tcp --dport 21:22 --syn -m limit --limit 1/s -j LOG --log-prefix "IP TCP/SYN on PORT 21/22:"
$ipt -A INPUT -p tcp -m tcp --dport 21:22 --syn -m limit --limit 1/s -j BRUTE

#Do not allow NEW connection without syn on port 21,22
$ipt -A INPUT -p tcp -m tcp --dport 21:22 ! --syn -m state --state NEW -j LOG --log-prefix "New not syn:"
$ipt -A INPUT -p tcp -m tcp --dport 21:22 ! --syn -m state --state NEW -j $rej

#$ipt -A INPUT -m state --state NEW -p tcp --dport 21:22 -j LOG --log-prefix "IP TCP/NEW on PORT 21/22:"
$ipt -A INPUT -m state --state NEW -p tcp --dport 21:22 -j BRUTE

#reject any udp to port 21,22
#$ipt -A INPUT -m state --state NEW -p udp --dport 21:22 -j LOG --log-prefix "IP UDP on PORT 22:"
$ipt -A INPUT -m state --state NEW -p udp --dport 21:22 -j $rej

#Here we filter the wrong udp "related" packet of hackers
#$ipt -A INPUT -m state --state ESTABLISHED,RELATED -p udp --dport 22 -j LOG --log-prefix "IP UDP ESTABLISHED/RELATED on PORT 22:"
$ipt -A INPUT -m state --state ESTABLISHED,RELATED -p udp --dport 22 -j $rej

#Allow established connections or any connection to port 80 and webinterface
$ipt -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ipt -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
#$ipt -A INPUT -p tcp -m tcp --dport 88 -j ACCEPT

#Allow connections to mediaserver wizd if ports are forwarded
#$ipt -A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT
#$ipt -A INPUT -p udp -m udp --dport 8000 -j ACCEPT


#Any invalid packets are directed to chain CONTROL
$ipt -A INPUT -m state --state INVALID -j CONTROL 

#when anything comes through, which is udp, for instance a broadcast message from your network
$ipt -A INPUT -p udp -j UBLOCK

#And any other packets are rejected
$ipt -A INPUT -j LOG --log-prefix "Alarm !!!!"
$ipt -A INPUT -j REJECT

###################### END OF INPUT CHAIN ###############################


#... handling of white/blacklists in BRUTE chain ...
$ipt -A BRUTE -m recent --rcheck --seconds 900 --hitcount 3 --name BRUTE --rsource -j LOG --log-prefix "BRUTE FORCE IP banned:"
$ipt -A BRUTE -m recent --update --seconds 900 --hitcount 3 --name BRUTE --rsource -j $rejhur
$ipt -A BRUTE -m recent --set --name BRUTE --rsource -j ACCEPT
#return from chain BRUTE to INPUT
$ipt -A BRUTE -j RETURN

#Write any invalid packet to LOG and then DROP the connection
$ipt -A CONTROL -j LOG -m limit --limit 1/s --log-prefix "INVALID PACKET FROM:"
$ipt -A CONTROL -j $rejhur
$ipt -A CONTROL -j RETURN

#Chain BLOCKIT is just a placeholder for possibility to block bad ip's before any other rule
#see script checklog and add a checklog call to crontab every x minute.
#$ipt -A BLOCKIT -j RETURN

#Chain udp blocks any udp after ssh, or established connection
#broadcast messages from your network
$ipt -A UBLOCK -s 0.0.0.0 -d 255.255.255.255 -j LOG --log-prefix "LAN-PC/DEVICE-STARTUP:"
$ipt -A UBLOCK -s 0.0.0.0 -d 255.255.255.255 -j ACCEPT
#$ipt -A UBLOCK -j LOG -m limit --limit 1/s --log-prefix "UDP-ALARM FROM:"
$ipt -A UBLOCK -j $rej
$ipt -A UBLOCK -j RETURN


