netcat - How do I synchronize my portscan and port listen scripts and how do i export all output to a .txt file? - bash

My goal is to have a port listen script on Host A which listens on predefined ports using netcat.
While this script listens, the port scan script is running on Host B and checks if the ports on Host A or open or not.
The output of the scan script needs to be directed to a separate .txt file and must include all information from the nc -zvv output.
The listen script looks like this:
#!/bin/bash
# Define the four arrays of ports to listen on
ports_1st=(20 21 22 80 443)
ports_2nd=(2000 2001 2002 2003)
ports_3rd=(3000 3001 3002 3003)
ports_4th=(4000 4001 4002 4003)
# Sleep to allow the scan script to start and bind to all ports
echo "Start PortScan.sh as soon as port listen starts!"
sleep 5
echo -e "\n"
echo -e "\n"
# Countdown timer
echo "Start the port scan in:"
for i in 5 4 3 2 1; do
echo "$i..."
sleep 1
done
# Loop through each array of ports and use nc to listen on each port
echo "Listening on 1st ports..."
for ports in ports_1st; do
for port in "${!ports[#]}"; do
nc -l -k -p $port &
done
done
echo -e "\n"
echo "Listening on 1st ports completed"
echo -e "\n"
echo -e "\n"
echo "Listening on 2nd ports..."
for ports in ports_2nd; do
for port in "${!ports[#]}"; do
nc -l -k -p $port &
done
done
echo -e "\n"
echo "Listening on 2nd ports completed"
echo -e "\n"
echo -e "\n"
echo "Listening on 3rd ports..."
for ports in ports_3rd; do
for port in "${!ports[#]}"; do
nc -l -k -p $port &
done
done
echo -e "\n"
echo "Listening on 3rd ports completed"
echo -e "\n"
echo -e "\n"
echo "Listening on 4th ports..."
for ports in ports_4th; do
for port in "${!ports[#]}"; do
nc -l -k -p $port &
done
done
echo -e "\n"
echo "Listening on 4th ports completed"
echo -e "\n"
echo -e "\n"
# Wait for all background nc processes to complete
wait
echo "Portscan has been completed"
echo -e "\n"
echo -e "\n"
And the scanscript looks like this:
#!/bin/bash
# Define the range of ports to scan
ports_1st=(20 21 22 80 443)
ports_2nd=(2000 2001 2002 2003)
ports_3rd=(3000 3001 3002 3003)
ports_4th=(4000 4001 4002 4003)
# Define the IP of the target host
echo "Please enter the server IP of the target host!"
read target_host
echo -e "\n"
echo -e "\n"
# Define current date variable
current_date=$(date +"%Y-%m-%d")
# Loop through the range of ports and use nc to test for a response
echo "Scanning 1st ports..."
for ports in ports_1st; do
for port in "${ports[#]}"; do
nc -zvv -w 1 $target_host $port 2>&1 | tee -a Portscan_$current_date.txt
if [ $? -eq 0 ]; then
echo "Port $port is open" | tee -a Portscan_$current_date.txt
else
echo "Port $port is closed or connection timed out" | tee -a Portscan_$current_date.txt
fi
done
echo "1st port scan completed" | tee -a Portscan_$current_date.txt
echo -e "\n"
echo -e "\n"
echo "Scanning 2nd ports..."
for ports in ports_2nd; do
for port in "${ports[#]}"; do
nc -zvv -w 1 $target_host $port 2>&1 | tee -a Portscan_$current_date.txt
if [ $? -eq 0 ]; then
echo "Port $port is open" | tee -a Portscan_$current_date.txt
else
echo "Port $port is closed or connection timed out" | tee -a Portscan_$current_date.txt
fi
done
echo "2nd scan completed" | tee -a Portscan_$current_date.txt
echo -e "\n"
echo -e "\n"
echo "Scanning 3rd ports..."
for ports in ports_3rd; do
for port in "${ports[#]}"; do
nc -zvv -w 1 $target_host $port 2>&1 | tee -a Portscan_$current_date.txt
if [ $? -eq 0 ]; then
echo "Port $port is open" | tee -a Portscan_$current_date.txt
else
echo "Port $port is closed or connection timed out" | tee -a Portscan_$current_date.txt
fi
done
echo "3rd port scan completed" | tee -a Portscan_$current_date.txt
echo -e "\n"
echo -e "\n"
echo "Scanning 4th ports..."
for ports in ports_4th; do
for port in "${ports[#]}"; do
nc -zvv -w 1 $target_host $port 2>&1 | tee -a Portscan_$current_date.txt
if [ $? -eq 0 ]; then
echo "Port $port is open" | tee -a Portscan_$current_date.txt
else
echo "Port $port is closed or connection timed out" | tee -a Portscan_$current_date.txt
fi
done
echo "4th port scan completed" | tee -a Portscan_$current_date.txt
echo -e "\n"
echo -e "\n"
done
done
done
done
The problem is that the listen script seems to end instantly instead of waiting for all ports to be scanned and the portscan script does not put the proper output to the .txt file.
Do you have any ideas on how to fix this?
Side notes:
Netcat is mandatory to be used.
I am expecting to loop through each port mentioned in the listen script as well as in the scan script.
The scan script is supposed to prompt if the port is open or closed/timeout in a .txt file.

Related

Notify only when IP changes

I use this script to log ext IP changes
host myip.opendns.com resolver1.opendns.com | sed -n -e 's/^\(.*\)\(myip.opendns.com has address \)/\1/p' | sed "s/^/`date` /" ยป /DataVolume/shares/Public/MyIP.txt
How can I create an alert (maybe creating a separate log file or sending a mail) only when IP changes?
Something along these lines:
#!/bin/bash
previp=
while :; do
ip=$(host myip.opendns.com resolver1.opendns.com |
sed -n '/.* has address \(.*\)/ { s//\1/; p; q; }' )
if [[ $previp != "$ip" ]]; then
msg="$(date): IP change from '$previp' to '$ip'"
echo "$msg" >> logfile
mail -s "IP change" somebody#somewhere <<< "$msg"
previp=$ip
fi
sleep 60
done
If you want it to run one time only (from crontab, for example):
#!/bin/bash
ipfile='/tmp/previous_ip'
ip=$(host myip.opendns.com resolver1.opendns.com |
sed -n '/.* has address \(.*\)/ { s//\1/; p; q; }' )
if ! [[ -f $ipfile ]]; then
echo "$ip" > "$ipfile"
fi
read -r previp < "$ipfile"
if [[ $previp != "$ip" ]]; then
msg="$(date): IP change from '$previp' to '$ip'"
echo "$msg" >> logfile
mail -s "IP change" somebody#somewhere <<< "$msg"
echo "$ip" > "$ipfile"
fi

Unable to execute multiple commands + nested if in a for loop over ssh non-interactive session

