enrichment

package
v0.26.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package enrichment provides post-scan host enrichment: banner grabbing, TLS certificate extraction, DNS resolution, and SNMP probing.

Package enrichment provides post-scan host enrichment: reverse DNS lookup, DNS record collection, and related operations.

Package enrichment — service fingerprint library. Maps (port, banner) → (application, version) using ordered regex rules.

Package enrichment provides post-scan host enrichment using SNMP.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DNSNameIsUsable added in v0.26.0

func DNSNameIsUsable(name string) bool

DNSNameIsUsable returns true when the PTR name is likely a stable, human-assigned hostname rather than a DHCP-generated or ISP-generated artifact.

Names are rejected when they:

  • Are a bare IP address literal
  • Contain an IP literal embedded with hyphens (e.g. 192-168-1-50)
  • Have a leftmost label starting with a DHCP-generated prefix (dhcp-, host-, ip-, client-)
  • Contain an ISP/DHCP infrastructure fragment (.dynamic., .dhcp., .broadband.)
  • Consist entirely of numeric labels (e.g. reversed-PTR arpa form "1.0.168.192")

Types

type BannerGrabber

type BannerGrabber struct {
	// contains filtered or unexported fields
}

BannerGrabber grabs TCP/TLS banners from open ports and stores the results.

func NewBannerGrabber

func NewBannerGrabber(repo *db.BannerRepository, logger *slog.Logger, extraFingerprintPath string) *BannerGrabber

NewBannerGrabber creates a new BannerGrabber. extraFingerprintPath is an optional path to a JSON file with custom fingerprint rules; pass an empty string to use only the built-in rules.

func (*BannerGrabber) EnrichHosts

func (g *BannerGrabber) EnrichHosts(ctx context.Context, targets []BannerTarget)

EnrichHosts grabs banners for all targets concurrently. Errors are logged rather than returned — enrichment is best-effort. For each host, at most maxExtendedProbesPerHost ports with an unidentified service are eligible for extended protocol probing.

type BannerTarget

type BannerTarget struct {
	HostID uuid.UUID
	IP     string
	Ports  []PortInfo
}

BannerTarget describes a host and its open TCP ports to probe.

type DNSEnricher

type DNSEnricher struct {
	// contains filtered or unexported fields
}

DNSEnricher enriches hosts with DNS records collected after discovery or scanning.

It performs:

  • A PTR (reverse) lookup for the host IP to discover its hostname.
  • If a hostname is found and the host has none set, it writes it back to hosts.hostname.
  • Forward A/AAAA lookups on the discovered hostname.
  • TXT and MX record collection on the discovered hostname.

All results are stored in host_dns_records (replacing any previous records).

func NewDNSEnricher

func NewDNSEnricher(
	resolver *internaldns.Resolver,
	dnsRepo *db.DNSRepository,
	hostRepo *db.HostRepository,
) *DNSEnricher

NewDNSEnricher creates a DNSEnricher.

func (*DNSEnricher) EnrichHost

func (e *DNSEnricher) EnrichHost(ctx context.Context, host *db.Host) error

EnrichHost performs DNS enrichment for a single host. ctx should carry a suitable deadline (the caller is responsible for timeout management).

func (*DNSEnricher) EnrichHosts

func (e *DNSEnricher) EnrichHosts(ctx context.Context, hosts []*db.Host)

EnrichHosts runs EnrichHost for each host in the slice. Errors from individual hosts are logged but do not abort the remaining enrichments.

func (*DNSEnricher) WithNetResolver

func (e *DNSEnricher) WithNetResolver(r netLookups) *DNSEnricher

WithNetResolver overrides the net.Resolver used for CNAME, MX, TXT, and SRV lookups. The primary use-case is unit tests.

type Fingerprint

