MartineauPASTEBIN

HackerPorts.sh

May 3rd, 2017
320
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/sh
  2. VER="v2.03"
  3. #======================================================================================================= © 2016-2017 Martineau, v2.03
  4. #
  5. #      Report on Hacker attempts to attack local LAN ports. (Usually called by IPSET_Block.sh as part of its Summary display)
  6. #      ('IPSET_Block.sh v3.xx' if 'nolog' arg is used then this script will NOT be able to report on the attacks!!!)
  7. #      ('IPSET_Block.sh v4.xx' optionally uses an IPSET as a crude database for logging the hack attempts as well as, or in place of, Syslog messages)
  8. #
  9. #      The console display report is also created to disk and allows double-clicking on the URLs to help identify the port being attacked and its attacker.
  10. #
  11. #     HackerPorts   [help | -h] | [file_name_for report] [verbose] [syslog] [num=nn] [all] [wipe] [in=syslog_file]
  12. #
  13. #     HackerPorts
  14. #                   Will produce a summary display of the top 10 WAN blocks in three categories: (unless default 'num=nn' has been specified)
  15. #
  16. #                          4541 records scanned from Syslog ('/tmp/syslog.log')
  17. #
  18. #                          07 May 13:58:40: # Unique Ports attacked via 'eth0': 172 (out of 2119 attempts) tracked via SYSLOG, May 5 20:39:18 - May 7 13:58:36
  19. #
  20. #                          ***ATTENTION 5 GRE (Generic Route Encapsulation) aka Virtual Private Network (VPN) attacks.
  21. #
  22. #                              Top 10 Ports attacked:
  23. #                          4227 http://www.speedguide.net/port.php?port=23    e.g.  https://dnsquery.org/ipwhois/1.10.130.6
  24. #                              <...>
  25. #                              Top 10 attackers:
  26. #                            3 https://dnsquery.org/ipwhois/52.174.156.242
  27. #                              <...>
  28. #                              Last 10 most recent attackers:
  29. #                              https://dnsquery.org/ipwhois/146.185.239.117
  30. #                              <...>
  31. #
  32. #     HackerPorts   verbose
  33. #                   Will produce a summary display as above, but will also list ALL of the attacked ports and by whom! i.e. 167 in this example!!
  34. #     HackerPorts   syslog num=25
  35. #                   Will ignore the BlacklistTRK IPSET (if it exists) and use the Syslog attack messages and the top 25 (instead of 10) are listed.
  36. #     HackerPorts   all wipe
  37. #                   Will produce a summary display for ALL i.e. any interface (e.g. ppp0/vlan etc.) with the top 3 in each category listed.
  38. #                   NOTE: ALL tracking records to date will be *ERASED* from Syslog/BlacklistTRK IPSET.
  39. #     HackerPorts   syslog in=/mnt/USB/Syslog/Archive/syslog.log-20170416-144840
  40. #                   Will produce a summary display as above but will not use the current live '/tmp/syslog.log' instead '/mnt/USB/Syslog/Archive/syslog.log-20170416-144840' is used
  41. #
  42. # https://dnsquery.org/ipwhois/ is FREE but not 100% accurate?, whereas https://www.whoisxmlapi.com/ is accurate but ONLY 20 FREE IP lookups per Guest
  43.  
  44. # Print between line beginning with '#==' to first blank line inclusive
  45. ShowHelp() {
  46.     awk '/^#==/{f=1} f{print; if (!NF) exit}' $0
  47. }
  48.  
  49. # Function Parse(String delimiter(s) variable_names)
  50. Parse() {
  51.     #
  52.     #   Parse       "Word1,Word2|Word3" ",|" VAR1 VAR2 REST
  53.     #               (Effectivley executes VAR1="Word1";VAR2="Word2";REST="Word3")
  54.    
  55.     local string IFS
  56.  
  57.     TEXT="$1"
  58.     IFS="$2"
  59.     shift 2
  60.     read -r -- "$@" <<EOF
  61. $TEXT
  62. EOF
  63. }
  64. Tracking_Enabled () {
  65.  
  66. # Try and determine if Port tracking is enabled - either via Syslog or IPSET
  67.  
  68.     # I really should use a semaphore such as NVRAM variable?
  69.     #   but someone will always complain about wasting a few precious bytes? if it generates the Yellow '!'
  70.  
  71.     local STATUS=0                                  # 0-DISABLED,1-Syslog,2-IPSET,3-Both
  72.     local FN=
  73.  
  74.     if [ ! -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh" /jffs/scripts/firewall-start | grep -vE "^\#")" ];then
  75.         if [ -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh.*nolog" /jffs/scripts/firewall-start)" ];then
  76.             STATUS=1                                # Yes Syslog i.e. 'nolog' wasn't specified
  77.         else
  78.             FN="/jffs/scripts/firewall-start"
  79.         fi
  80.     else
  81.         if [ ! -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh" /jffs/scripts/services-start | grep -vE "^\#")" ];then
  82.             if [ -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh.*nolog" /jffs/scripts/services-start)" ];then
  83.                 STATUS=1                            # Yes Syslog i.e. 'nolog' wasn't specified
  84.             else
  85.                 FN="/jffs/scripts/services-start"
  86.             fi
  87.         else
  88.             if [ ! -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh" /jffs/scripts/post-mount | grep -vE "^\#")" ];then
  89.                 if [ -z "$(grep -iE "/jffs/scripts/IPSET_Block\.sh.*nolog" /jffs/scripts/post-mount)" ];then
  90.                     STATUS=1                        # Yes Syslog i.e. 'nolog' wasn't specified
  91.                 else
  92.                     FN="/jffs/scripts/post-mount"
  93.                 fi
  94.             fi
  95.         fi
  96.     fi
  97.    
  98.     if [ "$(ipset $LIST BlacklistTRK 2> /dev/null | wc -l)" -gt 0 ]; then
  99.         STATUS=$(($STATUS+2))                       # Yes - IPSET
  100.     fi
  101.  
  102.     echo $STATUS","$FN
  103.  
  104. }
  105.  
  106. Delete_TempFiles () {
  107.  
  108.     rm $LOGFILE".tmp" 2> /dev/null
  109.     rm $LOGFILE".new" 2> /dev/null
  110.    
  111.     return 0
  112. }
  113.  
  114. #==============================================Main=============================================
  115.  
  116. # Need assistance!???
  117. if [ "$1" == "help" ] || [ "$1" == "-h" ]; then
  118.     ShowHelp
  119.     exit 0
  120. fi
  121.  
  122. MYROUTER=$(nvram get computer_name)
  123.  
  124. if [ -d "/tmp/mnt/"$MYROUTER ];then
  125.     MOUNT="/tmp/mnt/"$MYROUTER
  126. else
  127.     MOUNT="/tmp"
  128. fi
  129.  
  130. SYSLOG="/tmp/syslog.log"
  131. if [ "$( echo $@ | grep -o "in=" | wc -w )" -eq 1 ];then
  132.     Parse "$( echo $@ | grep -oE "in=.*")" " =" v1 SYSLOG v3        # Use the supplied file to generate the report from.
  133.     TRACKING=1                                                      # Spoof a valid tracker status for the user file! ;-)
  134. else
  135.     # Using standard Syslog, so a quick check to ensure 'nolog' isn't specifed!
  136.    
  137.     Parse "$(Tracking_Enabled)" "," TRACKING FN
  138.  
  139.     if [ "$TRACKING" == "0" ];then
  140.         echo -e "\a\n\t***ERROR Tracking not enabled? - check '"$FN"' 'IPSET_Block.sh init' is used WITHOUT 'nolog'\n"
  141.         logger -t "($(basename $0))" $$ "***ERROR Tracking not enabled? - check '"$FN"' 'IPSET_Block.sh init' is used WITHOUT 'nolog'"
  142.         exit 96
  143.     fi
  144. fi
  145.  
  146. # Check that Syslog or the user supplied file actually exists!
  147. if [ ! -f $SYSLOG ];then
  148.     echo -e "\a\n\t***ERROR Input Syslog file '$SYSLOG' NOT found\n"
  149.     logger -t "($(basename $0))" $$ "***ERROR Input Syslog file '"$SYSLOG"' NOT found"
  150.     exit 94
  151. fi
  152.  
  153.  
  154.  
  155. if [ ! -z $1 ] && [ "$1" != "verbose" ] && [ -z $(echo $1 | grep -o "syslog") ] && \
  156.    [ -z $(echo $1 | grep -o "num=") ] && [ -z $(echo $1 | grep -o "all") ]    && \
  157.    [ -z $(echo $1 | grep -o "wipe") ] && [ -z $(echo $1 | grep -o "in=") ]    && \
  158.    [ -z $(echo $1 | grep -o "any") ];then
  159.     LOGFILE=$1
  160. else
  161.     LOGFILE=${MOUNT}/HackerReport.txt
  162. fi
  163.  
  164. Delete_TempFiles
  165.  
  166. # 380.63+ for ARM routers, IPSET v6  is available...Load appropriate IPSET modules
  167. case $(ipset -v | grep -o "v[4,6]") in
  168.   v6) MATCH_SET='--match-set'; LIST='list'; CREATE='create'; SAVE='save'; RESTORE='restore'; FLUSH='flush'; DESTROY='destroy'; ADD='add'; SWAP='swap'; IPHASH='hash:ip'; NETHASH='hash:net'; SETNOTFOUND='name does not exist'; TIMEOUT="timeout"
  169.       lsmod | grep -q "xt_set" || for module in ip_set ip_set_hash_net ip_set_hash_ip xt_set
  170.       do modprobe $module; done;;
  171.   v4) MATCH_SET='--set'; LIST='--list'; CREATE='--create'; SAVE='--save'; RESTORE='--restore'; FLUSH='--flush'; DESTROY='--destroy'; ADD='--add'; SWAP='--swap'; IPHASH='iphash'; NETHASH='nethash'; SETNOTFOUND='Unknown set'; TIMEOUT=; RETAIN_SECS=
  172.       lsmod | grep -q "ipt_set" || for module in ip_set ip_set_nethash ip_set_iphash ipt_set
  173.       do modprobe $module; done;;
  174.   *) logger -st "($(basename $0))" $$ "**ERROR** Unknown ipset version: $(ipset -v). Exiting." && (echo -e "\a";exit 99);;
  175. esac
  176.  
  177. logger -st "($(basename $0))" $$ $VER "Hacker Port attacks Report....."
  178.  
  179.  
  180. if [ "$(ipset $LIST Blacklist 2> /dev/null | wc -l)" -eq 0 ];then
  181.     echo -e "\a\n\t***ERROR IPSET Blacklist does not exist! - Please run 'IPSET_Block.sh init'\n"
  182.     logger -t "($(basename $0))" $$ "***ERROR IPSET Blacklist does not exist! - Please run 'IPSET_Block.sh init'"
  183.     exit 95
  184. fi
  185.  
  186. VERBOSE=0
  187. if [ "$( echo $@ | grep -o "verbose" | wc -w )" -eq 1 ];then
  188.     VERBOSE=1                                   # List ALL report lines rather than just the summary
  189. fi
  190.  
  191. # How many attack items to be displayed in each category
  192. TOPX=10
  193. if [ "$( echo $@ | grep -o "num=" | wc -w )" -eq 1 ];then
  194.     Parse "$( echo $@ | grep -oE "num=.*")" "=" v1 TOPX
  195.     TOPX=$(echo $TOPX | cut -d" " -f1)                      # Tacky! regexp should be used properly!
  196.     TOPX=$(echo $TOPX | sed 's/ //g')                       # Tacky! regexp should be used properly!
  197.     if [ -z "$TOPX" ] || [ -z "${TOPX##*[!0-9]*}" ] || [ "$TOPX" -eq 0 ];then   # Must be only digits and not blank or '0'
  198.         TOPX=1
  199.         echo -e "\a\n\t\e[91m***Warning \e[5m'num='\e[25m directive invalid...num=1 assumed!\e[0m"
  200.     fi
  201. fi
  202.  
  203. # Modern Firmware?
  204. if [ -z "$(which uniq)" ];then
  205.     echo -e "\a\n\t***ERROR 'uniq' utility not installed?\n"
  206.     logger -t "($(basename $0))" $$ "***ERROR 'uniq' utility not installed?"
  207.     exit 97
  208. fi
  209.  
  210. # How may input lines scanned/processed
  211. REC_CNT=0
  212.        
  213. # Does the Port tracker IPSET exist with at least 1 entry?
  214. if [ "$(ipset $LIST BlacklistTRK 2> /dev/null | wc -l)" -gt 7 ] && [ "$( echo $@ | grep -o "syslog" | wc -w )" -eq 0 ];then
  215.     ipset $LIST BlacklistTRK | grep -E "^[0-9]" | tr ",:" "  " | sort -nk3 | uniq -f2 -c | while read ITEM
  216.         do
  217.             Parse "$ITEM" " " PORTCNT SRC v3 PORT
  218.             echo -e "$(printf "%5d %-45s e.g. %s" $PORTCNT "http://www.speedguide.net/port.php?port="$PORT )" "https://dnsquery.org/ipwhois/"$SRC >> $LOGFILE.tmp
  219.         done
  220.         DTYPE="IPSET"
  221.         PERIODTXT=
  222.         REC_CNT=$(ipset $LIST BlacklistTRK | grep -E "^[0-9]" | wc -l)
  223. else
  224.     if [ "$TRACKING" == "1" ] || [ "$TRACKING" == "3" ] ;then
  225.         # Extract the relevant Hacker attempt msgs (created by /jffs/scripts/IPSET_Block.sh etc.) from file usually Syslog or an archived Syslog
  226.         IFNAME=$(nvram get wan0_ifname)
  227.         IIFXT="'"$IFNAME"'"
  228.         if [ "$( echo $@ | grep -o "all" | wc -w )" -eq 1 ];then        # WAN only report ?
  229.             IFNAME=                                                     # ALL i.e.  ANY interface e.g. 'ppp0' or 'vlan2' etc.
  230.             IIFXT="ANY interface"
  231.         fi
  232.         # Report these 'GRE' attacks separately as they don't have a DST=
  233.         # Block IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
  234.         #               SRC=114.34.75.79 DST=xxx.xxx.xxx.xxx
  235.         #               LEN=52 TOS=0x00 PREC=0x00 TTL=53 ID=63784
  236.         #               DF PROTO=47
  237.         GRE_CNT=0
  238.         GRE_CNT=$(grep -E "Block IN=$IFNAME" $SYSLOG | grep "PROTO=47" | wc -l )
  239.        
  240.         echo -e "\n\e[1;36mScanning" $SYSLOG "for" $IIFXT "violations, please wait.....\e[0m"
  241.        
  242.         # grep -E "Block IN=" /tmp/syslog.log | grep -oE "SRC=.*DPT=[0-9]+" | sed -e 's/SRC=//' -e 's/DPT=//' | awk '{ print $1" "$(NF) }' | sort -k2n | awk '{a[$2]++;}END{for (i in a)print i, a[i];}'
  243.         # Weird, need to parse the clunky old-skool way :-(
  244.         # Also wot if   'uniq -c '                                          isn't installed?
  245.         #               "awk '{a[$1]++;}END{for (i in a)print i, a[i];}'"   counts how many times first word appears
  246.         grep -E "Block IN=$IFNAME" $SYSLOG | \
  247.             grep -v "PROTO=47"             | \
  248.             sed -e 's/^.*SRC=//' -e 's/SEQ.*$//' -e 's/LEN=.*TOS//' -e 's/WINDOW.*$//' -e 's/LEN=.*$//' -e 's/DPT=//' | \
  249.             awk '{ print $1" "$(NF) }'     | \
  250.             sort -k2n                      | \
  251.             uniq -f 1 -c |
  252.         while read ITEM
  253.             do
  254.                 Parse "$ITEM" " " PORTCNT SRC PORT
  255.                 echo -e "$(printf "%5d %-45s e.g. %s" $PORTCNT "http://www.speedguide.net/port.php?port="$PORT )" "https://dnsquery.org/ipwhois/"$SRC >> $LOGFILE.tmp
  256.             done
  257.             DTYPE="SYSLOG"
  258.             REC_CNT=$(wc -l $SYSLOG | awk '{print $1}')
  259.             # Beware in some Syslog extracts, the displayed month e.g. 'May' is actually 4 chars long! "May'0xa0'" ('0xa0' = 240 octal)
  260.             # NOTE: The Unicode 0xa0 char is the '&nbsp' so maybe it's just present when the user debug/test data is transferred from the forum?
  261.             FIRSTTIMESTAMP=$(head -n 1 $SYSLOG | tr -d "\240" | awk '{print $1" "$2" "$3}')
  262.             LASTTIMESTAMP=$(tail  -n 1 $SYSLOG | tr -d "\240" | awk '{print $1" "$2" "$3}')
  263.             PERIODTXT=", $FIRSTTIMESTAMP - $LASTTIMESTAMP"
  264.     else
  265.         echo -e "\a\t\n***ERROR Syslog Tracking DISABLED? - check '$FN' to run 'IPSET_Block.sh init'\n"
  266.         logger -t "($(basename $0))" $$ "***ERROR Syslog Tracking DISABLED? - check '$FN' to run 'IPSET_Block.sh init'"
  267.         exit 98
  268.     fi
  269. fi
  270.  
  271. UTOTAL=0;TOTAL=0
  272. if [ -f ${LOGFILE}.tmp ];then
  273.     UTOTAL=$(wc -l ${LOGFILE}.tmp | cut -d" " -f1)                      # Unique Ports attacked
  274.     TOTAL=$(awk -F' ' '{sum+=$1} END{print sum;}' ${LOGFILE}.tmp)       # Physical number of attacks
  275. fi
  276.  
  277. TIMESTAMP=$(date +"%d %b %T")":"
  278. echo -e "\n\n"$TIMESTAMP "# Unique Ports attacked via "$IIFXT":" $UTOTAL "(out of" $TOTAL "attempts) tracked via" $DTYPE"$PERIODTXT"  >> $LOGFILE.new   # New period's report Header
  279. logger -t "($(basename $0))" $$ "Hacker report created '"$LOGFILE"' - Statistics: Total Unique Ports attacked:" $UTOTAL "(out of" $TOTAL "attempts) tracked using" $DTYPE "$PERIODTXT"
  280.  
  281. if [ $GRE_CNT -gt 0 ];then
  282.     echo -e "\n\t***ATTENTION" $GRE_CNT "GRE (Generic Route Encapsulation) aka Virtual Private Network (VPN) attacks." >> $LOGFILE.new
  283. fi
  284.  
  285. echo -e "\n\tTop" $TOPX "Ports attacked:" >> $LOGFILE.new
  286. if [ -f ${LOGFILE}.tmp ];then
  287.     sort -nr  $LOGFILE".tmp"  | head -n $TOPX >> $LOGFILE.new
  288. fi
  289.  
  290. echo -e "\n\tTop" $TOPX "attackers:"      >> $LOGFILE.new
  291. if [ -f ${LOGFILE}.tmp ];then
  292.     cat $LOGFILE".tmp" | uniq -f 3 -c | sort -nr | head -n $TOPX| awk '{printf "%5d %s\n", $1, $5}' >> $LOGFILE.new
  293. fi
  294.  
  295. echo -e "\n\tLast" $TOPX "most recent attackers:" >> $LOGFILE.new
  296. if [ -f ${LOGFILE}.tmp ];then
  297.     tail -n $TOPX $LOGFILE".tmp" | awk '{print "      "$4}'  >> $LOGFILE.new        # ...in chronological order last is 'most recent'
  298. fi
  299.  
  300. cat $LOGFILE".new" >> $LOGFILE                          # Update master report with this period's attack summary
  301.  
  302. echo -e "\n\tPorts attacked:" >> $LOGFILE
  303. if [ -f ${LOGFILE}.tmp ];then
  304.     cat $LOGFILE".tmp" >> $LOGFILE                      # Update master report with this period's attack details
  305. fi
  306.  
  307. echo -e "\n\033[0;92m"$REC_CNT "records scanned from Syslog ('"$SYSLOG"')\e[0m"
  308.  
  309. # Show report just created ...either in FULL or just the summary.
  310. if [ "$VERBOSE" == "1" ];then                           # Just the summary report or ALL report details?
  311.     awk -v pattern="${TIMESTAMP}" ' $0 ~ pattern { matched = 1 }; matched { print }' "$LOGFILE"     # Display ALL report lines
  312. else
  313.     echo -en "\e[1;31m"
  314.     LINES=3
  315.     if [ $GRE_CNT -gt 0 ];then
  316.         LINES=5
  317.     fi
  318.     head -n $LINES $LOGFILE.new                         # Highlight the Summary header and GRE count if >0 in RED
  319.     LINES=$(($LINES+1))
  320.     echo -e "\033[00m"
  321.     tail -q -n +$LINES $LOGFILE.new                     # Only display the new period's summary report
  322. fi
  323.  
  324. echo -e " "
  325.  
  326. Delete_TempFiles
  327.  
  328. # Always sanitise the Syslog now that the report file has been created ?
  329. if [ "$( echo $@ | grep -o "wipe" | wc -w )" -eq 1 ];then
  330.     echo "`sed '/Block IN=/d' $SYSLOG`" > $SYSLOG
  331.     echo -e "\a\e[41m***Warning 'Block IN=' tracking messages now erased! ('"$SYSLOG"')\033[00m"
  332.     logger -t "($(basename $0))" $$ "'Block IN=' tracking messages now erased! ('"$SYSLOG"')"
  333.     echo -e " "
  334. fi
  335.  
  336.  
  337. exit 0
RAW Paste Data