networking - Quick way to scan for opened ports on local network according to a list

06
2014-04
  • Mikhael Djekson

    How can I quickly find out whether port 80 is open/listening on a server via a bash script?

    Normally on all workstations the daemon is running, but sometimes it fails. I use the following command to check if an IP address has an open port. I would like to be able to do this for every line in a file without having to manually type it each time.

     nc -zw3 10.101.0.13 80 && echo "opened" || echo "closed"
    

    The list file looks like this, where 3333 and 3334 are strings after $ip;

    10.101.0.13; 3333
    10.101.0.15; 3334
    10.101.0.17; 4143
    10.101.0.21; 1445
    10.101.0.27; 2443
    10.101.0.31; 2445
    10.101.0.47; 3443
    10.101.0.61; 3445
    

    I have to separate open ports from closed ones, so I'll have a list of failed servers that will have to be fixed.

    I tried something like this without success:

    while IFS=";" read ip port ; do nc -zw3 "$ip" "$port" && echo "$ip:$port => opened" || echo "$ip:$port =>  closed" ; done < list.txt
    
    while IFS=";" read ip port ; do nc -zw3 "${ip}" "${port}" && echo "${ip}:${port} => opened" || echo "${ip}:${port} =>  closed" ; done < list.txt
    
  • Answers
  • bonsaiviking

    Here's the most basic and efficient Nmap command to do what you want (and nothing more):

    #!/bin/sh
    # Gather the IPs to scan for each port
    perl -lanF\; -e'push @{$p{$F[1]}}, $F[0];END{$,=" ";while(($x,$y)=each%p){print $x,@$y}}' input.txt | while read port ips; do
      # Scan the appropriate port for each set of IPs
      nmap -Pn -n -oG - -p $port $ips |\
      # Put the open ones into open.txt and the closed/filtered into closed.txt
      awk 'OFS=":";$4~/^Ports:/{if(/open/){print $2,'$port' >> "open.txt"}else{print $2,'$port' >> "closed.txt"}}'
    done
    

    Unfortunately, Nmap does not have a built-in way to scan only some ports on some IPs and other ports on other IPs, otherwise this could be a lot simpler.

  • dma1324
    #!/bin/bash
    N=0
    cat $1 | while read line
    do
        N=$((N+1))
        nc -zw3 $( echo $line | tr -d ';' ) && echo -e "OPEN\t$( echo $line | sed 's/; /:/g' )" || echo -e "CLOSED\t$( echo $line | sed 's/; /:/g' )" 
    done
    

    Usage: ./script.sh Scans the file specified and tests if each "$ip; $port" is open or closed.

    If you want sorted output: ./script.sh | sort

    No installation necessary.

    As one line that you can paste into your terminal without having to make a shell script:

    N=0; cat FILENAME | while read line; do; N=$((N+1)); nc -zw3 $( echo $line | tr -d ';' ) && echo -e "OPEN\t$( echo $line | sed 's/; /:/g' )" || echo -e "CLOSED\t$( echo $line | sed 's/; /:/g' )"; done
    
  • MariusMatutiae

    Easiest thing is to install nmap from the repos, then do:

       awk -F ";" '{print $1}' data | xargs -L 1 nmap -p 80
    

    where data is the file with the IP addresses to scan.

    Edit:

    If it is true,as @pabouk suggests below, that the number following the IP address is port to be scanned, then you can achieve the desired scan as follows:

       awk -F ";" '{print "nmap " $1 " -p" $2}' data | xargs -I % sh -c '%'
    

    If you wish scan for both port 80, and the port read from the file, you can do it with this command:

       awk -F ";" '{print "nmap " $1 " -p80," $2}' data | xargs -I % sh -c '%'
    

    If nmap is thought to produce too much output, the follwoing command will do:

       awk -F ";" '{print "nmap -oG - " $1 " -p80," $2}' data | xargs -I % sh -c '%' | grep Ports
    

  • Related Question

    linux - Netcat file transfer problem
  • squircle

    I have two custom scripts I just wrote to facilitate transferring files between my VPS and my home server. They are both written in bash (short & sweet):

    To send:

    #!/bin/bash
    
    SENDFILE=$1
    PORT=$2
    HOST='<my house>'
    HOSTIP=`host $HOST | grep "has address" | cut --delimiter=" " -f 4`
    
    echo Transferring file \"$SENDFILE\" to $HOST \($HOSTIP\).
    
    tar -c "$SENDFILE" | pv -c -N tar -i 0.5 | lzma -z -c -6 | pv -c -N lzma -i 0.5 | nc -q 1 $HOSTIP $PORT
    
    echo Done.
    


    To receive:

    #!/bin/bash
    
    SERVER='<myserver>'
    SERVERIP=`host $SERVER | grep "has address" | cut --delimiter=" " -f 4`
    PORT=$1
    
    echo Receiving file from $SERVER \($SERVERIP\) on port $PORT.
    
    nc -l $PORT | pv -c -N netcat -i 0.5 | lzma -d -c | pv -c -N lzma -i 0.5 | tar -xf -
    
    echo Done.
    

    The problem is that, for a very quick second, I see something flash along the lines of "Connection Refused" (before pv overwrites it), and no file is ever transferred. The port is forwarded through my router, and nmap confirms it:

    ~$ sudo nmap -sU -PN -p55515 -v <my house>
    
    Starting Nmap 5.00 ( http://nmap.org ) at 2010-04-21 18:10 EDT
    NSE: Loaded 0 scripts for scanning.
    Initiating Parallel DNS resolution of 1 host. at 18:10
    Completed Parallel DNS resolution of 1 host. at 18:10, 0.00s elapsed
    Initiating UDP Scan at 18:10
    Scanning 74.13.25.94 [1 port]
    Completed UDP Scan at 18:10, 2.02s elapsed (1 total ports)
    Host 74.13.25.94 is up.
    Interesting ports on 74.13.25.94:
    PORT      STATE         SERVICE
    55515/udp open|filtered unknown
    
    Read data files from: /usr/share/nmap
    Nmap done: 1 IP address (1 host up) scanned in 2.08 seconds
               Raw packets sent: 2 (56B) | Rcvd: 5 (260B)
    

    Also, running netcat normally doesn't work either:

    squircle@summit:~$ netcat <my house> 55515
    <my house> [<my IP>] 55515 (?) : Connection refused
    

    Both boxes are Ubuntu Karmic (9.10). The receiver has no firewall, and outbound traffic on that port is allowed on the sender. I have no idea what to troubleshoot next. Any ideas?

    P.S.: Feel free to move this to SO/SF if you feel it would fit better there.


  • Related Answers
  • user23307
    HOSTIP=`host $HOST | grep "has address" | cut --delimiter=" " -f 4`
    SERVERIP=`host $SERVER | grep "has address" | cut --delimiter=" " -f 4`
    

    I have no idea what you think this accomplishes, but you should remove these lines and just use $HOST and $SERVER directly.

    The problem is that, for a very quick second, I see something flash along the lines of "Connection Refused" (before pv overwrites it), and no file is ever transferred. The port is forwarded through my router, and nmap confirms it: ~$ sudo nmap -sU -PN -p55515 -v [...] PORT STATE SERVICE 55515/udp open|filtered unknown

    You told it to do a udp scan. Why did you do that? You are not using netcat in udp mode, nor would that even make sense for file transfer.

    Also, running netcat normally doesn't work either: squircle@summit:~$ netcat 55515 [] 55515 (?) : Connection refused

    You are not forwarding the port correctly.

    Anyway, this whole scenario is flawed from the beginning. Just use scp or rsync. If you insist on using lzma, pipe tar+lzma over ssh. Using netcat in this situation buys you absolutely nothing.