77 lines
2.7 KiB
Markdown
77 lines
2.7 KiB
Markdown
# checker-tls
|
|
|
|
TLS posture checker for happyDomain.
|
|
|
|
Consumes `DiscoveredEndpoint` entries published by service checkers (xmpp,
|
|
srv, caldav, carddav, …) via `AutoFill: discovered_endpoints`, performs a
|
|
real TCP dial, optional STARTTLS upgrade, and TLS handshake on each, and
|
|
exports per-endpoint posture under the observation key `tls_probes`.
|
|
|
|
## Supported endpoint types
|
|
|
|
| `DiscoveredEndpoint.Type` | Handshake |
|
|
| --------------------------- | ---------------------------------------------- |
|
|
| `tls` | Direct TLS on connect |
|
|
| `starttls-smtp` | ESMTP EHLO + STARTTLS (RFC 3207) |
|
|
| `starttls-submission` | Same as `starttls-smtp` |
|
|
| `starttls-imap` | IMAP CAPABILITY + STARTTLS (RFC 3501) |
|
|
| `starttls-pop3` | POP3 CAPA + STLS (RFC 2595) |
|
|
| `starttls-xmpp-client` | XMPP c2s stream + `<starttls/>` (RFC 6120) |
|
|
| `starttls-xmpp-server` | XMPP s2s stream + `<starttls/>` (RFC 6120) |
|
|
| other `starttls-*` | Rejected with a `handshake_failed` issue |
|
|
|
|
## Payload shape
|
|
|
|
Observation data under `tls_probes`:
|
|
|
|
```json
|
|
{
|
|
"probes": {
|
|
"<endpointId>": {
|
|
"host": "example.net",
|
|
"port": 5222,
|
|
"endpoint": "example.net:5222",
|
|
"type": "starttls-xmpp-client",
|
|
"sni": "example.net",
|
|
"tls_version": "TLS1.3",
|
|
"cipher_suite": "TLS_AES_128_GCM_SHA256",
|
|
"hostname_match": true,
|
|
"chain_valid": true,
|
|
"not_after": "2026-07-01T00:00:00Z",
|
|
"issuer": "Let's Encrypt",
|
|
"issues": []
|
|
}
|
|
},
|
|
"collected_at": "2026-04-21T12:34:56Z"
|
|
}
|
|
```
|
|
|
|
Consumers pick their own endpoint from the map via
|
|
`RelatedObservation.EndpointID`.
|
|
|
|
## Issues reported
|
|
|
|
- `tcp_unreachable` — dial failed.
|
|
- `handshake_failed` — TLS handshake or STARTTLS upgrade failed.
|
|
- `starttls_not_offered` — server didn't advertise STARTTLS (severity depends
|
|
on `Meta["starttls"]` = `"required"` vs `"opportunistic"`).
|
|
- `chain_invalid` — leaf does not chain to a system-trusted root.
|
|
- `hostname_mismatch` — cert SANs don't cover the SNI.
|
|
- `expired` / `expiring_soon` — cert expiry posture.
|
|
- `weak_tls_version` — negotiated TLS < 1.2.
|
|
|
|
## Options
|
|
|
|
| Id | Type | Default | Description |
|
|
| ----------------- | ------ | ------- | ------------------------------------------------ |
|
|
| `probeTimeoutMs` | number | 10000 | Per-endpoint dial + handshake timeout in ms. |
|
|
|
|
## Running
|
|
|
|
```bash
|
|
# Plugin (loaded by happyDomain at startup)
|
|
make plugin
|
|
|
|
# Standalone HTTP server
|
|
make && ./checker-tls -listen :8080
|
|
```
|