Skip to content

pqdoctor

pqdoctor answers one question about a TLS server: is it post-quantum, and if not, why? It sends seven hand-built ClientHellos, reads only the server’s first reply to each, and turns the replies into a verdict, a stable cause code, and the fix for that server’s software.

Download pqdoctor 0.2.1

For Windows, macOS (Apple silicon and Intel) and Linux (x86_64 and arm64). Or, with Rust: cargo install pqdoctor (crates.io). Quickstart

pqdoctor nginx.org
✘ nginx.org:443 (3.147.99.198)
Not post-quantum: TLS 1.2 only
The server doesn't speak TLS 1.3, so it can't do hybrid ML-KEM.
cause: tls12-only server: nginx/1.31.3
Fixes
1. Turn on TLS 1.3
Hybrid post-quantum key exchange only exists in TLS 1.3. This server answered with TLS 1.2.
# nginx
ssl_protocols TLSv1.2 TLSv1.3;
# Apache
SSLProtocol -all +TLSv1.2 +TLSv1.3
2. nginx: link against OpenSSL 3.5+ and list the PQ group
nginx gets PQ from its TLS library. OpenSSL 3.5 or newer is needed (Ubuntu 25.04+, Debian 13+, or an nginx build linked against 3.5). Check with `nginx -V`.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;
Diagnosis, not just a yes/no 12 cause codes: old TLS library, hand-set curve list, TLS 1.2 only, Kyber draft only, a middlebox dropping large or split hellos, and more
Fixes for your stack Reads the Server header and prints the config for nginx, Apache, HAProxy, Caddy, Node, Go, IIS, Java, Postfix, Dovecot, Exim or Exchange, plus a Cloudflare Tunnel fallback
Handshake-only Never completes a key-exchange handshake, never sends application data
Post-quantum authentication Reads the certificate chain and checks whether the server serves an ML-DSA certificate
Every address Up to 6 addresses per name, reported per address when they disagree
Mail and SSH STARTTLS for SMTP, IMAP and POP3; SSH key exchange offers
Scans Thousands of hosts, politely: concurrency and rate caps, resume, exclusions, CDN skipping
Scriptable JSON and JSON Lines output, stable codes, meaningful exit status
Checked 59 / 59 against OpenSSL 3.5 on real sites, 30 / 30 in a fix lab of real faulty servers

The same Rust engine is inside Flarebox, the GitHub Action, and pqdoctor on Workers. All of them give the same verdict, cause and fix for the same server.