Generic TCP + TLS/SNI Scanner
A high-performance asynchronous TCP and TLS/SNI scanner for probing large IP ranges, CIDRs, and custom target lists.
The scanner supports concurrent TCP connectivity checks, TLS handshakes with configurable SNI values, certificate name extraction, keyword matching, retry logic for transient failures, and a real-time terminal interface powered by Rich.
Designed for large-scale scanning workloads while minimizing false negatives caused by transient network conditions, packet loss, or upstream rate limiting.
- High-performance asynchronous scanning using
asyncio - Multi-port scanning with range support (e.g.
80,443,1025-2000) - TCP port probing with configurable concurrency
- TLS handshake support with custom SNI values
- Multiple SNI support per target
- SNI file loading for bulk SNI testing (IPs × Ports × SNIs combinations)
- Certificate SAN/Common Name extraction
- Keyword matching against certificate names
- CIDR, IP range, and file-based target loading
- Optional ICMP ping filtering before scanning
- Concurrent TCP → TLS pipeline mode for improved throughput
- Automatic retry logic for transient failures
- Live result writing (results saved in real-time as scan progresses)
- Separate IP and SNI output files (
--ips-out,--snis-out) - Rich live terminal interface with:
- Progress tracking
- Live event feed
- Success monitoring
- Throughput metrics
- ETA estimation
- Combination count display (IPs × Ports × SNIs)
- Graceful shutdown with partial result saving
- Atomic output file writing
- IPv4 and IPv6 support
- Logging support for debugging and troubleshooting
- Python 3.10+
- Linux/macOS recommended
pingbinary (optional, for--pingmode)
Install dependencies:
pip install richOptional (for certificate name extraction and keyword matching):
pip install cryptographyClone the repository:
git clone <your-repository-url>
cd <repository-name>Scan a single IP:
python scanner.py 1.2.3.4Scan a CIDR range:
python scanner.py 142.250.0.0/16Scan targets from file:
python scanner.py -f targets.txtProbe TLS using a custom SNI:
python scanner.py 1.2.3.4 --sni example.comTry multiple SNI values:
python scanner.py \
-f ips.txt \
--sni example.com \
--sni api.example.comPerform a no-SNI TLS probe:
python scanner.py 1.2.3.4 --sni ""Load SNI hostnames from a file. Every IP:Port combination is probed against every SNI:
python scanner.py \
-f hosts.txt \
--sni-file snis.txt \
-o results.txtThe SNI file supports one hostname per line with # comments:
# SNI hostnames to probe
example.com
api.example.com
cdn.example.com
Extract unique IPs and SNIs from successful TLS hits into separate files:
python scanner.py \
-f hosts.txt \
--sni-file snis.txt \
-o results.txt \
--ips-out matched_ips.txt \
--snis-out matched_snis.txt--ips-outwrites one unique IP per line (numerically sorted)--snis-outwrites one unique SNI per line (alphabetically sorted)
Match certificate names against keywords:
python scanner.py \
-f cidrs.txt \
--sni vercel.com \
--match vercel,now.shMatched results are highlighted in the interface and can optionally be saved exclusively:
python scanner.py \
-f cidrs.txt \
--sni vercel.com \
--match vercel \
--matched-onlyPing targets before scanning to reduce unnecessary connection attempts:
python scanner.py \
-f targets.txt \
--pingOnly ping-responsive hosts continue to TCP/TLS scanning.
Scan multiple ports and port ranges:
python scanner.py \
-f ips.txt \
-p 80,443,1025-2000Single port:
python scanner.py \
142.250.0.0/16 \
-p 443Run a TCP connectivity scan without TLS:
python scanner.py \
-f ips.txt \
--no-tls \
-p 80,443Skip standalone TCP probing and attempt TLS directly:
python scanner.py \
-f targets.txt \
--no-tcp \
--sni example.comIncrease worker count for larger scans:
python scanner.py \
142.250.0.0/16 \
--workers 800 \
--tls-workers 400Example with retries disabled for maximum speed:
python scanner.py \
-f targets.txt \
--retries 0Scan IPs from file with TLS SNI:
python scanner.py \
-f hosts.txt \
--sni example.com \
-o results.txtScan CIDRs and match certificate names:
python scanner.py \
-f cidrs.txt \
--ping \
--sni vercel.com \
--match vercel,now.shMulti-port scan with SNI file:
python scanner.py \
-f hosts.txt \
--sni-file snis.txt \
-p 80,443,8443 \
-o results.txt \
--ips-out matched_ips.txt \
--snis-out matched_snis.txtLarge TCP scan:
python scanner.py \
142.250.0.0/16 \
-p 443 \
--workers 800Disable TCP→TLS pipeline mode:
python scanner.py \
-f ips.txt \
--sni example.com \
--no-pipelineThe scanner supports multiple input formats.
1.2.3.4
10.0.0.0/24
1.1.1.1-1.1.1.50
Target files support:
- One entry per line
- CIDRs
- IP ranges
- Comments using
#
Example:
# Production ranges
1.2.3.4
10.0.0.0/24
192.168.1.1-192.168.1.50
Results are written atomically to the output file. Results are also written in real-time as the scan progresses.
Example:
# Generated 2026-05-28T00:00:00+00:00
# matched_keywords=vercel,now.sh
# rows=2
# columns: ip<TAB>port<TAB>sni<TAB>matched<TAB>cipher<TAB>cert_names
1.2.3.4 443 vercel.com 1 TLS_AES_256_GCM_SHA384 vercel.com
5.6.7.8 443 vercel.com 0 TLS_CHACHA20_POLY1305_SHA256 edge.example.net
Fields:
| Field | Description |
|---|---|
ip |
Target IP address |
port |
TCP port probed |
sni |
TLS Server Name Indication used |
matched |
Keyword match result (0 or 1) |
cipher |
Negotiated TLS cipher |
cert_names |
Certificate SAN/CN names |
| Option | Description |
|---|---|
-f, --file |
File containing targets |
-o, --output |
Output file |
-p, --ports |
Ports to scan (e.g. 80,443,1025-2000) |
--sni |
SNI hostname (repeatable) |
--sni-file |
File of SNI hostnames (IPs × Ports × SNIs combos) |
--match |
Comma-separated keyword matching |
--matched-only |
Save only matched results |
--ips-out |
Write unique successful IPs to file |
--snis-out |
Write unique successful SNIs to file |
--ping |
Enable ICMP ping filtering |
--no-tcp |
Skip TCP probe (alias: --no-port-scan) |
--no-tls |
Skip TLS probe (TCP-only scan) |
--no-pipeline |
Disable concurrent TCP→TLS pipeline |
--tcp-timeout |
TCP timeout (default: 3.0s) |
--tls-timeout |
TLS timeout (default: 5.0s) |
--ping-timeout |
Ping timeout (default: 2.0s) |
--retries |
Retry transient failures (default: 2) |
--retry-delay |
Base retry delay (default: 0.2s) |
--workers |
TCP/Ping concurrency (default: 500) |
--tls-workers |
TLS concurrency (default: 200) |
--log-file |
Log file path (default: scanner.log) |
-v |
Verbose logging |
The scanner distinguishes between deterministic and transient failures.
These fail immediately without retry:
ECONNREFUSEDEHOSTUNREACHENETUNREACHConnectionRefusedError
These are retried using exponential backoff with jitter:
- Timeouts
- Temporary socket failures
- Resource exhaustion (
EMFILE,ENOBUFS) - Temporary network instability
This significantly reduces false negatives during high-throughput scans.
The terminal interface provides real-time visibility into scan progress.
Displayed metrics include:
- Total targets
- Tested targets
- Successful probes
- Failed probes
- Errors
- Throughput (IPs/sec)
- Elapsed time
- Estimated completion time
- Combination count (IPs × Ports × SNIs)
- Pipeline statistics
- Success feed
- Live event stream
Logs are written to:
scanner.log
Enable verbose output:
python scanner.py -vDebug logging:
python scanner.py -vvFor large scans:
- Increase
--workersfor TCP-heavy workloads - Increase
--tls-workerswhen TLS handshakes are the bottleneck - Multi-port scans multiply combinations — adjust concurrency accordingly
- Raise file descriptor limits if needed:
ulimit -n 100000Recommended settings for large CIDR scans:
python scanner.py \
-f large.txt \
--workers 1000 \
--tls-workers 500Multi-port scan with high concurrency:
python scanner.py \
-f large.txt \
-p 80,443,8443 \
--workers 800 \
--tls-workers 400Actual performance depends on:
- Network quality
- OS socket limits
- Upstream rate limiting
- Target responsiveness
- TLS handshake latency
This tool is intended for authorized network testing, infrastructure validation, and research purposes only.
Ensure you have permission before scanning networks you do not own or manage.