tls_checker is a command-line tool for running concurrent TLS checks against a list of hosts. It resolves DNS, completes the TLS handshake, reports the negotiated version, checks ALPN, probes HTTP/2 when it makes sense, and can also attach ASN information to the result.

Origin

Sometimes I do not want a full scanner. I just want a fast answer to a narrower question: what does this set of endpoints actually negotiate right now?

That usually starts small. Maybe I want to see which hosts are still on TLS 1.2, which ones advertise h2, or whether a certificate mismatch is isolated to one edge and not another. The annoying part is that the quick path tends to turn into a pile of one-off commands: openssl s_client, curl -I --http2, maybe a DNS lookup, maybe a WHOIS lookup, and then repeating that for a whole list of domains.

tls_checker came out of that. I wanted one pass over an input file, with output that was easy to scan and boring in a good way.

It is useful when you need to:

  • Check a batch of hostnames after a TLS change
  • See which endpoints negotiate TLS 1.3 versus older versions
  • Confirm whether h2 is advertised and actually usable
  • Catch certificate or reachability problems without opening a browser
  • Add ASN context when the endpoint ownership matters

The tool reads hosts or URLs from a file, normalizes them into host and port pairs, and checks them concurrently. Each result includes the resolved IP, round-trip time, certificate CN and SANs, negotiated TLS version, ALPN result, HTTP/2 probe result, and optional ASN data.

The output is grouped into four buckets:

  • Full: TLS 1.3, h2 negotiated, and the HTTP/2 probe succeeds
  • Success: TLS 1.3, even if ALPN or HTTP/2 is not there
  • Partial: TLS works, but the endpoint negotiates something older than TLS 1.3
  • Failure: DNS, timeout, TLS handshake, certificate, or connection problems

That classification is opinionated on purpose. I wanted something stricter than “the socket accepted TLS” but simpler than a full grading system.

Here is the kind of output it produces in practice:

📋 Found 4 unique host:port targets to check.
🔒 TLS Checker → 4 targets, 12 workers, timeout=5s, retries=2, ASN:true, default port:443
---------------------- RESULTS ----------------------
🔵 cloudflare.com:443 (104.16.132.229) - RTT:41ms | CN:cloudflare.com | SANs:[cloudflare.com, sni.cloudflaressl.com] | ASN:13335 (CLOUDFLARENET) | TLS:TLS1.3 | ALPN:h2 | H2:ok | Cert:ok
🟢 example.com:443 (93.184.216.34) - RTT:58ms | CN:*.example.com | SANs:[*.example.com, example.com] | ASN:15133 (EDGECAST) | TLS:TLS1.3 | ALPN:http/1.1 | H2:n/a | Cert:ok
🟡 legacy.example.net:443 (198.51.100.20) - RTT:77ms | CN:legacy.example.net | SANs:[legacy.example.net] | ASN:64500 (LEGACY-NET) | TLS:TLS1.2 | ALPN:http/1.1 | H2:n/a | Cert:ok
❌ broken.example.org:443 - FAILED (TLS_HANDSHAKE_FAILED)

-------------------- SUMMARY --------------------
Hosts Checked: 4/4
🔵 Full: 1 | 🟢 Success: 1 | 🟡 Partial: 1 | ❌ Failure: 1
-------------------------------------------------

Installing It

On macOS or Linux, the shortest path is:

curl -fsSL https://raw.githubusercontent.com/sinnet3000/tls_checker/main/scripts/install.sh | bash

That installs the latest release into /usr/local/bin when writable, or ~/.local/bin otherwise.

If you want to build it yourself, you need Go 1.26.1 or newer:

git clone https://github.com/sinnet3000/tls_checker.git
cd tls_checker
make install

If ~/.local/bin is not already on your PATH, add it before trying to run the binary.

The tool expects an input file with one host or URL per line. Then you can run something like:

tls_checker -i example_urls.txt -t 16 --timeout 5s --retries 2

And if you do not care about ASN lookups for that run:

tls_checker -i example_urls.txt --no-asn

Source code: https://github.com/sinnet3000/tls_checker