So I was thinking about what I could try next in my quest to learn bash and came across a web post on how to scan 'localhost' for open ports. It was actually just the command, so I embellished it a bit to include options, printing, etc. Then I happened upon 'netcat' and thought "could this be better?" Turns out it is, if only for the fact it provides more information and runs a lot faster and uses way less CPU resources. I've left the web solution included in the script should someone want to compare the two, but in my final script, it will be gone. Though the script works, I am absolutely certain there are mistakes or better ways of doing what I did. Also, if anyone has a way to improve it that would be great. For instance, it would be nice to know what is using those open ports. :| So here is the script:
and here is the output file:
As always, comments, suggestions, corrections and such are appreciated.
Code:
#!/bin/bash
#
# bash ver 4.2-68.1.5
# openSUSE 13.1
# A simple port scanner performed on 'localhost'
# Note: This script has to be run with root permissions to get full benefit
#
# Like to start with a clean slate.
clear
# Set some variables
myDate=$(date +"%A %B %d %Y %T %Z %n")
myFile="/root/open_ports.txt"
declare -i myRange1
declare -i myRange2
declare -i myScanned
#
echo -e "==============================\n"
if [ "$(whoami)" != 'root' ];
then
echo "I'm sorry "$USER", you must be root to run this script."
exit 1;
fi
echo -e "Hello, "$USER". this script will scan for open ports.\n"
echo -e "==============================\n"
#
# ++++++++++ CREATE FILE IF NECESSARY ++++++++++
# Make sure they only enter y or n
#
while true
do
read -s -n1 -p "Do you want to save data to a file [y/n]: " myAns
echo $myAns
#
case $myAns in
y|Y) # see if file /root/port_scanner.txt exists, If no, then create, if yes, move on
touch $myFile
echo "========== Report Generated "$myDate >> $myFile
echo -e "++++++ File /root/open_ports.txt ready.\n"
break
;;
n|N)
echo -e "++++++ No file will be created or modified\n"
break
;;
*) # Presses something other than 'y' or 'n'
echo "Smartass, just press y or n"
continue
;;
esac
done
#
# ++++++++++ GET PORT OR PORT RANGE ++++++++++
#
echo -e "==============================\n"
echo "Ports are generally divided into three groups:"
echo "**** Well Known Ports: 0-1023" # I am omitting '0' from this range and making 1 the minimum port
echo "**** Registered Ports: 1024-49151"
echo -e "**** Dynamic/Private Ports: 49152-65535\n"
echo -e "==============================\n"
#
while true
do
read -s -n1 -p "Moving on, do you want to check a (s)ingle port or a (r)ange of ports [s/r]: " myOpt
echo $myOpt
case $myOpt in
s|S)
read -p "Enter the port you want to check [1-65535]: " myRange1
if [[ "$myRange1" -lt "1" ]] || [[ "$myRange1" -gt "65535" ]]
then
echo "Must be in range of 1-65535"
continue
fi
myRange2=$myRange1
break
;;
r|R)
read -p "Enter the first port you want to check []: " myRange1
if [[ "$myRange1" -lt "1" ]] || [[ "$myRange1" -gt "65535" ]]
then
echo "Must be in range of 1-65535"
continue
fi
read -p "Enter the ending port you want to check []: " myRange2
if [[ "$myRange2" -lt "$myRange1"+1 ]] || [[ "$myRange2" -gt "65535" ]]
then
echo "Must be greater than Range 1 and less than or equal to 65535"
continue
fi
break
;;
*)
echo "Really? Out of range"
continue
;;
esac
done
#
# ++++++++++ TIME TO SCAN PORTS ++++++++++
#
echo
echo -e "==============================\n"
echo -e "Scanning for open ports using web solution\n"
#
# Print results to file- Yes
#
if [ "$myAns" == "y" ]
then
for (( p=$myRange1; p<=$myRange2; p++ )) do
(echo >/dev/tcp/localhost/$p) >/dev/null 2>&1 && echo "$p open" | tee >> $myFile;
done
fi
#
# Or No
#
for (( p=$myRange1; p<=$myRange2; p++ )) do
(echo >/dev/tcp/localhost/$p) >/dev/null 2>&1 && echo "$p open" ;
done
#
echo
echo -e "==============================\n"
echo -e "Scanning for open ports using netcat (nc)\n"
#
# Lets try it with netcat
# Note: on my default system I have the 'netcat-openbsd' package. Not sure if this will
# + work with netcat-traditional.
#
if [ "$myAns" == "y" ]
then
nc -vz localhost $myRange1-$myRange2 2>&1 | grep succeeded | tee >> $myFile;
fi
#
nc -vz localhost $myRange1-$myRange2 2>&1 |grep succeeded;
#
echo
echo -e "==============================\n"
echo "Total number of ports scanned"
#
if [[ "$myRange2" = "$myRange1" ]]
then
myScanned=1
else
let "myScanned = $myRange2 - $myRange1"
fi
echo "Ports Scanned = " $myScanned
#
# Lets us know script is done by sending us a beep.
#
echo -e "\a" > /dev/console;
echo -e "==============================\n"
echo "tata"
Code:
========== Report Generated Sunday June 08 2014 12:41:42 EDT
* With web solution
25 open *(mail)
7634 open *(hddtemp)
47452 open *(unk)
* With netcat
Connection to localhost 25 port [tcp/smtp] succeeded!
Connection to localhost 7634 port [tcp/*] succeeded!
Connection to localhost 55453 port [tcp/*] succeeded!
Connection to localhost 60924 port [tcp/*] succeeded!
Note: entrys with a '*' I added, not the program