checker: enforce prober-as-observation, move all analysis to rules layer

This commit is contained in:
nemunaire 2026-05-15 17:05:53 +08:00
commit f77895dcab
12 changed files with 174 additions and 171 deletions

View file

@ -89,19 +89,19 @@ type reportSSHFPRecord struct {
}
type reportEndpoint struct {
Address string
Host string
Port uint16
IsIPv6 bool
TCPConnected bool
Banner string
SoftwareVer string
Vendor string
ElapsedMS int64
Error string
StatusLabel string
StatusClass string
AnyFail bool
Address string
Host string
Port uint16
IsIPv6 bool
DialFailed bool
Banner string
SoftwareVer string
Vendor string
ElapsedMS int64
Error string
StatusLabel string
StatusClass string
AnyFail bool
HostKeys []reportHostKey
AlgoTables []reportAlgoTable
@ -239,11 +239,12 @@ func buildReportData(d *SSHData, states []sdk.CheckState) reportView {
matched := false
for _, ep := range d.Endpoints {
for _, k := range ep.HostKeys {
if k.SSHFPAlgo == rr.Algorithm {
if rr.Type == 2 && strings.EqualFold(rr.Fingerprint, k.SHA256) {
if sshfpAlgoForKeyType(k.Type) == rr.Algorithm {
sha1hex, sha256hex := hostKeyFingerprints(k)
if rr.Type == 2 && strings.EqualFold(rr.Fingerprint, sha256hex) {
matched = true
}
if rr.Type == 1 && strings.EqualFold(rr.Fingerprint, k.SHA1) {
if rr.Type == 1 && strings.EqualFold(rr.Fingerprint, sha1hex) {
matched = true
}
}
@ -264,24 +265,24 @@ func buildReportData(d *SSHData, states []sdk.CheckState) reportView {
for _, ep := range d.Endpoints {
re := reportEndpoint{
Address: ep.Address,
Host: ep.Host,
Port: ep.Port,
IsIPv6: ep.IsIPv6,
TCPConnected: ep.TCPConnected,
Banner: ep.Banner,
SoftwareVer: ep.SoftVer,
Vendor: ep.Vendor,
ElapsedMS: ep.ElapsedMS,
Error: ep.Error,
Address: ep.Addr(),
Host: ep.Host,
Port: ep.Port,
IsIPv6: ep.IP != nil && ep.IP.To4() == nil,
DialFailed: ep.Stage == "dial",
Banner: ep.Banner,
SoftwareVer: ep.SoftVer,
Vendor: ep.Vendor,
ElapsedMS: ep.ElapsedMS,
Error: ep.Error,
}
if ep.IsIPv6 {
if ep.IP != nil && ep.IP.To4() == nil {
v.AnyIPv6 = true
} else {
v.AnyIPv4 = true
}
perEpIssues := perEp[ep.Address]
perEpIssues := perEp[ep.Addr()]
// Per-endpoint status label.
epWorst := SeverityOK
for _, f := range perEpIssues {
@ -307,15 +308,18 @@ func buildReportData(d *SSHData, states []sdk.CheckState) reportView {
}
for _, k := range ep.HostKeys {
sha1hex, sha256hex := hostKeyFingerprints(k)
sha1Match, sha256Match := keyMatchesSSHFP(k, d.SSHFP)
algo := sshfpAlgoForKeyType(k.Type)
rh := reportHostKey{
Type: k.Type,
Bits: k.Bits,
SHA256: k.SHA256,
SHA1: k.SHA1,
Type: k.Type,
Bits: hostKeyBits(k),
SHA256: sha256hex,
SHA1: sha1hex,
SSHFPMatched: sha256Match || sha1Match,
SSHFPFamily: sshfpAlgoName(algo),
SSHFPSnippet: fmt.Sprintf("%d 2 %s", algo, sha256hex),
}
rh.SSHFPMatched = k.SSHFPMatchSHA256 || k.SSHFPMatchSHA1
rh.SSHFPFamily = sshfpAlgoName(k.SSHFPAlgo)
rh.SSHFPSnippet = fmt.Sprintf("%d 2 %s", k.SSHFPAlgo, k.SHA256)
re.HostKeys = append(re.HostKeys, rh)
}
@ -602,7 +606,7 @@ tr.info td:first-child { border-left: 3px solid #3b82f6; }
<dl class="kv">
<dt>Host</dt><dd>{{.Host}}</dd>
<dt>IP</dt><dd><code>{{.Address}}</code>{{if .IsIPv6}} (IPv6){{end}}</dd>
<dt>TCP</dt><dd>{{if .TCPConnected}}<span class="check-ok">&#10003; connected</span>{{else}}<span class="check-fail">&#10007; failed</span>{{end}}</dd>
<dt>TCP</dt><dd>{{if .DialFailed}}<span class="check-fail">&#10007; failed</span>{{else}}<span class="check-ok">&#10003; connected</span>{{end}}</dd>
{{if .SoftwareVer}}<dt>Version</dt><dd><code>{{.SoftwareVer}}</code>{{if .Vendor}} · <span class="note">{{.Vendor}}</span>{{end}}</dd>{{end}}
<dt>Duration</dt><dd>{{.ElapsedMS}} ms</dd>
{{if .Error}}<dt>Error</dt><dd><span class="check-fail">{{.Error}}</span></dd>{{end}}