RedAmon - Port Scanning (Masscan + Naabu)

August 10, 2026 · View on GitHub

Complete Technical Documentation

Modules: recon/masscan_scan.py, recon/port_scan.py Purpose: High-speed port scanning using Masscan and Naabu in parallel Author: RedAmon Security Suite


Table of Contents

  1. Overview
  2. Features
  3. Installation
  4. Configuration Parameters
  5. Architecture & Flow
  6. Output Data Structure
  7. Usage Examples
  8. Troubleshooting

Overview

The naabu_scan.py module integrates ProjectDiscovery's Naabu scanner into RedAmon's reconnaissance pipeline. Naabu is optimized for fast, reliable port scanning at scale.

⚠️ Important: Naabu runs exclusively via Docker. No native installation is supported.

Why Naabu?

FeatureTraditional ScannersNaabu
SpeedMinutes-hoursSeconds-minutes
Resource UsageHighLow
Docker SupportVariableNative
CDN DetectionLimitedBuilt-in
Rate ControlBasicFine-grained

How It Works

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│  Recon Data     │────▶│  naabu_scan.py   │────▶│  Enriched JSON  │
│  (hostnames,    │     │                  │     │  with ports,    │
│   IPs from DNS) │     │  1. Extract IPs  │     │  services, CDN  │
└─────────────────┘     │  2. Build targets│     └─────────────────┘
                        │  3. Run Naabu    │
                        │  4. Parse JSON   │
                        └──────────────────┘

Features

FeatureDescription
Fast ScanningSYN scan with configurable rate limiting
CDN DetectionIdentifies CDN-protected hosts (Cloudflare, Akamai, etc.)
Service DetectionMaps common ports to service names
Docker ExecutionNo local installation required
Passive ModeQuery Shodan InternetDB instead of active scanning
Incremental SavingResults saved progressively

Installation

Requirements

  • Docker installed and running
  • Root/sudo for SYN scans (or use CONNECT mode)

Setup

# Make sure Docker is running
sudo systemctl start docker

# Run the scan - image will be pulled automatically
python3 recon/main.py

Verify Docker is Ready

# Check Docker is running
docker info

# Optionally pre-pull the image
docker pull projectdiscovery/naabu:latest

Configuration Parameters

All parameters are configured via the webapp project settings (stored in PostgreSQL) or as defaults in project_settings.py:

Docker Settings

ParameterTypeDefaultDescription
NAABU_DOCKER_IMAGEstr"projectdiscovery/naabu:latest"Docker image to use

Port Selection

ParameterTypeDefaultDescription
NAABU_TOP_PORTSstr"1000"Number of top ports ("100", "1000", "full")
NAABU_CUSTOM_PORTSstr""Custom ports (overrides TOP_PORTS)

Port Examples:

NAABU_TOP_PORTS = "100"           # Top 100 ports
NAABU_TOP_PORTS = "1000"          # Top 1000 ports (default)
NAABU_CUSTOM_PORTS = "22,80,443"  # Specific ports
NAABU_CUSTOM_PORTS = "1-65535"    # Full port range

Scan Type

ParameterTypeDefaultDescription
NAABU_SCAN_TYPEstr"s"Scan type: "s" (SYN) or "c" (CONNECT)

Scan Types:

  • "s" (SYN) - Faster, more reliable, requires root/sudo
  • "c" (CONNECT) - No root needed, full TCP handshake

SYN Scan (Half-Open) - Default:

   You                                    Target
    │                                        │
    │──────────── 1. SYN ───────────────────►│
    │                                        │
    │◄─────────── 2. SYN/ACK ───────────────│  ← Port OPEN
    │                                        │
    │──────────── 3. RST (abort) ───────────►│  ← Connection killed
    │                                        │
    │         ❌ NO CONNECTION ESTABLISHED    │
    │         ❌ MINIMAL LOGGING ON TARGET    │

CONNECT Scan (Full TCP):

   You                                    Target
    │                                        │
    │──────────── 1. SYN ───────────────────►│
    │                                        │
    │◄─────────── 2. SYN/ACK ───────────────│
    │                                        │
    │──────────── 3. ACK ───────────────────►│  ← FULL HANDSHAKE
    │                                        │
    │         ✅ CONNECTION ESTABLISHED       │
    │         ✅ LOGGED BY APPLICATION        │
    │                                        │
    │──────────── 4. FIN ───────────────────►│
    │◄─────────── 5. FIN/ACK ───────────────│  ← GRACEFUL CLOSE
    │──────────── 6. ACK ───────────────────►│

Comparison:

AspectSYN (-s s)CONNECT (-s c)
Packets sent2 (SYN, RST)6+ (full handshake)
Speed⚡ Faster🐢 Slower
Stealth🥷 Stealthier👀 Easily detected
Application logging❌ Usually not✅ Logged
Requires root✅ Yes❌ No

Performance Settings

ParameterTypeDefaultDescription
NAABU_RATE_LIMITint1000Packets per second
NAABU_THREADSint25Concurrent threads
NAABU_TIMEOUTint10000Timeout per port (ms)
NAABU_RETRIESint3Retries for failed probes

Recommended Settings:

ScenarioRate LimitThreadsTimeout
Safe/Slow5001015000
Normal10002510000
Aggressive3000505000
Internal Network5000+1003000

Feature Flags

ParameterTypeDefaultDescription
NAABU_EXCLUDE_CDNboolTrueSkip non-standard ports on CDN hosts
NAABU_DISPLAY_CDNboolTrueShow CDN information in output
NAABU_SKIP_HOST_DISCOVERYboolTrueAssume all hosts are up
NAABU_VERIFY_PORTSboolTrueExtra TCP check to verify ports
NAABU_PASSIVE_MODEboolFalseUse Shodan InternetDB (no active scan)

NAABU_EXCLUDE_CDN - CDN Port Filtering

Problem: CDN providers (Cloudflare, Akamai, AWS CloudFront) expose thousands of ports on their edge servers that belong to the CDN infrastructure, not the actual target.

Without CDN Exclusion:
┌─────────────────────────────────────────────────────────────────┐
│  Target: example.com (behind Cloudflare)                        │
│                                                                 │
│  Scan Result: Ports 22, 80, 443, 2052, 2053, 2082, 2083,       │
│               2086, 2087, 2095, 2096, 8080, 8443...            │
│                                                                 │
│  Reality: Only 80/443 are YOUR server                          │
│           All others are Cloudflare's infrastructure ❌         │
└─────────────────────────────────────────────────────────────────┘

With CDN Exclusion (NAABU_EXCLUDE_CDN = True):
┌─────────────────────────────────────────────────────────────────┐
│  Target: example.com (behind Cloudflare)                        │
│                                                                 │
│  Scan Result: Ports 80, 443                                    │
│  CDN Detected: cloudflare ✅                                    │
│                                                                 │
│  Clean results - only ports that reach YOUR origin server      │
└─────────────────────────────────────────────────────────────────┘
SettingBehavior
True (default)Only scan 80/443 on CDN hosts, skip other ports
FalseScan all ports (includes CDN infrastructure noise)

NAABU_DISPLAY_CDN - CDN Detection Display

Shows which CDN provider protects each host in the output.

{
  "host": "cdn.example.com",
  "ip": "104.16.123.96",
  "ports": [80, 443],
  "cdn": "cloudflare",    // ← This field
  "is_cdn": true          // ← And this field
}

Detected CDN Providers:

  • Cloudflare, Akamai, Fastly, AWS CloudFront
  • Google Cloud CDN, Azure CDN, Incapsula
  • MaxCDN, KeyCDN, StackPath, and more

NAABU_SKIP_HOST_DISCOVERY - Skip Ping Check (-Pn)

Host Discovery = Check if host is alive before scanning ports.

WITH Host Discovery (NAABU_SKIP_HOST_DISCOVERY = False):
┌─────────────────────────────────────────────────────────────────┐
│   You                                        Target             │
│    │                                            │               │
│    │   PHASE 1: Is host alive?                  │               │
│    │                                            │               │
│    │──────────── ICMP Ping ────────────────────►│               │
│    │◄─────────── Pong (or timeout) ────────────│               │
│    │                                            │               │
│    │   If NO response → Host "DOWN" → SKIP ❌   │               │
│    │   If response → Continue to port scan      │               │
│    │                                            │               │
│    │   PHASE 2: Port scan (only if UP)          │               │
│    │──────────── SYN port 80 ──────────────────►│               │
└─────────────────────────────────────────────────────────────────┘

WITHOUT Host Discovery (NAABU_SKIP_HOST_DISCOVERY = True):
┌─────────────────────────────────────────────────────────────────┐
│   You                                        Target             │
│    │                                            │               │
│    │   SKIP Phase 1 - Assume host is UP         │               │
│    │                                            │               │
│    │   Go directly to port scanning             │               │
│    │──────────── SYN port 80 ──────────────────►│               │
│    │──────────── SYN port 443 ─────────────────►│               │
└─────────────────────────────────────────────────────────────────┘
SettingBehaviorUse When
True (default)Skip ping, assume all hosts UPFirewalls block ICMP, hosts from DNS
FalsePing first, skip "dead" hostsLarge IP ranges, internal networks

Why default is True: RedAmon already confirmed hosts exist via DNS resolution. Many firewalls block ICMP ping, causing false negatives.


NAABU_VERIFY_PORTS - Double-Check Open Ports

After finding an open port via SYN scan, perform an additional TCP connection to verify.

Without Verification:
┌─────────────────────────────────────────────────────────────────┐
│   SYN scan says port 8080 is OPEN                              │
│   → Report as open (might be false positive)                   │
└─────────────────────────────────────────────────────────────────┘

With Verification (NAABU_VERIFY_PORTS = True):
┌─────────────────────────────────────────────────────────────────┐
│   SYN scan says port 8080 is OPEN                              │
│   → Try full TCP connection to verify                          │
│   → Connection successful? Report as open ✅                    │
│   → Connection failed? Discard (was false positive) ❌          │
└─────────────────────────────────────────────────────────────────┘
SettingBehaviorTrade-off
True (default)Verify each open port with TCP connectMore accurate, slightly slower
FalseTrust SYN scan results directlyFaster, may have false positives

Reduces false positives from:

  • Stateful firewalls that RST after SYN/ACK
  • Load balancers with connection limits
  • Rate-limiting that causes inconsistent responses

NAABU_PASSIVE_MODE - Shodan InternetDB (No Active Scan)

Instead of actively scanning the target, query Shodan's InternetDB for known open ports.

Active Scanning (NAABU_PASSIVE_MODE = False):
┌─────────────────────────────────────────────────────────────────┐
│   You ──────── SYN packets ──────────────────► Target           │
│                                                                 │
│   • Sends packets to target                                    │
│   • Target sees your IP                                        │
│   • May trigger IDS/IPS alerts                                 │
│   • Real-time results                                          │
└─────────────────────────────────────────────────────────────────┘

Passive Mode (NAABU_PASSIVE_MODE = True):
┌─────────────────────────────────────────────────────────────────┐
│   You ──────── API query ──────────────────► Shodan InternetDB  │
│                                                                 │
│   • NO packets to target                                       │
│   • Target never sees you                                      │
│   • 100% stealth                                               │
│   • Data may be days/weeks old                                 │
└─────────────────────────────────────────────────────────────────┘
SettingBehaviorTrade-off
False (default)Active SYN scanReal-time, target aware
TrueQuery Shodan databaseStealth, but potentially stale data

Use Passive Mode when:

  • Initial reconnaissance (don't want to touch target yet)
  • Target has strict IDS/IPS
  • Legal constraints on active scanning
  • Quick overview before active scan

Limitations:

  • Data freshness depends on Shodan's last scan
  • May miss recently opened ports
  • May show ports that are now closed

CDN Handling

When NAABU_EXCLUDE_CDN = True:

  • CDN-protected hosts only scanned on ports 80/443
  • Reduces false positives from CDN edge servers
  • Still reports CDN detection in output

Architecture & Flow

Pipeline context: Port scanning runs in GROUP 3 of the parallelized recon pipeline, concurrently with Shodan enrichment via ThreadPoolExecutor. The run_port_scan_isolated() function accepts a read-only snapshot of recon data and returns only the port scan results, making it thread-safe for parallel execution.

Execution Flow

1. INITIALIZATION
   └── Check Docker availability
   └── Pull Naabu image if needed

2. TARGET EXTRACTION
   └── Parse recon_data JSON
   └── Extract unique IPs from DNS records
   └── Extract hostnames/subdomains
   └── Build IP-to-hostname mapping

3. SCAN EXECUTION
   └── Create targets file (hostnames preferred over IPs)
   └── Build Naabu Docker command
   └── Execute with JSON Lines output
   └── Monitor progress

4. RESULT PROCESSING
   └── Parse JSONL output line by line
   └── Group results by host and IP
   └── Map ports to service names
   └── Calculate statistics

5. DATA ENRICHMENT
   └── Add "naabu" section to recon_data
   └── Save incrementally to JSON file
   └── Generate summary statistics

Docker Command Structure

docker run --rm \
  --net=host \                              # Required for SYN scans
  -v /targets:/targets:ro \
  -v /output:/output \
  projectdiscovery/naabu:latest \
  -list /targets/targets.txt \
  -o /output/naabu_output.json \
  -json \
  -silent \
  -top-ports 1000 \
  -scan-type s \
  -rate 1000 \
  -c 25 \
  -timeout 10000 \
  -retries 3 \
  -cdn \                                    # Display CDN
  # -sD not used (not yet implemented in naabu)
  -Pn \                                     # Skip host discovery
  -verify                                   # Verify ports

Output Data Structure

Complete JSON Schema

{
  "naabu": {
    "scan_metadata": {
      "scan_timestamp": "2024-01-15T12:00:00.000000",
      "scan_duration_seconds": 45.2,
      "docker_image": "projectdiscovery/naabu:latest",
      "scan_type": "syn",
      "ports_config": "top-1000",
      "rate_limit": 1000,
      "passive_mode": false,
      "proxy_used": false,
      "total_targets": 15,
      "cdn_exclusion": true
    },
    
    "by_host": {
      "example.com": {
        "host": "example.com",
        "ip": "93.184.216.34",
        "ports": [80, 443, 8080],
        "port_details": [
          {
            "port": 80,
            "protocol": "tcp",
            "service": "http"
          },
          {
            "port": 443,
            "protocol": "tcp",
            "service": "https"
          },
          {
            "port": 8080,
            "protocol": "tcp",
            "service": "http-proxy"
          }
        ],
        "cdn": null,
        "is_cdn": false
      },
      "cdn.example.com": {
        "host": "cdn.example.com",
        "ip": "104.16.123.96",
        "ports": [80, 443],
        "port_details": [...],
        "cdn": "cloudflare",
        "is_cdn": true
      }
    },
    
    "by_ip": {
      "93.184.216.34": {
        "ip": "93.184.216.34",
        "hostnames": ["example.com", "www.example.com"],
        "ports": [80, 443, 8080],
        "cdn": null,
        "is_cdn": false
      }
    },
    
    "all_ports": [22, 80, 443, 3306, 8080],
    
    "ip_to_hostnames": {
      "93.184.216.34": ["example.com", "www.example.com"]
    },
    
    "summary": {
      "hosts_scanned": 15,
      "ips_scanned": 12,
      "hosts_with_open_ports": 10,
      "total_open_ports": 45,
      "unique_ports": [22, 80, 443, 3306, 8080],
      "unique_port_count": 5,
      "cdn_hosts": 3
    }
  }
}

Service Name Mapping

PortService
21ftp
22ssh
23telnet
25smtp
53dns
80http
110pop3
143imap
443https
445microsoft-ds
3306mysql
3389ms-wbt-server
5432postgresql
6379redis
8080http-proxy
8443https-alt
27017mongodb

Usage Examples

Basic Usage (via main.py)

# Include "port_scan" in SCAN_MODULES in project settings
SCAN_MODULES = ["initial_recon", "naabu", "httpx", "nuclei"]

# Run the full pipeline
python3 recon/main.py

Standalone Enrichment

from naabu_scan import enrich_recon_file
from pathlib import Path

enriched = enrich_recon_file(Path("output/recon_example.com.json"))

Command Line

# Enrich an existing recon file
python3 recon/naabu_scan.py output/recon_example.com.json

Configuration Profiles

Quick Scan (Fast):

NAABU_TOP_PORTS = "100"
NAABU_RATE_LIMIT = 3000
NAABU_THREADS = 50
NAABU_VERIFY_PORTS = False

Comprehensive Scan:

NAABU_TOP_PORTS = "1000"
NAABU_RATE_LIMIT = 1000
NAABU_THREADS = 25
NAABU_VERIFY_PORTS = True

Stealth Scan:

NAABU_TOP_PORTS = "100"
NAABU_RATE_LIMIT = 100
NAABU_THREADS = 5
NAABU_SCAN_TYPE = "c"  # CONNECT instead of SYN

Full Port Scan:

NAABU_CUSTOM_PORTS = "1-65535"
NAABU_RATE_LIMIT = 5000
NAABU_THREADS = 100
NAABU_TIMEOUT = 5000

Troubleshooting

Common Issues

"Docker not found"

# Install Docker
sudo apt install docker.io  # Debian/Ubuntu

# Start Docker daemon
sudo systemctl start docker
sudo systemctl enable docker

"Permission denied" for SYN scan

# Option 1: Run with sudo
sudo python3 recon/main.py

# Option 2: Use CONNECT scan (no root needed)
NAABU_SCAN_TYPE = "c"

"No open ports found"

Possible causes:

  1. Target firewall blocking scans
  2. Rate limiting triggered
  3. CDN blocking non-80/443 ports

Solutions:

# Reduce rate limit
NAABU_RATE_LIMIT = 100

# Disable CDN exclusion to see all ports
NAABU_EXCLUDE_CDN = False

# Try passive mode
NAABU_PASSIVE_MODE = True

Scan too slow

# Increase performance
NAABU_RATE_LIMIT = 3000
NAABU_THREADS = 50
NAABU_TIMEOUT = 5000
NAABU_RETRIES = 1

Debug Mode

Run Naabu manually via Docker:

docker run --rm --net=host \
  projectdiscovery/naabu:latest \
  -host example.com \
  -top-ports 100 \
  -v -debug

Security Considerations

⚠️ Legal Warning: Only scan systems you have explicit permission to test.

RiskMitigation
Rate limiting/bansReduce NAABU_RATE_LIMIT
IDS/IPS detectionUse CONNECT mode, lower rate
CDN blockingUse NAABU_EXCLUDE_CDN = True
DetectionReduce rate limit

Safe Defaults

NAABU_RATE_LIMIT = 500
NAABU_THREADS = 10
NAABU_TOP_PORTS = "100"
NAABU_EXCLUDE_CDN = True

Dependencies

PackagePurpose
DockerContainer runtime for Naabu
projectdiscovery/naabu:latestNaabu Docker image (auto-pulled)
Python 3.8+Script runtime

References


Masscan Port Scanner

Overview

The masscan_scan.py module integrates Robert David Graham's Masscan — the fastest Internet port scanner — into RedAmon's reconnaissance pipeline. Masscan runs as a native binary built from source inside the recon container (not Docker-in-Docker). Both Masscan and Naabu are enabled by default and run in parallel; results are merged and deduplicated automatically.

Masscan vs Naabu

FeatureMasscanNaabu
SpeedFastest (10M+ pps capable)Fast (1000s pps)
Best forLarge CIDR ranges, bulk IP scanningHostname-based scanning, CDN detection
CDN DetectionNoBuilt-in
Passive ModeNoYes (Shodan InternetDB)
ExecutionNative binaryDocker container
Banner GrabbingOptional (--banners)No
Output FormatNDJSON (-oD)JSON

How It Works

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│  Recon Data      │────▶│  masscan_scan.py  │────▶│  masscan_scan   │
│  (IPs from DNS,  │     │                  │     │  key in JSON    │
│   metadata)      │     │  1. Extract IPs  │     └────────┬────────┘
└─────────────────┘     │  2. Write targets │              │
                        │  3. Run masscan   │     ┌────────▼────────┐
                        │  4. Parse NDJSON  │     │ merge into      │
                        └──────────────────┘     │ port_scan key   │
                                                  └─────────────────┘

Pipeline integration: Masscan runs in the same ThreadPoolExecutor as Naabu (GROUP 3 fan-out). After both complete, merge_port_scan_results() combines their output into the unified port_scan key, deduplicating by host+port. Downstream modules (httpx, Nuclei, graph DB) consume port_scan unchanged.


Configuration Parameters

All parameters are configured via the webapp project settings or as defaults in project_settings.py:

ParameterTypeDefaultDescription
MASSCAN_ENABLEDboolTrueEnable/disable Masscan
MASSCAN_TOP_PORTSstr"1000"Top N ports ("100", "1000", "full")
MASSCAN_CUSTOM_PORTSstr""Custom ports (overrides TOP_PORTS)
MASSCAN_RATEint1000Packets per second
MASSCAN_BANNERSboolFalseCapture service banners
MASSCAN_WAITint10Seconds to wait for late responses
MASSCAN_RETRIESint1Retry attempts
MASSCAN_EXCLUDE_TARGETSstr""Comma-separated IPs/CIDRs to exclude

Port Examples:

MASSCAN_TOP_PORTS = "100"              # Top 100 ports
MASSCAN_TOP_PORTS = "1000"             # Top 1000 ports (default)
MASSCAN_TOP_PORTS = "full"             # All 65535 ports
MASSCAN_CUSTOM_PORTS = "80,443,8080"   # Specific ports
MASSCAN_CUSTOM_PORTS = "8080-8090"     # Port range

Key Design Decisions

  • NDJSON output (-oD) instead of -oJ to avoid Masscan's known trailing-comma JSON bug
  • Native binary (built from source in multi-stage Dockerfile) instead of Docker-in-Docker for simplicity
  • Results merged into existing port_scan key so all downstream modules work unchanged
  • Mock hostname detection prevents invalid URLs in IP mode (e.g., 10-0-0-1 replaced with 10.0.0.1)
  • Raw SYN packets bypass the TCP stack for maximum scanning speed

Stealth Mode Behavior

In stealth mode, Masscan is disabled (active SYN scanning generates significant network traffic). Naabu switches to passive mode (Shodan InternetDB queries).


References


Documentation updated for RedAmon v3.1 - Port Scanning Module (Masscan + Naabu)