I am trying to run certain commands, also checking some using nested if conditions over non-interactive SSH connections to my servers in the list. But unfortunately, it hits with syntax errors.
$ for i in $(cat servers);do ssh -t -l root ${i} 'hostname && grep BACKUPENABLE /var/cpanel/backups/config && if [[ $(ss -tulnp | grep rpc) ]] ; then echo -ne "RPCbind service is running \n$(cat /etc/exports)\n"; IP=$(awk -F'(' '{print $1}' /etc/exports | awk '{print $2}'); if [[ $( ping ${IP} -c1 > /dev/null) ]] ; then echo "NFS server responds"; else echo "NFS server not responding"; fi ; else -ne "No RPC and NFS backup not found\n"; fi && ss -tulnp | grep -vE "ssh|cpsrvd|pure-ftp|exim|httpd|named|dovecot|mysqld|snmp|ntp|java|spamd|cpdavd|State|rpc" && if [ -x /usr/sbin/csf ]; then echo csf present;else echo csf not present;fi && yum -q check-update kernel' 2> /dev/null;echo;done
-bash: syntax error near unexpected token `('
when checking in debug mode
$ bash -x for i in $(cat servers);do ssh -t -l root ${i} 'hostname && grep BACKUPENABLE /var/cpanel/backups/config && if [[ $(ss -tulnp | grep rpc) ]] ; then echo -ne "RPCbind service is running \n$(cat /etc/exports)\n"; IP=$(awk -F'(' '{print $1}' /etc/exports | awk '{print $2}'); if [[ $( ping ${IP} -c1 > /dev/null) ]] ; then echo "NFS server responds"; else echo "NFS server not responding"; fi ; else -ne "No RPC and NFS backup not found\n"; fi && ss -tulnp | grep -vE "ssh|cpsrvd|pure-ftp|exim|httpd|named|dovecot|mysqld|snmp|ntp|java|spamd|cpdavd|State|rpc" && if [ -x /usr/sbin/csf ]; then echo csf present;else echo csf not present;fi && yum -q check-update kernel' 2> /dev/null;echo;done
-bash: syntax error near unexpected token `do'
But the interesting thing is when I run the set of commands on an individual server, it produces the expected result fine.
root#server [~]# hostname && grep BACKUPENABLE /var/cpanel/backups/config && if [[ $(ss -tulnp | grep rpc) ]] ; then echo -ne "RPCbind service is running \n$(cat /etc/exports)\n"; IP=$(awk -F'(' '{print $1}' /etc/exports | awk '{print $2}'); if [[ $( ping ${IP} -c1 > /dev/null) ]] ; then echo "NFS server responds"; else echo "NFS server not responding"; fi ; else -ne "No RPC and NFS backup not found\n"; fi && ss -tulnp | grep -vE "ssh|cpsrvd|pure-ftp|exim|httpd|named|dovecot|mysqld|snmp|ntp|java|spamd|cpdavd|State|rpc" && if [ -x /usr/sbin/csf ]; then echo csf present;else echo csf not present;fi && yum -q check-update kernel
server.host.com
BACKUPENABLE: 'no'
RPCbind service is running
/backups/serverpath IP.x.x.x(rw,sync,no_root_squash,no_subtree_check)
NFS server not responding
udp UNCONN 0 0 *:44892 *:*
udp UNCONN 0 0 *:2049 *:*
udp UNCONN 0 0 :::36718 :::*
udp UNCONN 0 0 :::2049 :::*
tcp LISTEN 0 64 :::2049 :::*
tcp LISTEN 0 64 *:2049 *:*
tcp LISTEN 0 64 :::45701 :::*
tcp LISTEN 0 64 *:38633 *:*
csf present
kernel.x86_64 2.6.32-754.29.1.el6 updates
Basically, I can't figure out where the problem lies. Is it SSH can't group them or break at any point of if conditions instead of running sequentially over a non-interactive session?.

Linux telnet shell script

I'm trying to read multiple hosts and ports from a text file (ip.txt) and check if they are connected/failed to connect/timed out, and echo the responses to Telnet_Success.txt/Telnet_Failure.txt/Telnet_Refused.txt files
I have tried the following script, it simply shows all the connection results as failed, but when checking manually one by one, I find some of them connected. any help is appreciated.
Here is the script:
>Telnet_Success.txt
>Telnet_Refused.txt
>Telnet_Failure.txt
file=ip.txt
while read line ; do
ip=$( echo "$line" |cut -d ' ' -f1 )
port=$( echo "$line" |cut -d ' ' -f2 )
if telnet -c $ip $port </dev/null 2>&1 | grep -q Escape; then
echo "$ip $port Connected" >> Telnet_Success.txt
elif telnet -c $ip $port </dev/null 2>&1 | grep -q refused; then
echo "$ip $port Refused" >> Telnet_Refused.txt
else
echo "$ip $port Failed" >> Telnet_Failure.txt
fi
done < ${file}
I can't tell you exactly what's failing from the diagnostics you have provided, but it's definitely a problem that you attempt to call telnet multiple times - you could get different outcomes each time, producing bugs which are hard to troubleshoot. You also have some stylistic issues in your code.
Try this refactoring; see the inline comments.
>Telnet_Success.txt
>Telnet_Refused.txt
>Telnet_Failure.txt
# Why use a variable for something you only reference once anyway?
file=ip.txt
# Use the shell's field splitting facility
# Cope with missing final newline; see
# https://mywiki.wooledge.org/BashFAQ/001#My_text_files_are_broken.21__They_lack_their_final_newlines.21
while read -r ip port _ || [[ -n $port ]]; do
# Run telnet once, capture result for analysis
output=$(telnet -c "$ip" "$port" </dev/null 2>&1)
case $output in
*Escape*)
echo "$ip $port Connected" >> Telnet_Success.txt;;
*refused*)
echo "$ip $port Refused" >> Telnet_Refused.txt;;
*)
echo "$ip $port Failed" >> Telnet_Failure.txt;;
esac
# Always double quote file name variables, just in case
done < "${file}"
Hi looks like the telnet command is the culprit
should be "telnet ip port" not "telnet -c ip port"
file=ip.txt
while read line
do
ip=$( echo "$line" |cut -d ' ' -f1 )
port=$( echo "$line" |cut -d ' ' -f2 )
if telnet $ip $port </dev/null 2>&1 | grep -q Escape
then
echo "$ip $port Connected" >> Telnet_Success.txt
elif telnet $ip $port </dev/null 2>&1 | grep -q refused
then
echo "$ip $port Refused" >> Telnet_Refused.txt
else
echo "$ip $port Failed" >> Telnet_Failure.txt
fi
done < ${file}

Telnet to one computer from multiple computer

I have scenario where I have list of 100s of server . Want to check whether those all server can reach to specified destination server or not by telneting from all server to that destination server.
I have written a code as below,
#!/bin/bash
#bash to check telnet status.
#set -x;
#
#clear
SetParam() {
export URLFILE="Host_PortFile.txt"
export TIME=`date +%d-%m-%Y_%H.%M.%S`
export port=80
export STATUS_UP=`echo -e "\E[32m[ RUNNING ]\E[0m"`
export STATUS_DOWN=`echo -e "\E[31m[ DOWN ]\E[0m"`
export MAIL_TO="admin(at)techpaste(dot)com"
export SHELL_LOG="`basename $0`.log"
}
Telnet_Status() {
SetParam
cat $URLFILE | while read next
do
server=`echo $next | cut -d : -f1`
port=`echo $next | awk -F":" '{print $2}'`
TELNETCOUNT=`sleep 5 | telnet $server $port | grep -v "Connection refused" | grep "Connected to" | grep -v grep | wc -l`
if [ $TELNETCOUNT -eq 1 ] ; then
echo -e "$TIME : Port $port of URL http://$server:$port/ is \E[32m[ OPEN ]\E[0m";
else
echo -e "$TIME : Port $port of URL http://$server:$port/ is \E[31m[ NOT OPEN ]\E[0m";
echo -e "$TIME : Port $port of URL http://$server:$port/ is NOT OPEN" | mailx -s "Port $port of URL $server:$port/ is DOWN!!!" $MAIL_TO;
fi
done;
}
Main() {
Telnet_Status
}
SetParam
Main | tee -a $SHELL_LOG
My Host_PortFile.txt file looks like,
gmail.com:443
But here, i need to go to individual server and has to run this which consumes more time. Is there any modification I can do so that I can run the script from one machine to read all source server name from text file or any and can check that server can reach the destination server or not? Can anyone suggest on this please?

Open/close port shell script

I found a script that allows you to open or close any port and save it to the iptables. The problem I am having is it throws a syntax error after I tell it to close, but before I can give it a port number. The issue is right before the first else.
#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
clear
echo -e "############################nnnPresent ports opened on this machine are
$(iptables -nL INPUT | grep ACCEPT | grep dpt)
nCompleted listing...nnn#########################"
read -p "To open port enter open, to close etner close) " OPT1
if [[ "$OPT1" == open ]]
then
read -p "Please enter your desired port number to open: " PORT1
if [[ "$PORT1" =~ [0-9]{1,6} ]]
then
iptables -D INPUT $(iptables -nL INPUT --line-numbers | grep "$PORT1" | grep REJECT | awk '{print $1}')
iptables -A INPUT -m tcp -p tcp --dport "$PORT1" -j ACCEPT && { service iptables save;service iptables restart; echo -e "Ports opend through iptables are n$(iptables -nL INPUT | grep ACCEPT | grep dpt)"; }
else
echo "Please enter a valid port(0-65000)"
fi
elif [[ "$OPT1" == close ]]
then
read -p "Please enter your desired port number to close: " PORT1
if [[ "$PORT1" =~ [0-9]{1,6} ]]
then
iptables -D INPUT $(iptables -nL INPUT --line-numbers | grep "$PORT1" | grep ACCEPT | awk '{print $1}')
iptables -A INPUT -m tcp -p tcp --dport "$PORT1" -j REJECT && { service iptables save;service iptables restart; echo -e "Ports closed through iptables are n$(iptables -nL INPUT | grep REJECT | grep dpt)"; }
else
echo "Please enter a valid port(0-65000)"
fi
else
echo "Please enter only open or close..! Exiting script now";exit 1
fi
I don't see any error in the script. Can you paste the error that you are getting? See below
[root#kali ~]# ./ip.sh
######################nnnPresent ports opened on this machine are
nCompleted listing...nnn#########################
To open port enter open, to close etner close) close
Please enter your desired port number to close: 23
iptables: Bad rule (does a matching rule exist in that chain?).
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
Redirecting to /bin/systemctl restart iptables.service
Ports closed through iptables are nREJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:23 reject-with icmp-port-unreachable

Resources