Question

I am required to test at least 130 ip addresses and ports. I am hoping to write a bash script such that it reads the ip address and ports from an input file.

I have the following

while read line
do
telnet $line >> $2
done < $1

This is a crappy code as it cannot determine whether its connected or failed, and I have to rely on its auto escape character to disconnect from a connection.

How can I improvise this such that it updates $2 with the status quickly? I am working on Redhat and do not have netcat or expect installed..

Was it helpful?

Solution

As other stackoverflower's said, I would recommend using nmap or netcat if avilable. However, if you cannot use those software, you can use bash's builtin /dev/tcp/<host>/<port> instead.

http://www.gnu.org/software/bash/manual/bashref.html#Redirections

I could'nt figure out which version of bash you are using, but /dev/tcp/... seems to implemented since some old bash.

#!/bin/bash
echo "scanme.nmap.org 21
scanme.nmap.org 22
scanme.nmap.org 23
scanme.nmap.org 79
scanme.nmap.org 80
scanme.nmap.org 81" | \
while read host port; do
  r=$(bash -c 'exec 3<> /dev/tcp/'$host'/'$port';echo $?' 2>/dev/null)
  if [ "$r" = "0" ]; then
    echo $host $port is open
  else
    echo $host $port is closed
  fi
done

This produces

scanme.nmap.org 21 is closed
scanme.nmap.org 22 is open
scanme.nmap.org 23 is closed
scanme.nmap.org 79 is closed
scanme.nmap.org 80 is open
scanme.nmap.org 81 is closed

UPDATED: The following can do timeout. Although it may seem little tricky, idea is just to kill the child process after some timeout.

Bash script that kills a child process after a given timeout

#!/bin/bash
echo "scanme.nmap.org 80
scanme.nmap.org 81
192.168.0.100 1" | (
  TCP_TIMEOUT=3
  while read host port; do
    (CURPID=$BASHPID;
    (sleep $TCP_TIMEOUT;kill $CURPID) &
    exec 3<> /dev/tcp/$host/$port
    ) 2>/dev/null
    case $? in
    0)
      echo $host $port is open;;
    1)
      echo $host $port is closed;;
    143) # killed by SIGTERM
       echo $host $port timeouted;;
     esac
  done
  ) 2>/dev/null # avoid bash message "Terminated ..."

this produces

scanme.nmap.org 80 is open
scanme.nmap.org 81 is closed
192.168.0.100 1 timeouted

since 192.168.100 does not exist in my local network.

OTHER TIPS

A slight update to the accepted answer:

#!/bin/bash
# supertelnet 127.0.0.1:3306 10.10.10.45:22
(
  TCP_TIMEOUT=3
  for hostport in ${@}; do
    a=(${hostport//:/ })
    host=${a[0]}
    port=${a[1]}
    (CURPID=$BASHPID;
    (sleep $TCP_TIMEOUT;kill $CURPID) &
    exec 3<> /dev/tcp/$host/$port
    ) 2>/dev/null
    case $? in
    0)
      echo $host $port is open;;
    1)
      echo $host $port is closed;;
    143) # killed by SIGTERM
       echo $host $port timeouted;;
     esac
  done
  ) 2>/dev/null # avoid bash message "Terminated ..."

I find this to be a lot more friendly as a script.

Pure nmap replacment:

Sorry for comming so late on this question.

Speed parallelized process

This could be a lot quicker if all probe are done together:

TargetList=(
    scanme.nmap.org:21   scanme.nmap.org:22   scanme.nmap.org:23
    scanme.nmap.org:79   scanme.nmap.org:80   scanme.nmap.org:81
)

checkTcpConn() {
    local line testfd bpid=$BASHPID
    ( sleep 3 && kill -INT $bpid && echo $1 timeout) &
    if exec {testfd}<>/dev/tcp/${1/:/\/};then
        echo >&$testfd $'\r\n\r\n'
        read -ru $testfd -t 1 line
        [[ $line ]] &&
            echo $1 open $line ||
            echo $1 open
        exec {testfd}<&-
    else
        echo $1 closed
    fi
}

for target in ${TargetList[@]};do
    checkTcpConn $target &
done 2>/dev/null | sort

will output quickly:

scanme.nmap.org:21 closed
scanme.nmap.org:22 open SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.13
scanme.nmap.org:23 closed
scanme.nmap.org:79 closed
scanme.nmap.org:80 open HTTP/1.1 400 Bad Request
scanme.nmap.org:81 closed

or worst:

for target in scanme.nmap.org:{{1..1024},3128,3306,5432,5900,8080};do
    checkTcpConn $target &
    sleep .002
done 2>/dev/null | grep open
scanme.nmap.org:22 open SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.13
scanme.nmap.org:80 open HTTP/1.1 400 Bad Request

And with a timeout:

for target in scanme.nmap.org:2{2,1} 192.168.210.123:1 ;do
    checkTcpConn $target &
done 2>/dev/null |
    sort
192.168.210.123:1 timeout
scanme.nmap.org:21 closed
scanme.nmap.org:22 open SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.13

Nota The last pipe done 2>/dev/null | sort is required in order to avoid job control messages. For showing raw output, use

    ...
done 2>/dev/null | cat
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top