Asphyxia
A fast and efficient network scanner written in Rust.
Description
Asphyxia is a command-line network scanner that helps you discover open ports on a host and find reachable hosts on a network. It runs scans in parallel for speed and shows live progress while it works.
Features
- Port scanning — scan a range of ports or a specific comma-separated list on a target host.
- Address scanning — check a single IP, scan an IP range, or scan an entire subnet (CIDR).
- IPv4 and IPv6 — every scan mode accepts both address families.
- Configurable timeout — tune the per-connection timeout with
--timeout. - Parallel execution — scans run concurrently via rayon, with tunable concurrency (
--concurrency) for large subnet scans. - Live progress bars — long-running scans show real-time progress.
- Colorized output — readable, colored terminal output.
- Machine-readable output — emit results as JSON or JSON Lines with
--outputfor piping into other tools.
Note: IPv6 subnet and range scans are capped at 65 536 addresses (e.g. a
/112), since larger IPv6 spaces are impractical to walk exhaustively.
Installation
Homebrew (macOS & Linux)
The formula is published automatically to the jtprogru/homebrew-tap tap on every release and supports macOS (Apple Silicon) and Linux (x86_64 & arm64).
Cargo
Install the latest published release from crates.io:
Or install the current main branch straight from the repository:
Prebuilt binaries
Download the archive for your platform from the latest release, unzip it, and place the asphyxia binary somewhere on your PATH. Builds are provided for:
- Linux:
x86_64,aarch64 - macOS:
aarch64(Apple Silicon)
Each archive is shipped with a detached GPG signature (.asc). After importing the signing key you can verify an archive with:
Building from source
Requires Rust 1.88 or newer (the project uses the 2024 edition).
The compiled binary will be available at target/release/asphyxia.
Usage
Asphyxia exposes two subcommands: ps (port scan) and as (address scan).
Port scanning (ps)
# Scan a range of ports (start end)
# Scan specific ports (comma-separated)
# Scan an IPv6 host with a shorter timeout
| Flag | Description |
|---|---|
-t, --host <HOST> |
Target host (hostname, IPv4, or IPv6) |
-r, --range <START> <END> |
Scan an inclusive range of ports |
-s, --specific <PORTS> |
Scan specific comma-separated ports |
--timeout <MS> |
Per-connection timeout in milliseconds (default: 2000) |
-c, --concurrency <N> |
Maximum concurrent connection attempts (default: 256) |
-o, --output <FORMAT> |
Output format: text (default), json, or jsonl |
Address scanning (as)
# Scan a subnet in CIDR notation (IPv4 or IPv6)
# Scan a single IP address (IPv4 or IPv6)
# Scan a range of IP addresses (start end)
# Scan a subnet with a custom timeout
| Flag | Description |
|---|---|
-s, --subnet <SUBNET> |
Scan a subnet, e.g. 192.168.1.0/24 or 2001:db8::/120 |
-t, --target <IP> |
Scan a single IPv4 or IPv6 address |
-r, --range <START> <END> |
Scan an inclusive range of IPs (start and end must share the same family) |
--timeout <MS> |
Per-connection timeout in milliseconds (default: 2000) |
-c, --concurrency <N> |
Maximum concurrent connection attempts (default: 256) |
-o, --output <FORMAT> |
Output format: text (default), json, or jsonl |
Host availability is inferred from a TCP probe: a host counts as up when it either accepts the connection or actively refuses it (a closed port still proves the host answered). A host that times out or is unreachable is reported as down — so a live host behind a firewall that silently drops packets may appear offline. This is an unprivileged, best-effort check, not an ICMP ping.
Machine-readable output (--output)
By default Asphyxia prints a colorized, human-friendly report. Pass --output json or --output jsonl (alias -o) to emit structured results instead — for example to feed a network map, a coverage analyzer, or any downstream tool. Each result is a self-contained record with the fields ip, port (omitted for address scans), proto, latency_ms, and status.
# One JSON object per open port, on its own line (JSON Lines)
# {"ip":"93.184.216.34","port":80,"proto":"tcp","latency_ms":12,"status":"open"}
# A single JSON array of available hosts
Records are written to stdout; the progress bar and any errors go to stderr, so a consumer reading stdout sees only the data stream. An empty result is [] for json and no output for jsonl. Pipe straight into jq:
|
Performance
Scanning is network-I/O-bound — most of the time is spent waiting for TCP handshakes and timeouts, not using the CPU. Asphyxia therefore runs many more concurrent probes than there are CPU cores (256 by default), so an unresponsive address (which blocks for the full --timeout) does not stall the rest of the scan.
To tune a scan:
--concurrency— raise it to finish large subnets faster (e.g.--concurrency 512for a/22); lower it if you want a gentler scan. Capped at 1024.--timeout— on a responsive LAN a shorter timeout (e.g.--timeout 500) makes unreachable hosts give up much sooner.
For example, a /24 with the defaults completes in roughly one timeout window instead of serially walking every address.
Dependencies
- clap — command-line argument parsing
- rayon — parallel computing
- indicatif — progress bars and spinners
- owo-colors — terminal colors
- ipnetwork — IP network address handling
Development
CI runs formatting, Clippy (warnings denied), build, and tests on every pull request and push to main.
License
This project is licensed under the MIT License.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.