Skip to content

Instantly share code, notes, and snippets.

@lichti
Last active January 4, 2024 22:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lichti/542ff04ad0dbca78bf7b0bea97d9b9cd to your computer and use it in GitHub Desktop.
Save lichti/542ff04ad0dbca78bf7b0bea97d9b9cd to your computer and use it in GitHub Desktop.
Automate nmap scanning for multiple domains with threads
#!/bin/bash
# Author: Gustavo Lichti
# Email: gustavo.lichti@gmail.com
# Usage: ./scan_hosts.sh --hosts <hosts_file> --host xpto.xxx --host xpto2.xxx --threads <number_of_threads> --output <output_directory>
SCRIPT_STARTED=$(date +"%Y%m%d_%H%M")
# Function do add log Line
log_this() {
# USAGE log_this <LOG_FILE> <TAG> <LOG_LINE>
# USAGE log_this ${LOG_FILE} <TAG> <LOG_LINE>
NOW=$(date +"%Y%m%d_%H:%M:%S")
LOG_FILE=$1; shift
TAG=$1; shift
LOG_LINE=$@
echo "[${NOW}] [${TAG}] ${LOG_LINE}" | tee -a ${LOG_FILE}
}
# Define the function to run nmap scan for unique IPs
run_nmap() {
IP="$1"
SCAN_STARTED=$(date +"%Y%m%d_%H%M")
log_this ${LOG_FILE} NMAP "Scanning IP: ${IP} at ${SCAN_STARTED}..."
nmap -Pn -sV -sS "${IP}" -oN "$OUTPUT_DIR/nmap_report_${IP}_${SCAN_STARTED}.txt"
SCAN_ENDED=$(date +"%Y%m%d_%H%M")
log_this ${LOG_FILE} NMAP "Scan completed for IP: ${IP} at ${SCAN_ENDED}"
}
# Function to process host(s)
process_hosts() {
while read -r host; do
ips=$(dig +short "$host" | grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
while read -r ip; do
echo "$host:$ip" >> "$OUTPUT_DIR/host_ip.txt"
echo "${ip}"
done <<< "$ips"
done | sort -u > "$OUTPUT_DIR/uniq_ips.txt"
log_this ${LOG_FILE} PROCESS "Domain to IP mapping completed."
# Run nmap in parallel with a limit of 10 processes for unique IPs
xargs -n 1 -P "${THREADS}" -a "$OUTPUT_DIR/uniq_ips.txt" -I{} bash -c 'run_nmap "$@"' _ {}
log_this ${LOG_FILE} PROCESS "IP scan completed."
}
# Check for provided hosts file or hosts
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--hosts)
HOSTS_FILE="$2"
shift # past argument
shift # past value
;;
--host)
HOSTS+=("$2")
shift # past argument
shift # past value
;;
--threads)
THREADS="$2"
shift # past argument
shift # past value
;;
--output)
OUTPUT_DIR ="$2"
shift # past argument
shift # past value
;;
*) # unknown option
echo "Ignoring unknown option: $key"
shift # past argument
;;
esac
done
# Set default values if not provided
THREADS="${THREADS:-10}"
OUTPUT_DIR="${OUTPUT_DIR:-$(dirname "$HOSTS_FILE")/output_${SCRIPT_STARTED}}"
LOG_FILE="$OUTPUT_DIR/log_${SCRIPT_STARTED}_$ip.txt"
# Exports to make it available to xargs
export -f run_nmap
export -f log_this
export LOG_FILE
export OUTPUT_DIR
# Create output directory and log file
mkdir -p "$OUTPUT_DIR"
touch ${LOG_FILE}
# Check if either hosts file or individual hosts are provided
if [ -z "$HOSTS_FILE" ] && [ ${#HOSTS[@]} -eq 0 ]; then
log_this ${LOG_FILE} INIT "Please provide a hosts file using --hosts or individual hosts using --host."
exit 1
fi
# Process individual hosts if provided
if [ ${#HOSTS[@]} -gt 0 ]; then
log_this ${LOG_FILE} HOST "Processing individual hosts:"
# Create a temporary hosts file
TMP_HOSTS_FILE="tmp_hosts_${SCRIPT_STARTED}"
for host in "${HOSTS[@]}"; do
log_this ${LOG_FILE} HOST "$host"
done > "$TMP_HOSTS_FILE"
if [ -n "$HOSTS_FILE" ]; then
log_this ${LOG_FILE} HOSTPARAM "Append extra hosts to HOSTS_FILE"
cat "$TMP_HOSTS_FILE" >> "$HOSTS_FILE"
else
log_this ${LOG_FILE} HOST "Setting TMP_HOSTS_FILE as HOSTS_FILE"
HOSTS_FILE="$TMP_HOSTS_FILE"
fi
fi
# Check if hosts file exists and process it
if [ -n "$HOSTS_FILE" ]; then
if [ ! -f "$HOSTS_FILE" ]; then
log_this ${LOG_FILE} HOSTSP "Hosts file ${HOSTS_FILE} not found"
exit 1
fi
log_this ${LOG_FILE} HOSTS "Processing hosts from file: ${HOSTS_FILE}"
process_hosts < "${HOSTS_FILE}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment