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, a specific comma-separated list, or the entire port range (
--all-ports) on a target host. - Address scanning — check a single IP, scan an IP range, or scan an entire subnet (CIDR).
- Chainable scans — pipe the hosts an address scan discovers straight into a port scan with
--stdin, turning host discovery and port scanning into a single pipeline. - 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 every port (1-65535)
# Scan an IPv6 host with a shorter timeout
# Read targets from stdin instead of -t (one host per line, or JSON/JSONL from `as`)
Exactly one target source is required — either -t/--host or --stdin — and they are mutually exclusive. Likewise -r, -s, and --all-ports are mutually exclusive.
| Flag | Description |
|---|---|
-t, --host <HOST> |
Target host (hostname, IPv4, or IPv6) |
--stdin |
Read targets from stdin instead of -t: one host per line, or the JSON/JSONL emitted by asphyxia as -o (the ip field is used) |
-r, --range <START> <END> |
Scan an inclusive range of ports |
-s, --specific <PORTS> |
Scan specific comma-separated ports |
-a, --all-ports |
Scan the entire port range (1-65535) |
--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:
|
Chaining discovery into port scanning (--stdin)
asphyxia ps --stdin reads its targets from standard input, so the hosts an address scan finds can flow directly into a port scan. The input format is auto-detected line by line: a line that is a JSON object or array has its ip field(s) taken as targets (so the -o json/-o jsonl output of as works as-is), and any other non-empty line is treated as a bare host or IP (so a plain hosts.txt works too). Blank lines are skipped and duplicate targets are scanned once.
# Discover live hosts on a subnet, then scan common ports on each of them
|
# Same, but scan every port on each discovered host
|
# Feed a hand-written host list
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.