From d3a70cadc1d2ee80c03b4d6e0aa78fae968237d2 Mon Sep 17 00:00:00 2001 From: Theodore Kaczynski Date: Fri, 15 May 2026 03:43:46 +0300 Subject: [PATCH] addition: subscan --- README.md | 61 +++++++++++++++++++++++++ subscan.sh | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 README.md create mode 100755 subscan.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..6619c8a --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# VPN TOOLS + +## SubScan + +A Bash script that scans an IPv4 subnet for hosts with TCP port 443 open, extracts TLS certificate domains (SANs), and validates whether any SAN resolves (forward DNS) to the scanned IP. Outputs a Markdown report. + +### Usage +Required: bash, nmap, dig, openssl. + +Basic invocation: +``` +./script.sh 82.22.146.0/24 +``` +Output: a timestamped Markdown file named like `subscan_82.22.146.0-24_YYYYMMDD_HHMMSS.md`. + +### What it does (high level) +- Verifies required tools (prompts to install on Debian/Ubuntu via apt-get if missing). +- Runs nmap to find hosts with port 443 open. +- Connects to each host with openssl s_client, extracts certificate subjectAltName DNS entries. +- For each extracted domain, performs forward DNS (dig) and checks if any A record matches the host IP. +- Produces a Markdown report grouping hosts into "Valid" (a SAN resolves back to the IP) and "Invalid" (no SANs or no matching forward DNS). +- Cleans up temporary files. + +### Key behavior and defaults +- nmap options: -Pn -p443 --open -T4 --min-rate=1000 (fast scan, treats hosts as up). +- openssl s_client: 4s timeout per connection (using timeout command). +- dig: +short +timeout=3 +tries=2. +- Report file: `subscan__YYYYMMDD_HHMMSS.md`. +- Exit codes: + - 0 on success (report written), + - 1 if usage error, missing tools and user declined install, or no hosts with 443 open. + +### Important notes & limitations +- Requires network access and privileges to run nmap and install packages if chosen. +- The script assumes IPv4 addresses and that visible A records map directly to the scanned IP. +- TLS extraction relies on the certificate presented when connecting without using a specific SNI (the script sets SNI to `dummy`); some servers may require a correct SNI to present relevant certificates. +- False negatives possible if: + - Certificate SANs are absent or located only in the certificate presented for a different SNI. + - DNS uses CNAMEs, load balancers, or geo/anycast addressing where the certificate domain resolves to different IPs. + - Hosts use IPv6-only addresses. +- Use responsibly and only on networks you are authorized to scan. + +### Example output (trimmed) +The generated Markdown report includes metadata and two sections: + +### Valid (TLS domain resolves back to IP) +- 203.0.113.5 → example.com + +### Invalid (No match or no TLS domains) +- 198.51.100.12 → No TLS domains found +- 198.51.100.20 → site1.example.net site2.example.org + +### Installation (optional) +On Debian/Ubuntu, if you allow the script to auto-install it will run: +``` +sudo apt-get update +sudo apt-get install -y nmap dnsutils openssl +``` + +### License +No license specified — treat as permissive example code. Modify and use as needed. diff --git a/subscan.sh b/subscan.sh new file mode 100755 index 0000000..7dd44d0 --- /dev/null +++ b/subscan.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +MAGENTA='\033[0;35m' +NC='\033[0m' + +SUBNET="$1" + +if [ -z "$SUBNET" ]; then + echo -e "${RED}Usage: $0 (example: 82.22.146.0/24)${NC}" + exit 1 +fi + +echo -e "${GREEN}[+] Starting scan on subnet: ${CYAN}$SUBNET${NC}" +echo + +check_dependencies() { + local missing=() + command -v nmap >/dev/null 2>&1 || missing+=("nmap") + command -v dig >/dev/null 2>&1 || missing+=("dig") + command -v openssl >/dev/null 2>&1 || missing+=("openssl") + + if [ ${#missing[@]} -ne 0 ]; then + echo -e "${RED}[-] Missing tools: ${missing[*]}${NC}" + read -p "Install them automatically? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + sudo apt-get update + sudo apt-get install -y nmap dnsutils openssl + else + echo -e "${RED}Please install missing tools and try again.${NC}" + exit 1 + fi + fi +} + +check_dependencies + +SAFE_SUBNET=$(echo "$SUBNET" | tr '/' '-') +OUTPUT_FILE="subscan_${SAFE_SUBNET}_$(date +%Y%m%d_%H%M%S).md" + +echo -e "${GREEN}[+] Scanning for open port 443...${NC}" + +nmap -Pn -p443 --open -T4 --min-rate=1000 -oG - "$SUBNET" 2>/dev/null | \ +grep "443/open" | awk '{print $2}' > /tmp/open_443.txt + +mapfile -t IPS < /tmp/open_443.txt +TOTAL=${#IPS[@]} + +if [ "$TOTAL" -eq 0 ]; then + echo -e "${RED}[-] No hosts with port 443 open found.${NC}" + rm -f /tmp/open_443.txt + exit 1 +fi + +echo -e "${GREEN}[+] Found ${CYAN}$TOTAL${GREEN} hosts with port 443 open.${NC}" +echo -e "${GREEN}[+] Extracting TLS domains + validating with forward DNS...${NC}" + +VALID=() +INVALID=() + +CURRENT=0 + +for ip in "${IPS[@]}"; do + CURRENT=$((CURRENT + 1)) + printf "\r${GREEN}[+] Progress: ${CYAN}%d/%d${NC}" "$CURRENT" "$TOTAL" + + tls_domains=$(echo | timeout 4 openssl s_client -connect "$ip":443 -servername dummy 2>/dev/null | \ + openssl x509 -noout -subject -ext subjectAltName 2>/dev/null | \ + grep -oE 'DNS:[^, ]+' | sed 's/DNS://' | tr '\n' ' ' | sed 's/ $//') + + if [ -z "$tls_domains" ]; then + INVALID+=("$ip → No TLS domains found") + continue + fi + + is_valid=0 + matched_domain="" + + for domain in $tls_domains; do + forward_ips=$(dig "$domain" +short +timeout=3 +tries=2 2>/dev/null | \ + grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$') + + if echo "$forward_ips" | grep -q "^${ip}$"; then + is_valid=1 + matched_domain="$domain" + break + fi + done + + if [ $is_valid -eq 1 ]; then + VALID+=("$ip → $matched_domain") + else + INVALID+=("$ip → $tls_domains") + fi +done + +printf "\r${GREEN}[+] Progress: ${CYAN}%d/%d${GREEN} - Done!${NC}%*s\n" "$TOTAL" "$TOTAL" 20 "" + +{ + echo "---" + echo "TLS + DNS Validation Report" + echo "Subnet : $SUBNET" + echo "Total Hosts: $TOTAL" + echo "Valid : ${#VALID[@]}" + echo "Invalid : ${#INVALID[@]}" + echo "Date : $(date)" + echo "---" + echo "" + echo "## Valid (TLS domain resolves back to IP)" + for line in "${VALID[@]}"; do + echo "- $line" + done + echo "" + echo "## Invalid (No match or no TLS domains)" + for line in "${INVALID[@]}"; do + echo "- $line" + done +} > "$OUTPUT_FILE" + +echo +echo -e "${GREEN}[+] Scan completed!${NC}" +echo -e "${GREEN}[+] Results saved to: ${CYAN}$OUTPUT_FILE${NC}" +echo +echo -e "${YELLOW}Tip: Valid entries are best for SNI imitation.${NC}" + +rm -f /tmp/open_443.txt