Linux telnet shell script - bash

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}

Related

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

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.

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

Why SNMP or SSH prevents the while to loop from iterating?

I'm writing a code in order to capture information about routers thanks to SSH and SNMP. I work on network with 4 different router configurations. In my script bash, a while loop read line by line the IP address of routers then try to know the configuration and finally capture information about my router.
To do so, I use a while loop but it only run for one IP address...
I assume that the problem comes from SNMP or SSH.
I tried the while loop just with
echo $line
The while loop :
while IFS= read -r line
do
echo
echo "line : $line"
echo
typeRouter=""
version=""
# type multitech V4.1
type=$(snmpget -v3 -u Ai -l authpriv -a SHA -A "pass" -x AES -X "pass" "$line" 1.3.6.1.4.1.995.14.1.1.8.3.0 | cut -d\" -f2 | cut -d. -f1 )
if [[ "$type" == "4" ]]; then
typeRouter=2
version=4
fi
# type sierra
type=$(snmpget -v3 -u Ai -l authpriv -a SHA -A "pass" -x AES -X "pass" "$line" iso.3.6.1.4.1.20542.9.1.1.9.7.0 | cut -d\" -f2 )
if [[ "$type" == "LX40" ]]; then
typeRouter=3
fi
case $typeRouter in
2)
echo "Mutlitech"
# version 4.1 et ultérieur
MultiV4 "$line" "$txtfile" "pass" "pass"
;;
3) # TODO PASSWORD
echo "Sierra"
Sierra "$line" "$txtfile" "pass" "pass"
;;
*)
echo
echo "Unknown router model, IP : $line"
echo
;;
esac
done < "file"
The function called
MultiV4 () {
# "$1" : #IP
# $2 : txtfile
# "$3" : mdp snmp
# $4 : mdp ssh
# Files
txtfile=$2
model="Multitech"
MACtxt="ephemere/mac.txt"
MacAddressRouter=$(snmpget -v3 -u Ai -l authpriv -a SHA -A "$3" -x AES -X "$3" "$1" iso.3.6.1.4.1.995.14.1.1.5.1.0 | cut -d\" -f2)
echo "Router MAC address : $MacAddressRouter"
sshpass -p "$4" ssh -o StrictHostKeyChecking=no admin#"$1" "cat /proc/net/arp" > "$MACtxt"
rssiPacket=$(snmpget -v3 -u Ai -l authpriv -a SHA -A "$3" -x AES -X "$3" "$1" iso.3.6.1.4.1.995.14.1.1.3.5.0 | cut -d: -f2 | cut -d\" -f2 | tr -d dBm)
echo "RSSI packet : $rssiPacket"
firmware=$(snmpget -v3 -u Ai -l authpriv -a SHA -A "$3" -x AES -X "$3" "$1" iso.3.6.1.4.1.995.14.1.1.3.4.0 | cut -d: -f2 | cut -d\" -f2)
echo "Firmware version : $firmware"
echo "$MacAddressRouter", "$MacAddressPlayer", "$rssiPacket", "$model", "$firmware", "$imei", "$SIMStatus", "$operator", "$connectionType", "$IPaddress", "$SINR", "$RSRP", "$RSRQ" >> "$txtfile"
}
My file
10.252.144.138
10.252.144.140
10.252.144.23
10.252.144.15
10.252.144.134
Can you help me why the loop running only one time ?
I solved the problem using
ssh -n
Go see this answer for more explanation : Shell script while read line loop stops after the first line

Email Alerts when service or server automatically comes up

I am working on a bash script that helps to ping and get the network interface level status of the host machines and services.
This script will send a email alerts in case of failure.
#!/bin/bash
HOSTS="192.168.8.200"
COUNT=4
for myHost in $HOSTS
do
count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
# 100% failed
echo -e "HOST:$myHost is down (ping failed) at $(date)" | mailx -A gmail -s “Mail subject” anymail#anydomain.com
fi
done
This works fine.
But need help to get a one single email alert when host automatically comes up (ping success).
You need to save the state of the host (up/down) during the calls of your script.
if the host is "up" and the former state was "down" then you need to send an email.
You can just write the result of the "check command" to a file in /tmp/
if the check returns that the server is up you read the content of the file. if the state is "down" in the file, then send an email an write "up" to the file.
on the next check if the server is up, there will be no additional email sent, because the server was also "up" before.
#!/bin/bash
HOSTS="192.168.8.200 192.168.8.201 192.168.122.1"
COUNT=4
STATE="/tmp/ping_state.txt"
for myHost in $HOSTS
do
count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
# 100% failed
#echo -e "HOST:$myHost is down (ping failed) at $(date)" | mailx -A gmail -s “Mail subject” anymail#anydomain.com
echo "host $myHost down"
#delete all previous entries of that ip
sed -i "/$myHost/d" $STATE
#mark host as down
echo "$myHost - down" >> $STATE
else
CHECK=`grep "$myHost" $STATE | grep -o "down"`
if [ "$CHECK" = "down" ]; then
echo "host $myHost up again"
#insert email for host up here
fi
#delete all previous entries of that ip
sed -i "/$myHost/d" $STATE
echo "$myHost - up" >> $STATE
fi
done
for simple testing I just used an echo statement instead of sending an email.

ftp while do error

Anyone can help what will be the problem?
Host='192.153.222.1'
User='ftpuser'
passwd='apple'
logfile='a.log'
while :; do
ftp -n -p -v $HOST < example.script >> $logfile
grep -qF "Connected" $logfile &&
grep -qF "File successfully transferred" $logfile && break
done
quote USER $USER
quote PASS $PASSWD
example.script contains
put example.txt
The error is
./example.sh: line 20: syntax error: unexpected end of file
Some fixes:
You missed the closing quote in:
Host='192.153.222.1'
Use a single <, otherwise it's an "here document" in:
ftp -n -p -v "$HOST" < example.script >> "$logfile"
Why you use << in this line?
ftp -n -p -v $HOST << example.script >> $logfile
Change it to
ftp -n -p -v $HOST < example.script >> $logfile
It will work :-)

Resources