Skip to main content

A fast, async port scanner with banner grabbing

Project description

Socket Scout

A high-performance, concurrent port scanner written in Python that focuses on correct asynchronous design, per-host isolation, and extensibility. This project demonstrates systems-oriented software engineering with an asyncio-based pipeline for efficient multi-host and large-range scanning.

Ethical Disclaimer

This tool is intended for educational purposes and should only be used on systems you own or have explicit permission to test. Unauthorized scanning of networks or systems may be illegal or unethical. Always ensure you have proper authorization before using this tool.

Notice

  • This project is designed to run on Linux, macOS, and Windows systems with Python 3.10 or later installed.
  • Root/sudo privileges required: Raw socket operations require elevated privileges, so you must run this tool with sudo or as root. Use with caution and only on authorized systems.
  • This project is a work in progress, and I am open to suggestions for improvement. Please let me know if you have any ideas or feedback.

Devices Supported

  • Linux distributions (Ubuntu, Debian, Fedora, etc.)
  • Windows 10 (WSL) or later
  • macOS

MAC Limitations

  • Due to the way of how macOS handles raw sockets, the SYN scan mode may not work as expected
  • SYN scan is still available on macOS, but may produce unreliable results. TCP connect scan is recommended for macOS users.
  • Possible fixes for more consistent results (not guaranteed):
    • Increase the timeout (-T flag) to allow more time for responses
    • Set retry count (-r flag) to 1 or higher to allow for multiple attempts
    • Use a smaller port range to reduce the number of packets sent

Dependencies

System Requirements

  • Python 3.10 or later
  • libpcap library (required for packet manipulation)

Install libpcap:

# Ubuntu/Debian
sudo apt-get install libpcap-dev

# Fedora/RHEL
sudo dnf install libpcap-devel

# macOS (usually pre-installed, or via Homebrew)
brew install libpcap

Python Packages

  • See pyproject.toml for Python package dependencies (automatically installed with pip)

Installation

Note: Due to PEP 668 (externally managed environments), it's recommended to use pipx for CLI tools or install in a virtual environment.

Recommended: Using pipx

# Install pipx with apt if you don't have it (or use your package manager)
sudo apt-get install pipx
pipx ensurepath

source ~/.bashrc  # or ~/.zshrc to refresh your shell environment

# Install socketscout
pipx install socketscout

# Create a symbloic link for sudo usage (since pipx installs to ~/.local/bin whiVch is not in the sudo PATH)
sudo ln -s ~/.local/bin/socketscout /usr/local/bin/socketscout

# Run with sudo (required)
sudo socketscout -t localhost

Alternative: From PyPI with pip

# Create a virtual environment
python3 -m venv ~/socketscout-env
source ~/socketscout-env/bin/activate
pip install socketscout

# Run with sudo
sudo ~/socketscout-env/bin/socketscout -t localhost

From GitHub Release

# In a virtual environment
python3 -m venv ~/socketscout-env
source ~/socketscout-env/bin/activate
pip install https://github.com/JoelBeau/socketscout/releases/latest/download/socketscout-1.0.3-py3-none-any.whl

From Source

# Clone and install in development mode
git clone https://github.com/JoelBeau/socketscout.git
cd socketscout
sudo ./build.sh

Features

  • Concurrent scanning across multiple hosts and large port ranges
  • Asyncio-based pipeline to maximize throughput and avoid blocking
  • Per-host state isolation to prevent cross-target interference
  • TCP connect scanning as the default method
  • Optional SYN-based scanning for reduced connection overhead
  • Modular banner-grabbing stage for service metadata extraction
  • Configurable timeouts, retries, and concurrency limits
  • Clean separation between scan logic, networking primitives, and output

How to Use

Note: Sudo is required to use this tool due to the need for raw socket operations. Make sure to run with appropriate permissions and only on systems you own or have explicit permission to test.

  1. Basic scan of a single host (default port range is 1-1025):

       sudo socketscout -t localhost
    
  2. Scan specific ports:

       sudo socketscout -t localhost -p 22,80,443
    
  3. Scan a port range:

       sudo socketscout -t localhost -p 1-1024
    
  4. Scan with banner grabbing & increased verbosity:

       sudo socketscout -t localhost -v 2 -b
    
  5. Output to text file (other formats are available):

       sudo socketscout -t localhost -o test.txt
    
  6. View all available options:

       sudo socketscout --help
    

Output Examples

  • Default output format (text, to console):

       sudo socketscout -t localhost -p 22,80,443 -b
    

    Example of text output format to console

  • JSON output format to console:

       sudo socketscout -t localhost -p 22,80,443 -b -o json
    

    Example of JSON output format to console

  • CSV output format to console:

       sudo socketscout -t localhost -p 22,80,443 -b -o csv
    

    Example of CSV output format to console

For each output type, they can be written to a file instead of the console by providing a filename instead of "json" or "text" to the -o flag. For example:

   sudo socketscout -t localhost -p 22,80,443 -b -o results.txt

Note that the file will be renamed by adding on the hostname (if applicable) to the end of the filename, so the above command will actually write to results-localhost.txt. This is to prevent overwriting results when scanning multiple hosts.

Usage Examples

Programmatic Usage

You can also import and use the scanner in your own Python scripts:

   import asyncio
   from port_scanner import Scanner

   async def main():

      flags = {
         "scan_type": "tcp",
         "target": "example.com",
         "ports": [80, 443]
      }

      scanner = SCANNER_CLASS[flags["scan_type"]](**flags)
      results = await scanner.scan(**flags)
      for port in results:
         print(f"{port}")

   asyncio.run(main())

Logging

