Examining Multiple Ports When Running NetCat (nc)

I am using -w 1 below to limit timeouts to 1 second. I also use -v for the reasons mentioned in comments. I used -n to refuse delays for reverse DNS lookups...

[mpenning@tsunami ~]$ for i in $(echo "172.16.1.1,172.16.1.5"|tr "," "\n"); do echo -e "22\n80\n443\n8080" | xargs -i nc -w 1 -zvn $i {}; done
(UNKNOWN) [172.16.1.1] 22 (ssh) open
(UNKNOWN) [172.16.1.1] 80 (www) : Connection timed out
(UNKNOWN) [172.16.1.1] 443 (https) open
(UNKNOWN) [172.16.1.1] 8080 (http-alt) : Connection timed out
(UNKNOWN) [172.16.1.5] 22 (ssh) open
(UNKNOWN) [172.16.1.5] 80 (www) open
(UNKNOWN) [172.16.1.5] 443 (https) open
(UNKNOWN) [172.16.1.5] 8080 (http-alt) : Connection refused
[mpenning@tsunami ~]$

If you like GNU Parallel as much as I do, try this:

parallel nc -vz host ::: 22 80 443 8080

Sample Output:

Connection to foo.example.com 22 port [tcp/ssh] succeeded!
nc: connect to foo.example.com port 80 (tcp) failed: Connection refused
nc: connect to foo.example.com port 443 (tcp) failed: Connection refused
nc: connect to foo.example.com port 8080 (tcp) failed: Connection refused

This method is also faster in some cases since it's testing connecting to ports in parallel, not serial. Specifically this would be where the remote host (or intervening firewall) discards your packets to stay stealth (as opposed to a successful connection or forceful reject).

Tip: in most Linux distros, you can install parallel from your package manager.

Update: With parallel, this generalizes super well to cover an often needed case of multiple hosts x multiple ports. The following example uses parallel to iterate over the cross product, so you don't need to write any nested loops.

parallel nc -vz ::: host1 host2 host3 ::: 22 80 443 8080

Output:

Connection to host1 22 port [tcp/ssh] succeeded!
Connection to host1 80 port [tcp/http] succeeded!
Connection to host1 443 port [tcp/https] succeeded!
nc: connect to host1 port 8080 (tcp) failed: Connection refused
Connection to host2 22 port [tcp/ssh] succeeded!
nc: connect to host2 port 80 (tcp) failed: Connection refused
nc: connect to host2 port 443 (tcp) failed: Connection refused
nc: connect to host2 port 8080 (tcp) failed: Connection refused
Connection to host3 22 port [tcp/ssh] succeeded!
nc: connect to host3 port 80 (tcp) failed: Connection refused
nc: connect to host3 port 8080 (tcp) failed: Connection refused
nc: connect to host3 port 443 (tcp) failed: Connection refused

Just as the previous example, parallel executes the connection tests in parallel. Note, the default parallelism is how many threads your system have, but can override easily with the -j switch to any value. You could easily get away with parallel -j 50 ... or even higher since testing sockets is not a CPU intensive task.


Netcat is not really a scanner, as the comment suggests nmap would be a better option here. Not using the the port range option I guess you are left with wrapping it in a shell script;

    for host in $(cat hostlist); do
        for port in $ports; do nc -z $host $port; done
    done

etc..


On Gentoo Linux (with net-analyzer/netcat-110-r9 installed):

$ nc -vz www.example.com 80 443
www.example.com [93.184.216.34] 80 (http) open

$ nc -vvz www.example.com 80 443
www.example.com [93.184.216.34] 80 (http) open
www.example.com [93.184.216.34] 443 (https) : Connection refused

In Redhat 6 you could run something like this as a true one-liner:

nc -znv -w 2 <host> <port1>; nc -znv -w 2 <host> <port2>

-z tests port
-n doesn't resolve DNS
-v give verbose output
-w timeout after 2 seconds
; strings one command after another as long as you don't mind typing it out again.

I like the suggestions for using a loop if you are scanning multiple ports, however if it's 2 or 3 and you are already trying to loop through a list with something like SSH, stringing commands like this is useful.