Preparation

You can run rustscan first to find open ports, and then use nmap to analyze the services exposed.

rustscan -u 10000 --scripts none -a <comma-delimited list of CIDRs, IPs, or hosts>

RustScan’s scripting engine is extensible but difficult to set up, so you could disable it with --scripts none and run nmap yourself.

You should disable any

You may need to increase the local router’s nf_conntrack_max sysctl variable. 262144 connections tracked should take less than 100 MiB of RAM, but usually 131072 is enough.

sysctl net.netfilter.nf_conntrack_max=262144

You may also consider reducing net.netfilter.nf_conntrack_tcp_timeout_syn_sent to let connection tracking end sooner if the remote port is unresponsive, that is, filtered in nmap terms. The default 120 seconds is too long.

Scanning

First, gather a list of IP addresses to scan. For servers without NAT, you can use the following command to gather a list:

ip addr | awk '$1=="inet"{split($2,a,"/"); if(a[1] !~ /^(10|127|169\.254|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168)\./) print a[1]} $1=="inet6"{split($2,a,"/"); if(a[1] ~ /^[23]/) print a[1]}'

and convert them to a comma separated list:

... | grep -E '\.|:' | grep -v '^100\.' | sort | uniq | tr '\n' ',' ; echo

Finally, run rustscan and save its output.

You can also scan them with nmap using the script nmap_runner.sh below. For example, cat ports.txt | ./nmap_runner.sh | tee port-scan.txt.

#!/bin/bash
 
pattern='^([^[:space:]]+)[[:space:]]*->[[:space:]]*\[([0-9,]+)\]$'
 
while read -r line; do
    # Skip empty lines and comments (lines starting with #)
    [[ -z "$line" || "$line" == \#* ]] && continue
 
    if [[ "$line" =~ $pattern ]]; then
        ip="${BASH_REMATCH[1]}"
        ports="${BASH_REMATCH[2]}"
        if [[ "$ip" == *:* ]]; then
            nmap -6 -Pn -A -p "${ports}" "${ip}"
        else
            nmap -Pn -A -p "${ports}" "${ip}"
        fi
    else
        echo "Error: Invalid input format - $line" >&2
    fi
done

Nmap flags

  • -oX <file>: Output scan in XML format to <file>. Use - for stdout. You could also use -oN or -oG for normal and Grep-able format, respectively.
  • -v: Increase verbosity level. Most changes only affect interactive and normal output. Use if you want to watch scan progress.
Connect Scan Timing: About 1.03% done; ETC: 20:25 (1:00:00 remaining)
  • -sV: Probe open ports to determine service/version info.
  • -A: Presently this enables OS detection (-O), version scanning (-sV), script scanning (-sC) and traceroute (--traceroute). Note that both OS detection and traceroute require root privileges, so normal users just get -sV -sC.
  • -Pn: Treat all hosts as online — skip host discovery.
  • -T paranoid|sneaky|polite|normal|aggressive|insane: Set timing template (higher is faster). You can specify them with the -T option and their number (0–5) or their name. If you are on a decent broadband or ethernet connection, I would recommend always using -T4.
  • --min-rate <number>: Override Nmap’s dynamic timing to send packets no slower than <number> per second. When the option is given, Nmap will do its best to send packets as fast as or faster than the given rate.

References