#!/bin/sh # # p2partisan v3.01 (28/08/2014) # # ########################################### # Adjust location where the files are kept P2Partisandir=/cifs1/p2partisan # # Edit the file "blacklists" to customise if needed # Edit the "whitelist" to overwrite the blacklist if needed # # Enable logging? Use only for troubleshooting. 0=off 1=on syslogs=1 # Maximum number of logs to be recorded in a given 60 min # Consider set this very low (like 3 or 6) once your are # happy with the installation. To troubleshoot blocked # connection close all the secondary traffic e.g. p2p # and try a connection to the blocked site/port you should # find a reference in the logs. maxloghour=1 # # What do you want to block? # 1) Input (Router only, running transmission?) # 2) LAN (LAN clients only) # 3) Both *default protection=3 # # ports to be whitelisted. Whitelisted ports will never be # blocked no matter what the source/destination IP is. # This is very important if you're running a service like # e.g. SMTP/HTTP/IMAP/else. Separate value in the list below # with commas - NOTE: Leave 80 and 443 untouched, add custom ports only # you might want to add remote admin and VPN ports here if any. # Standard iptables syntax, individual ports divided by "," and ":" to # define a range e.g. "80,443,2100:2130". Do not whitelist you P2P client! whiteports="21,25,53,80,123,443,1194:1196" # # Fastrouting will process the IP classes very quickly but use # Lot of resources. If you disable the effect is transparent # but the full process will take minutes rather than seconds # 0=disabled 1=enabled fastroutine=1 # # Enable check on script availability to help autorun # E.g. wait for the file to be available in cifs before run it # instead of quit with a file missing error autorun_availability_check=1 # # Schedule updates? (once a week is plenty) schedule="30 4 * * 1" # testip="8.8.8.8" # ########################################### # Wait until Internet is available while : do ping -c 3 $testip >/dev/null 2>&1 if [ $? = 0 ]; then break fi sleep 2 done pidfile=/var/run/p2partisan.pid cd $P2Partisandir version=`head -3 ./p2partisan.sh | tail -1 | cut -f 3- -d " "` alias ipset='/bin/nice -n19 /usr/sbin/ipset' alias sed='/bin/nice -n19 /bin/sed' alias iptables='/usr/sbin/iptables' alias service='/sbin/service' alias plog='logger -t P2PARTISAN -s' now=`date +"%H:%M:%S - %d/%m/%y"` wanif=`nvram get wan_ifname` lanif=`nvram get lan_ifname` psoftstop() { ./iptables-del 2> /dev/null plog "Stopping P2Partisan" [ -f $pidfile ] && rm -f "$pidfile" 2> /dev/null } pblock() { plog "P2PArtisan: Applying paranoia block" iptables -N PARANOIA-DROP 2> /dev/null whiteports_number=`echo $whiteports | tr -d '\n' | sed 's/,/,\n/g' | sed 's/:/:\n/g' | wc -l` a=1 b=8 rounds=`echo $(( $whiteports_number / $b ))` if [ $rounds -eq 0 ]; then rounds="1"; fi while [ $rounds -gt 0 ] do w=`echo $whiteports | cut -d"," -f $a-$b` a=`echo $(( $a + $b ))` b=`echo $(( $b + $b ))` whitep="${whitep}iptables -A PARANOIA-DROP -p tcp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A PARANOIA-DROP -p udp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A PARANOIA-DROP -p tcp --match multiport --dports $w -j ACCEPT 2> /dev/null iptables -A PARANOIA-DROP -p udp --match multiport --dports $w -j ACCEPT 2> /dev/null " rounds=`echo $(( $rounds - 1 ))` done iptables -A PARANOIA-DROP -m limit --limit $maxloghour/hour --limit-burst 5 -j LOG --log-prefix "P2Partisan Rejected (paranoia): " --log-level 1 2> /dev/null iptables -A PARANOIA-DROP -j DROP iptables -I wanin 1 -i $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null iptables -I wanout 1 -o $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null iptables -I INPUT 1 -i $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null iptables -I OUTPUT 1 -o $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null } punblock() { while iptables -L wanin 2> /dev/null | grep "PARANOIA-DROP" do iptables -D wanin -i $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null done while iptables -L wanout 2> /dev/null | grep "PARANOIA-DROP" do iptables -D wanout -o $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null done while iptables -L OUTPUT 2> /dev/null | grep "PARANOIA-DROP" do iptables -D OUTPUT -o $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null done while iptables -L INPUT 2> /dev/null | grep "PARANOIA-DROP" do iptables -D INPUT -i $wanif -m state --state NEW -j PARANOIA-DROP 2> /dev/null done iptables -F PARANOIA-DROP 2> /dev/null && plog "P2PArtisan: Removing paranoia block" iptables -X PARANOIA-DROP 2> /dev/null } pforcestop() { while iptables -L wanin 2> /dev/null | grep P2PARTISAN-IN do iptables -D wanin -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null done while iptables -L wanout 2> /dev/null | grep P2PARTISAN-OUT do iptables -D wanout -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null done while iptables -L INPUT | grep P2PARTISAN-IN do iptables -D INPUT -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null done while iptables -L INPUT | grep P2PARTISAN-OUT do iptables -D INPUT -i $lanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null done while iptables -L OUTPUT | grep P2PARTISAN-OUT do iptables -D OUTPUT -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null done iptables -F P2PARTISAN-DROP-IN 2> /dev/null iptables -F P2PARTISAN-DROP-OUT 2> /dev/null iptables -F P2PARTISAN-IN 2> /dev/null iptables -F P2PARTISAN-OUT 2> /dev/null iptables -X P2PARTISAN-DROP-IN 2> /dev/null iptables -X P2PARTISAN-DROP-OUT 2> /dev/null iptables -X P2PARTISAN-IN 2> /dev/null iptables -X P2PARTISAN-OUT 2> /dev/null ipset -F for i in `ipset --list | grep Name | cut -f2 -d ":" `; do ipset -X $i done chmod 777 ./*.gz [ -f iptables-add ] && rm iptables-add [ -f iptables-del ] && rm iptables-del [ -f ipset-del ] && rm ipset-del [ -f $pidfile ] && rm -f "$pidfile" 2> /dev/null plog "Unloading ipset modules" lsmod | grep "ipt_set" > /dev/null 2>&1 && sleep 2 ; rmmod -f ipt_set 2> /dev/null lsmod | grep "ip_set_iptreemap" > /dev/null 2>&1 && sleep 2 ; rmmod -f ip_set_iptreemap 2> /dev/null lsmod | grep "ip_set" > /dev/null 2>&1 && sleep 2 ; rmmod -f ip_set 2> /dev/null plog "Stopping P2Partisan" } pstatus() { running3=`iptables -L | grep P2PARTISAN-IN 2> /dev/null | wc -l` running4=`[ -f $pidfile ] && echo 1 || echo 0` running5=`nvram get script_fire | grep p2partisan >/dev/null && echo Yes || echo No` running6=`cru l | grep P2Partisan-update >/dev/null && echo Yes || echo No` running7=`tail -200 /var/log/messages | grep Rejected | tail -1` from=`head -1 ./iptables-add 2> /dev/null | cut -c3-` drop_packet_count_in=`iptables -vL P2PARTISAN-DROP-IN 2> /dev/null| grep " DROP " | awk '{print $1}'` drop_packet_count_out=`iptables -vL P2PARTISAN-DROP-OUT 2> /dev/null| grep " REJECT " | awk '{print $1}'` if [[ $running3 -eq "0" ]] && [[ $running4 -eq "0" ]]; then running8=No elif [[ $running3 -eq "0" ]] && [[ $running4 -eq "1" ]]; then running8=Loading... elif [[ $running3 -gt "0" ]] && [[ $running4 -eq "0" ]]; then running8=Not quite... try to run \"p2partisan.sh update\" else running8=Yes fi echo "################### P2Partisan ########################## # Release version: $version ################# P2Partisan status ##################### # P2Partisan running: $running8 # P2Partisan autorun: $running5 # P2Partisan scheduled: $running6 ######################################################### # P2Partisan activity since: $from # Dropped connections inbound: $drop_packet_count_in # Rejected connections outbound: $drop_packet_count_out ################# Last log recorded ##################### # Remember your max logs per hour is set to: $maxloghour $running7 #########################################################" } if [ $autorun_availability_check = 1 ]; then av="while true; do [ -f $P2Partisandir/p2partisan.sh ] && break || sleep 5; done ;" fi pautorunset() { p=`nvram get script_fire | grep "p2partisan.sh" | grep -v cru | wc -l` if [ $p -eq "0" ] ; then t=`nvram get script_fire`; t=`printf "$t\n$av$P2Partisandir/p2partisan.sh\n"` ; nvram set "script_fire=$t" fi plog "P2Partisan AUTO RUN is ON" nvram commit } pautorununset() { p=`nvram get script_fire | grep "p2partisan.sh" | grep -v cru | wc -l` if [ $p -eq "1" ]; then t=`nvram get script_fire`; t=`printf "$t\n$P2Partisandir/p2partisan.sh\n" | grep -v p2partisan` ; nvram set "script_fire=$t" fi plog "P2Partisan AUTO RUN is OFF" nvram commit } pscheduleset() { cru d P2Partisan-update cru a P2Partisan-update "$schedule $P2Partisandir/p2partisan.sh paranoia-update" pp=`nvram get script_fire | grep "p2partisan.sh" | grep -v cru | wc -l` p=`nvram get script_fire | grep "cru a P2Partisan-update" | wc -l` if [ $p -eq "0" ] ; then if [ $pp -eq "0" ]; then t=`nvram get script_fire`; t=`printf "$t\ncru a P2Partisan-update \"$schedule $P2Partisandir/p2partisan.sh paranoia-update\"\n"` ; nvram set "script_fire=$t" else pautorununset t=`nvram get script_fire`; t=`printf "$t\ncru a P2Partisan-update \"$schedule $P2Partisandir/p2partisan.sh paranoia-update\"\n"` ; nvram set "script_fire=$t" pautorunset fi fi plog "P2Partisan AUTO UPDATE is ON" nvram commit } pscheduleunset() { cru d P2Partisan-update p=`nvram get script_fire | grep "cru a P2Partisan-update" | wc -l` if [ $p -eq "1" ] ; then t=`nvram get script_fire`; t=`printf "$t\ncru a P2Partisan-update \"$schedule $P2Partisandir/p2partisan.sh paranoia-update\"\n" | grep -v "cru a P2Partisan-update"` ; nvram set "script_fire=$t" fi plog "P2Partisan AUTO UPDATE is OFF" nvram commit } pstart() { running4=`[ -f $pidfile ] && echo 1 || echo 0` if [ $running4 -eq "0" ] ; then echo $$ > $pidfile sleep 2 [ -f iptables-add ] && rm iptables-add [ -f iptables-del ] && rm iptables-del [ -f ipset-del ] && rm ipset-del echo "### PREPARATION ###" echo "Loading the ipset modules" lsmod | grep "ip_set" > /dev/null 2>&1 || insmod ip_set lsmod | grep "ip_set_iptreemap" > /dev/null 2>&1 || insmod ip_set_iptreemap lsmod | grep "ipt_set" > /dev/null 2>&1 || insmod ipt_set counter=0 pos=1 couscous=`cat blacklist-custom | grep -v "^#" | grep -v "^$" | wc -l` echo "### CUSTOM BLACKLIST ### blacklist-custom file -> $couscous entries found" if [ $couscous -eq "0" ]; then echo "No custom blacklist entries found: skipping" else echo "loading blacklist #$counter --> ***Custom IP blacklist***" ipset --create blacklist-custom iptreemap if [ -e blacklist-custom ]; then for IP in `cat blacklist-custom | grep -v "^#" | grep -v "^$" | cut -d: -f2` do ipset -A blacklist-custom $IP done fi fi echo "### WHITELIST ###" whiteports_number=`echo $whiteports | tr -d '\n' | sed 's/,/,\n/g' | sed 's/:/:\n/g' | wc -l` a=1 b=8 rounds=`echo $(( $whiteports_number / $b ))` if [ $rounds -eq 0 ]; then rounds="1"; fi while [ $rounds -gt 0 ] do w=`echo $whiteports | cut -d"," -f $a-$b` a=`echo $(( $a + $b ))` b=`echo $(( $b + $b ))` echo "loading whitelisted ports $w exemption" whitep="${whitep}iptables -A P2PARTISAN-IN -p tcp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-IN -p udp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-IN -p tcp --match multiport --dports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-IN -p udp --match multiport --dports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-OUT -p tcp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-OUT -p udp --match multiport --sports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-OUT -p tcp --match multiport --dports $w -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-OUT -p udp --match multiport --dports $w -j ACCEPT 2> /dev/null " rounds=`echo $(( $rounds - 1 ))` done echo "# $now iptables -N P2PARTISAN-IN 2> /dev/null iptables -N P2PARTISAN-OUT 2> /dev/null iptables -N P2PARTISAN-DROP-IN 2> /dev/null iptables -N P2PARTISAN-DROP-OUT 2> /dev/null iptables -F P2PARTISAN-IN 2> /dev/null iptables -F P2PARTISAN-OUT 2> /dev/null iptables -F P2PARTISAN-DROP-IN 2> /dev/null iptables -F P2PARTISAN-DROP-OUT 2> /dev/null iptables -A P2PARTISAN-IN -m set --set blacklist-custom src -j P2PARTISAN-DROP-IN 2> /dev/null iptables -A P2PARTISAN-OUT -m set --set blacklist-custom src -j P2PARTISAN-DROP-OUT 2> /dev/null $whitep" >> iptables-add echo "# $now iptables -D wanin -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -D wanout -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null iptables -D INPUT -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -D INPUT -i $lanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -D OUTPUT -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null iptables -F P2PARTISAN-DROP-IN 2> /dev/null iptables -F P2PARTISAN-DROP-OUT 2> /dev/null iptables -F P2PARTISAN-IN 2> /dev/null iptables -F P2PARTISAN-OUT 2> /dev/null iptables -X P2PARTISAN-IN 2> /dev/null iptables -X P2PARTISAN-OUT 2> /dev/null iptables -X P2PARTISAN-DROP-IN 2> /dev/null iptables -X P2PARTISAN-DROP-OUT 2> /dev/null" >> iptables-del echo "preparing the IP whitelist for the iptables" #Load the whitelist if [ "$(ipset --swap whitelist whitelist 2>&1 | grep 'Unknown set')" != "" ] then ipset --create whitelist iptreemap cat whitelist | grep -v "^10." | grep -v "^172.16." | grep -v "^192.168." | ( while read IP do echo "$IP" | grep "^#" >/dev/null 2>&1 && continue echo "$IP" | grep "^$" >/dev/null 2>&1 && continue ipset -A whitelist $IP done ) fi echo "# $now ipset -F ipset -X blacklist-custom ipset -X whitelist" > ipset-del echo "loading the IP whitelist" echo "iptables -A P2PARTISAN-IN -m set --set whitelist src -j ACCEPT 2> /dev/null iptables -A P2PARTISAN-OUT -m set --set whitelist dst -j ACCEPT 2> /dev/null" >> iptables-add if [ $syslogs -eq "1" ]; then echo "iptables -A P2PARTISAN-DROP-IN -m limit --limit $maxloghour/hour --limit-burst 1 -j LOG --log-prefix \"P2Partisan Dropped: \" --log-level 1 2> /dev/null" >> iptables-add echo "iptables -A P2PARTISAN-DROP-OUT -m limit --limit $maxloghour/hour --limit-burst 1 -j LOG --log-prefix \"P2Partisan Rejected: \" --log-level 1 2> /dev/null" >> iptables-add fi echo "iptables -A P2PARTISAN-DROP-IN -j DROP" >> iptables-add echo "iptables -A P2PARTISAN-DROP-OUT -j REJECT --reject-with icmp-admin-prohibited" >> iptables-add echo "### BLACKLISTs ###" cat blacklists | ( while read line do echo "$line" | grep "^#" >/dev/null 2>&1 && continue echo "$line" | grep "^$" >/dev/null 2>&1 && continue counter=`expr $counter + 1` name=`echo $line |cut -d ' ' -f1` url=`echo $line |cut -d ' ' -f2` echo "loading blacklist #$counter --> ***$name***" if [ $fastroutine -eq "1" ]; then if [ "$(ipset --swap $name $name 2>&1 | grep 'Unknown set')" != "" ] then [ -e $name.gz ] || wget -q -O $name.gz "$url" { echo "-N $name iptreemap" gunzip -c $name.gz | \ sed -e "/^[\t ]*#.*\|^[\t ]*$/d;s/^.*:/-A $name /" echo COMMIT } | ipset -R fi else if [ "$(ipset --swap $name $name 2>&1 | grep 'Unknown set')" != "" ] then ipset --create $name iptreemap [ -e $name.lst ] || wget -q -O - "$url" | gunzip | cut -d: -f2 | grep -E "^[-0-9.]+$" > $name.lst for IP in $(cat $name.lst) do ipset -A $name $IP done fi fi echo "ipset -X $name " >> ipset-del echo "iptables -A P2PARTISAN-IN -m set --set $name src -j P2PARTISAN-DROP-IN 2> /dev/null iptables -A P2PARTISAN-OUT -m set --set $name dst -j P2PARTISAN-DROP-OUT 2> /dev/null" >> iptables-add done ) if [ $protection -eq "1" ]; then echo "iptables -I INPUT $pos -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -I OUTPUT $pos -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null" >> iptables-add elif [ $protection -eq "2" ]; then echo "iptables -I wanin $pos -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -I wanout $pos -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null iptables -I INPUT $pos -i $lanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null" >> iptables-add elif [ $protection -eq "3" ]; then echo "iptables -I INPUT $pos -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -I INPUT $pos -i $lanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null iptables -I OUTPUT $pos -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null iptables -I wanin $pos -i $wanif -m state --state NEW -j P2PARTISAN-IN 2> /dev/null iptables -I wanout $pos -o $wanif -m state --state NEW -j P2PARTISAN-OUT 2> /dev/null" >> iptables-add fi chmod 777 ./iptables-* chmod 777 ./ipset-* ./iptables-add #protecting plog "... P2Partisan started." p=`nvram get dnsmasq_custom | grep log-async | wc -l` if [ $p -eq "1" ]; then plog "log-async found under dnsmasq -> OK" else plog " It appears like you don't have a log-async parameter in your dnsmasq config. This is strongly suggested due to the amount of logs involved. please consider adding the following command under Advanced/DHCP/DNS /Dnsmasq Custom configuration log-async=10 " fi punblock #remove paranoia DROPs if any else echo " It appears like P2Partisan is already running. Skipping... If this is not what you expected? Try: p2partisan.sh update " fi } for p in $1 do case "$p" in "start") pstart exit ;; "stop") pforcestop exit ;; "restart") pscheduleunset psoftstop pscheduleset ;; "status") pstatus exit ;; "update") pscheduleunset pforcestop pscheduleset ;; "paranoia-update") pscheduleunset pblock pforcestop pscheduleset ;; "autorun-on") pautorunset exit ;; "autorun-off") pautorununset exit ;; "autoupdate-on") pscheduleset exit ;; "autoupdate-off") pscheduleunset exit ;; "help") echo " P2Partisan parameters: help Display this text start Starts the process (this runs also if no option is provided) stop Stops P2Partisan restart Soft restart, quick, updates iptables only update Hard restart, slow removes p2partisan, updates the lists and does a fresh start paranoia-update Like update but blocks any new connection until P2Partisan is running again status Display P2Partisan running status + extra info autorun-on Sets P2Partisan to boot with the router autorun-off Sets P2Partisan not to boot with the router autoupdate-on Sets automatic updates on autoupdate-off Sets automatic updates off " exit ;; *) echo "parameter not valid. please run: p2partisan.sh help " exit ;; esac done pstart exit