type Fingerprint struct {
	// Port restricts this rule to a specific port (0 = any port).
	Port int `json:"port,omitempty"`
	// Protocol restricts this rule to "tcp" or "udp" (empty = any).
	Protocol string `json:"protocol,omitempty"`
	// Pattern is a regular expression matched against the raw banner text.
	// An empty pattern matches any banner (port-only rule).
	Pattern string `json:"pattern"`
	// Service is the application name returned on a match (e.g. "Redis").
	Service string `json:"service"`
	// VersionPattern is an optional regex whose first capture group extracts
	// the version string from the banner. Ignored when empty.
	VersionPattern string `json:"version_pattern,omitempty"`
}

Fingerprint describes a single service identification rule. Rules are matched in order; the first match wins.

type Fingerprinter

type Fingerprinter struct {
	// contains filtered or unexported fields
}

Fingerprinter matches banners against a loaded set of fingerprint rules.

func NewFingerprinter

func NewFingerprinter(extraPath string) *Fingerprinter

NewFingerprinter builds a Fingerprinter from the bundled rules plus an optional user-supplied JSON file (extraPath). If extraPath is empty or does not exist, only the built-in rules are loaded. User rules are prepended before built-ins so they take priority and can override any built-in match.

func (*Fingerprinter) Match

func (f *Fingerprinter) Match(port int, banner string) (service, version string)

Match returns the service name and version string for the given port and banner. Returns empty strings when no rule matches.

type MDNSEnricher added in v0.26.0

type MDNSEnricher struct {
	// contains filtered or unexported fields
}

MDNSEnricher queries a host directly (unicast) on its mDNS port using a DNS PTR query for the reversed-IP .in-addr.arpa name. Apple, Android, and Linux/avahi devices respond with a stable .local name.

This is not multicast mDNS browsing — it is a targeted unicast query sent directly to the host IP. No listener is required.

func NewMDNSEnricher added in v0.26.0

func NewMDNSEnricher(opts ...MDNSOption) *MDNSEnricher

NewMDNSEnricher creates an MDNSEnricher with the given options.

func (*MDNSEnricher) Enrich added in v0.26.0

func (e *MDNSEnricher) Enrich(ctx context.Context, ip string) (string, error)

Enrich sends a unicast DNS PTR query to <ip>:<port> and returns the resolved .local name, stripped of its trailing dot. Returns ("", nil) when the host does not respond, returns NXDOMAIN, or has no PTR record — a non-response is not treated as an error.

type MDNSOption added in v0.26.0

type MDNSOption func(*MDNSEnricher)

MDNSOption configures an MDNSEnricher.

func WithMDNSPort added in v0.26.0

func WithMDNSPort(p int) MDNSOption

WithMDNSPort overrides the destination port (default: 5353). Intended for testing only — production always uses port 5353.

func WithMDNSTimeout added in v0.26.0

func WithMDNSTimeout(d time.Duration) MDNSOption

WithMDNSTimeout overrides the per-query deadline (default: 2s).

type PortInfo

type PortInfo struct {
	Number             int
	Service            string // nmap-detected service name, e.g. "http", "ssh", ""
	AllowExtendedProbe bool   // set by EnrichHosts; true when within per-host extended-probe cap
}

PortInfo carries a port number and its nmap-detected service name.

type SNMPEnricher

type SNMPEnricher struct {
	// contains filtered or unexported fields
}

SNMPEnricher probes network devices via SNMP and persists results.

func NewSNMPEnricher

func NewSNMPEnricher(repo *db.SNMPRepository, logger *slog.Logger) *SNMPEnricher

NewSNMPEnricher creates a new SNMPEnricher.

func (*SNMPEnricher) EnrichHost

func (e *SNMPEnricher) EnrichHost(ctx context.Context, target SNMPTarget) error

EnrichHost probes a single host via SNMPv2c and stores the results. Returns nil if the host does not respond (non-fatal).

type SNMPTarget

type SNMPTarget struct {
	HostID    uuid.UUID
	IP        string
	Community string // overrides default "public" when non-empty
}

SNMPTarget groups the host details needed for SNMP enrichment.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL