Add tlsenum package and add version/cipher enumeration into the checker
tlsenum package probes a remote endpoint with one ClientHello per (version, cipher) pair via utls, so the checker can report the exact set the server accepts rather than only the suite Go's stdlib happens to negotiate. Probe accepts an Upgrader callback so STARTTLS dialects plug in without tlsenum learning about them; the checker bridges its existing dialect registry through upgraderFor.
This commit is contained in:
parent
8a7f9feaf7
commit
a9f37c79cf
18 changed files with 1569 additions and 5 deletions
|
|
@ -9,8 +9,9 @@ const ObservationKeyTLSProbes = "tls_probes"
|
|||
|
||||
// Option ids on CheckerOptions.
|
||||
const (
|
||||
OptionEndpoints = "endpoints"
|
||||
OptionProbeTimeoutMs = "probeTimeoutMs"
|
||||
OptionEndpoints = "endpoints"
|
||||
OptionProbeTimeoutMs = "probeTimeoutMs"
|
||||
OptionEnumerateCiphers = "enumerateCiphers"
|
||||
)
|
||||
|
||||
// Defaults shared between the definition's Default field and the runtime
|
||||
|
|
@ -100,6 +101,12 @@ type TLSProbe struct {
|
|||
Chain []CertInfo `json:"chain,omitempty"`
|
||||
ElapsedMS int64 `json:"elapsed_ms,omitempty"`
|
||||
|
||||
// Enum carries the protocol-version and cipher-suite sweep. It is only
|
||||
// populated when the user enables OptionEnumerateCiphers. Direct TLS and
|
||||
// supported STARTTLS dialects are both swept; a STARTTLS endpoint with
|
||||
// an unknown dialect is skipped with a reason recorded in Enum.Skipped.
|
||||
Enum *TLSEnumeration `json:"enum,omitempty"`
|
||||
|
||||
// Error is a compatibility summary of whichever raw error applies.
|
||||
// Left for any external consumer still inspecting it; rules should
|
||||
// look at TCPError / HandshakeError instead.
|
||||
|
|
@ -142,3 +149,31 @@ type CertInfo struct {
|
|||
const (
|
||||
ExpiringSoonThreshold = 14 * 24 * time.Hour
|
||||
)
|
||||
|
||||
// TLSEnumeration is the result of sweeping a (version × cipher) matrix
|
||||
// against an endpoint. The exact set the server accepts (rather than just the
|
||||
// one combination it negotiated under default Go preferences) lets rules flag
|
||||
// legacy versions and weak cipher suites that would otherwise stay invisible.
|
||||
type TLSEnumeration struct {
|
||||
// Versions lists every protocol version for which at least one cipher
|
||||
// was accepted, with the matching cipher suites.
|
||||
Versions []EnumVersion `json:"versions,omitempty"`
|
||||
// Skipped is set when enumeration was not attempted (e.g. STARTTLS
|
||||
// endpoint, prior handshake failure). Empty when enumeration ran.
|
||||
Skipped string `json:"skipped,omitempty"`
|
||||
// DurationMS is the wall-clock time spent enumerating, for ops visibility.
|
||||
DurationMS int64 `json:"duration_ms,omitempty"`
|
||||
}
|
||||
|
||||
// EnumVersion is one accepted protocol version plus the ciphers it accepted.
|
||||
type EnumVersion struct {
|
||||
Version uint16 `json:"version"`
|
||||
Name string `json:"name"`
|
||||
Ciphers []EnumCipher `json:"ciphers,omitempty"`
|
||||
}
|
||||
|
||||
// EnumCipher is one accepted cipher suite.
|
||||
type EnumCipher struct {
|
||||
ID uint16 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue