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

@ -27,7 +27,11 @@
// and SSHFP host-key fingerprint validation.
package checker
import "time"
import (
"net"
"strconv"
"time"
)
// ObservationKeySSH is the observation key this checker writes.
const ObservationKeySSH = "ssh"
@ -81,12 +85,9 @@ type SSHFPRecord struct {
// SSHProbe is the outcome of probing a single SSH endpoint.
type SSHProbe struct {
Host string `json:"host"`
Port uint16 `json:"port"`
Address string `json:"address"`
IP string `json:"ip,omitempty"`
IsIPv6 bool `json:"ipv6,omitempty"`
TCPConnected bool `json:"tcp_connected"`
Host string `json:"host"`
Port uint16 `json:"port"`
IP net.IP `json:"ip,omitempty"`
// Banner is the SSH protocol banner (e.g. "SSH-2.0-OpenSSH_9.3p1").
Banner string `json:"banner,omitempty"`
@ -125,15 +126,15 @@ type SSHProbe struct {
Stage string `json:"stage,omitempty"`
}
// HostKeyInfo captures an observed host key and its computed fingerprints.
// Addr returns the "ip:port" dial string for this endpoint.
func (p SSHProbe) Addr() string {
return net.JoinHostPort(p.IP.String(), strconv.Itoa(int(p.Port)))
}
// HostKeyInfo captures an observed host key in its SSH wire format.
type HostKeyInfo struct {
Type string `json:"type"` // e.g. "ssh-ed25519"
Bits int `json:"bits,omitempty"` // key size (bits)
SHA256 string `json:"sha256"` // hex fingerprint (lowercase, no colons)
SHA1 string `json:"sha1"` // hex fingerprint (lowercase, no colons)
SSHFPAlgo uint8 `json:"sshfp_algorithm"` // the SSHFP algorithm number matching this key type
SSHFPMatchSHA256 bool `json:"sshfp_match_sha256"`
SSHFPMatchSHA1 bool `json:"sshfp_match_sha1"`
Type string `json:"type"` // e.g. "ssh-ed25519"
RawKey []byte `json:"key"` // SSH wire format (ssh.PublicKey.Marshal())
}
// Issue is a single SSH finding surfaced to consumers.