The port scanner includes a centralized logging system that tracks all operations and events during scanning.

Location: port_scanner/log.py

Features:

  • File-based logging to port_scanner.log
  • Configurable log directory via port_scanner/config.py
  • Automatic log flushing on program exit
  • Timestamp, logger name, and log level included in each message
  • Default logging level: INFO

Log Output: Logs are written to the configured log directory (typically ~/.config/port_scanner/logs/ or your custom LOG_DIR setting in config.py).

Using the Logger in Your Code:

from port_scanner.log import setup_logger

# Create a logger for your module
logger = setup_logger(__name__)

# Log at different levels
logger.info("Scan started")
logger.warning("High latency detected")
logger.error("Connection timeout")

Design Overview

This project is structured as a pipeline rather than a monolithic loop. Each target host maintains its own scanning state and concurrency limits, preventing shared-state bugs and ensuring predictable behavior when scanning multiple hosts concurrently.

Scanning is performed asynchronously using non-blocking I/O. Blocking operations are isolated from the event loop to preserve responsiveness and correctness. Banner grabbing is implemented as a separate stage that executes only after a port is confirmed open, reducing unnecessary connections and improving overall efficiency.

Input → Host Queue → Scanner Pipeline → Port Check → Banner Grab → Output
                          ↓
                    Per-Host State
                   (isolation, limits)

Architecture & Components

The port scanner is organized into modular components, each responsible for a specific aspect of the scanning pipeline:

core/

  • scanner.py: Main orchestration engine that manages the concurrent scanning pipeline across multiple hosts. Handles semaphore-based concurrency control, error handling, and per-host state isolation.
  • output.py: Formats and displays scan results in multiple formats (text, CSV, JSON) to console or file.

scanners/

  • base.py: Abstract base class Scan defining the scanner interface. Implements shared functionality for banner grabbing across HTTP, SSH, and generic services.
  • tcp.py: TCPConnect implementation—establishes full TCP connections to test port availability. Default, reliable scanning method.
  • syn.py: SYNScan implementation—uses raw SYN packets for lower-overhead scanning. Requires elevated privileges.

models/

  • port.py: Port data class representing scan results with service metadata (port number, state, banner info).
  • arguments.py: Argument validation and normalization for command-line flags.

utils/

  • network.py: Network helper functions for IP/CIDR/hostname parsing, DNS resolution, and reachability checks.
  • validation.py: Input validation for ports, targets, and configuration parameters.

config.py & log.py

  • config.py: Centralized configuration constants (timeouts, concurrency limits, log directories).
  • log.py: Logging setup with file-based output and configurable log levels.

Component Interaction:

CLI Input → models/arguments → utils/validation → core/scanner → scanners/{tcp,syn} → core/output
                ↓                                                                           ↓
           log.py ←──────────────────────────────────────────────────────────────────────→

Scanning Modes

TCP Connect Scan

  • Establishes a full TCP connection to determine port availability
  • Reliable and portable
  • Works without elevated privileges
  • Default scanning method
   # Example: TCP connect scan
   flags = {
      "scan_type": "tcp",
      "target": "example.com",
      "ports": [80, 443]
   }

   scanner = SCANNER_CLASS[flags["scan_type"]](**flags)
   results = await scanner.scan(**flags)

SYN Scan (Optional)

  • Sends crafted SYN packets using Scapy to infer port state
  • Lower overhead than full connections
  • Intended for controlled or lab environments
  • Preforms better with large port ranges and many hosts
   # Example: SYN connect scan
   flags = {
      "scan_type": "syn",
      "target": "example.com",
      "ports": [80, 443]
   }

   scanner = SCANNER_CLASS[flags["scan_type"]](**flags)
   results = await scanner.scan(**flags)

Concurrency Model

  • Asynchronous task scheduling using asyncio
  • Global concurrency limits to control total in-flight operations
  • Per-host concurrency limits to isolate scan behavior
  • Non-blocking network operations throughout the pipeline

This design allows the scanner to scale efficiently while maintaining correctness under load.

   # Configure concurrency limits in conf.py
   DEFAULT_CONCURRENCY_FOR_SCANS = 800

Use Cases

  • Studying asynchronous programming and concurrency patterns in Python
  • Understanding network scanning tradeoffs and implementation details
  • Demonstrating systems-oriented software engineering skills
  • Exploring extensible security and networking tooling

Contributing

Suggestions are welcome! Please open an issue or submit a pull request.

License

MIT License - see LICENSE file for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

socketscout-1.0.3.tar.gz (39.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

socketscout-1.0.3-py3-none-any.whl (41.5 kB view details)

Uploaded Python 3

File details

Details for the file socketscout-1.0.3.tar.gz.

File metadata

  • Download URL: socketscout-1.0.3.tar.gz
  • Upload date:
  • Size: 39.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for socketscout-1.0.3.tar.gz
Algorithm Hash digest
SHA256 5f4b6b9ce68490560ef4b4ec5fc8f946505a8f8e7bb9bf7aca991357d555213c
MD5 e957d232a24b97a8df3b55b9198045df
BLAKE2b-256 551dff03e4567f67d82efc1a0fa4c3f6e9cada9cbac7cac15413465b9f2550c9

See more details on using hashes here.

File details

Details for the file socketscout-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: socketscout-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 41.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for socketscout-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 cdc48990acd533859f5afa8016d1dcfa1bc533e5cc810efbdea5b17efecc1c57
MD5 84990976748f95fcba8dc81792d14894
BLAKE2b-256 4157e36e42ff40a7922fcc375b5d2cf8b25b7650ba977e5828ed6e85ad2129f4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page