Sometimes I don’t need a full compliance report — I just need to know, right now, exactly which ciphers a server accepts and whether it’s still vulnerable to something like Heartbleed. That’s the itch sslscan scratches. It’s a compact, fast, C-based tool that queries a server directly and lists supported SSL/TLS versions, cipher suites, and certificate details in one quick pass. I use it constantly as a companion (or sanity check) to sslyze.
This article covers what sslscan is, how it works internally, installation, syntax, real command examples, and how it fits into a broader testing workflow.
What SSLScan Does
sslscan connects to an SSL/TLS-enabled service and reports:
- Supported SSL/TLS protocol versions (SSLv2/3, TLS 1.0–1.3)
- Every cipher suite accepted per protocol, along with key strength
- Certificate details (subject, issuer, expiration, signature algorithm)
- Compression and renegotiation support (relevant to CRIME and secure renegotiation issues)
- Basic Heartbleed detection
Architecture and Internal Working
sslscan is written in C and links directly against a (often bundled, statically compiled) OpenSSL library — frequently a patched version that still supports legacy protocols disabled in modern system OpenSSL builds, which is precisely why it can detect servers still accepting SSLv2 or SSLv3 even when your system’s own OpenSSL refuses to negotiate them.
Its internal loop is straightforward:
- For each protocol version compiled in,
sslscaniterates through its full cipher list. - For each cipher, it attempts a handshake specifying only that cipher.
- If the handshake succeeds, the cipher is marked accepted; if it fails, it’s marked rejected.
- Once all ciphers/protocols are tested, it performs a final handshake to pull the certificate chain and print certificate details.
This brute-force-style, cipher-by-cipher approach is simpler than SSLyze’s plugin architecture but very fast for a single-host check.
Installation
Debian/Kali:
sudo apt update
sudo apt install sslscan -y
From source:
git clone --recursive https://github.com/rbsec/sslscan.git
cd sslscan
make static
sudo make install
Verify:
sslscan --version
Basic Syntax
sslscan [options] host[:port]
Command Examples
1. Basic scan
sslscan example.com
Sample output:
Testing SSL server example.com on port 443
TLS Fallback SCSV:
Server supports TLS Fallback SCSV
TLS renegotiation:
Secure session renegotiation supported
TLS Compression:
Compression disabled
Heartbleed:
TLS 1.2 not vulnerable to heartbleed
TLS 1.3 not vulnerable to heartbleed
Supported Server Cipher(s):
Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256
Server Key Exchange Group(s):
TLSv1.3 128 bits secp256r1
SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength: 2048
Subject: example.com
Not valid before: Jan 1 00:00:00 2026 GMT
Not valid after: Dec 31 23:59:59 2026 GMT
2. Scanning a non-standard port
sslscan example.com:8443
3. Testing STARTTLS services (SMTP)
sslscan --starttls-smtp mail.example.com:25
4. Show only certificate information
sslscan --show-certificate example.com
5. Only test specific protocol versions
sslscan --no-ssl2 --no-ssl3 --tlsv1_2 example.com
6. XML output for automation
sslscan --xml=results.xml example.com
Configuration Options
| Flag | Purpose |
|---|---|
--no-ciphersuites | Skip full cipher enumeration for a faster protocol-only check |
--no-check-certificate | Skip certificate validation (useful for self-signed certs in a lab) |
--ipv4 / --ipv6 | Force IP version |
--timeout=<n> | Adjust connection timeout |
--connect-timeout=<n> | Adjust the initial TCP connect timeout |
Real-World Use Cases
Quick sanity check mid-engagement: When I’ve already run a full SSLyze scan but want to confirm one specific finding (like whether a legacy cipher is really accepted), a targeted sslscan run is faster than re-running a full report.
Mail server security review: Using --starttls-smtp, --starttls-imap, or --starttls-pop3 to check whether internal mail servers still allow weak ciphers over STARTTLS connections.
Compliance spot-checks: Confirming a single remediated host no longer accepts SSLv3 or export-grade ciphers after a patch, without needing a full audit report.
Forensic review post-incident: After identifying a downgrade attack in packet captures, running sslscan against the affected server to confirm what cipher suites were actually available for an attacker to exploit at the time.
Workflow and Tool Integration
# Quick fleet-wide protocol/cipher spot check
for host in $(cat hosts.txt); do
echo "== $host ==" >> sslscan_fleet.txt
sslscan --no-ciphersuites "$host" >> sslscan_fleet.txt
done
# Follow up with a deep dive on any host showing weak protocol support
sslscan --show-certificate weakhost.example.com
I typically run sslscan and sslyze back to back on the same host early in an engagement — if their cipher lists disagree, that’s usually worth a closer manual look with openssl s_client.
Performance Optimization
- Use
--no-ciphersuiteswhen you only care about protocol version support, cutting scan time significantly. - Lower
--connect-timeouton local/lab networks to speed up scans against many hosts. - Batch hosts through a shell loop with output redirected to a single file rather than running interactively one at a time.
Troubleshooting
- “connect() failed” — verify the port is open and not filtered; try
nc -zv host portfirst. - Certificate validation errors on internal/self-signed hosts — add
--no-check-certificateto bypass validation for lab or internal CA-signed certs. - Handshake failures on legacy protocol tests — some modern OpenSSL system libraries block SSLv2/SSLv3 negotiation entirely; use a statically compiled
sslscanbuild (make static) which bundles a patched OpenSSL supporting legacy protocol testing.
Best Practices and Common Mistakes
- Don’t assume a clean
sslscanresult means the whole TLS stack is secure — always check certificate chain trust and hostname matching separately. - Explicitly test STARTTLS-capable services; a plain scan against port 25 or 143 without the STARTTLS flag will just fail to negotiate.
- Keep the static build up to date — legacy cipher/protocol testing depends on the bundled OpenSSL version being current with known CVE checks.
FAQ
How is sslscan different from sslyze? sslscan is a lightweight, single-binary, cipher-by-cipher brute-force tester written in C; sslyze is a Python-based platform with a plugin architecture, JSON output, and deeper compliance baseline comparisons (like Mozilla configuration levels).
Can sslscan detect Heartbleed? Yes, it includes a basic Heartbleed check as part of its default scan output.
Does sslscan need root privileges? No, it operates as a normal TCP/TLS client and doesn’t need elevated privileges.
Lab Example
Deploy an Apache server in a lab VM with mod_ssl configured to allow both modern and legacy ciphers, then run:
sslscan --show-certificate 192.168.56.30
Identify which legacy ciphers are accepted, update the Apache SSLCipherSuite directive to remove them, restart Apache, and re-run the scan to confirm the fix.
Summary
sslscan is the fast, no-nonsense counterpart to more comprehensive tools like sslyze — perfect for quick cipher and protocol checks, STARTTLS testing, and Heartbleed spot-checks. I keep it in my toolkit specifically for those moments when I need a fast, authoritative answer about a single host’s TLS configuration without spinning up a full audit.
References
- Official GitHub repository: https://github.com/rbsec/sslscan
- Man page:
man sslscan