detect

package
v1.163.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MPL-2.0 Imports: 10 Imported by: 0

Documentation

Overview

============================================================================= NFTBan v1.73 - Installer Conflict Detection (PR-P2-2: thin adapter over extfw) ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-conflicts" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="Conflicting firewall detection (services + ghost nft tables)" meta:inventory.files="internal/installer/detect/conflicts.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root" =============================================================================

PR-P2-2 unification note:

This file used to own its own detection surface (service probes +
ghost-nft-table parsing). As of PR-P2-2 it is a thin adapter over
internal/installer/extfw.Detect(), which is the single source of
truth for external-firewall detection across the install, update,
and uninstall lifecycle paths.

The Conflict struct and DetectConflicts()/ConflictNames() API are
preserved for backward compatibility with existing consumers
(phaseDetect, switchop.DisableConflicts, etc.). Internally, every
signal comes from extfw.Detect.

Option A resolution (2026-04-20): /etc/csf/csf.conf is a valid CSF signal. Install side now honors it — same as uninstall — so the two lifecycle surfaces cannot disagree about whether CSF is present.

=============================================================================

============================================================================= NFTBan v1.73 - Installer CT Limits Detection ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-ctlimits" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="DDoS connection tracking limit reads from config" meta:inventory.files="internal/installer/detect/ctlimits.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="/etc/nftban/conf.d/ddos/classic.conf" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================

============================================================================= NFTBan v1.161 - CVE-2025-NFTBAN-001 inet-filter guard (Go installer detect) ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-cve-inet-filter" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-06-08" meta:description="CVE-2025-NFTBAN-001 inet filter classify-then-act for the Go installer detect phase" meta:inventory.files="internal/installer/detect/cve_inet_filter.go" meta:inventory.binaries="" meta:inventory.env_vars="NFTBAN_ALLOW_REMOVE_INET_FILTER" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root" =============================================================================

CVE-2025-NFTBAN-001 — one-source consolidation (INST-CVE-PARITY / A-11)

The package scriptlets (DEB packaging/deb/postinst:38-104, RPM packaging/build_nftban.sh:1022-1065, both v1.146 Phase-D) already carry a classify-then-act guard on any pre-existing `inet filter` table. The source-install path (install.sh -> nftban-installer --source) had no equivalent in its detect phase, so a host installed from source got no inet-filter classification. This file closes that gap by mirroring the shell's exact logic and operator-facing wording inside the Go detect phase.

The DEB/RPM scriptlet guards are NOT replaced — they remain the proven, idempotent belt-and-suspenders for the package paths. This is the source- path twin, drift-checked against the shell behaviour:

NONE             — no `inet filter` table present -> no-op.
REMOVED          — an empty/skeleton accept-all `inet filter` table was
                   deleted (it would shadow nftban blocking).
REMOVED_OVERRIDE — a POPULATED operator-owned table was deleted ONLY
                   because NFTBAN_ALLOW_REMOVE_INET_FILTER=1 was set
                   (explicit, deterministic, logged opt-in).
POPULATED        — a populated operator-owned table is present and was
                   NOT removed. Warned (may shadow nftban). Non-fatal in
                   the detect phase, consistent with the other detect
                   steps; the operator-facing remediation runbook is the
                   same wording the scriptlets print.

The "is this a rule?" heuristic mirrors the shell grep filter (structural lines — table/chain/type/policy/closing-brace/comment — are not rules) and internal/installer/extfw/detect.go.

Idempotency: running this after the package scriptlet already removed the skeleton observes NONE and is a clean no-op. Running it twice is a no-op.

=============================================================================

============================================================================= NFTBan v1.73 - Installer Distro Detection ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-distro" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="OS distribution detection and nftables.conf path resolution" meta:inventory.files="internal/installer/detect/distro.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="/etc/os-release" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================

============================================================================= NFTBan v1.75.1 - Installer Panel Detection ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-panel" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="Control panel detection by directory existence" meta:inventory.files="internal/installer/detect/panel.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================

============================================================================= NFTBan v1.73 - Installer SSH Port Detection ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-detect-ssh" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="4-source SSH port detection chain for installer" meta:inventory.files="internal/installer/detect/ssh.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="/etc/ssh/sshd_config" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root" =============================================================================

Index

Constants

View Source
const (
	PathDirectAdmin = "/usr/local/directadmin"
	PathCPanel      = "/usr/local/cpanel"
	PathPlesk       = "/usr/local/psa"
	PathCyberPanel  = "/usr/local/CyberCP"
	PathHestia      = "/usr/local/hestia"
	PathVesta       = "/usr/local/vesta"
	PathCWP         = "/usr/local/cwpsrv"
	PathInterWorx   = "/usr/local/interworx"
)

Panel directory paths (exported for use by switchop and services packages).

Variables

This section is empty.

Functions

func ConflictNames

func ConflictNames(conflicts []Conflict) []string

ConflictNames returns a deduplicated list of conflict names, preserving the order they appeared in the input slice.

func DetectSSHPorts added in v1.125.0

func DetectSSHPorts(exec executor.Executor, log *logging.Logger) (ports []int, primary int, err error)

DetectSSHPorts is the v1.125 R-1 multi-port-aware entry point. It returns the full list of detected sshd listener ports (or a single-element slice when the host has only one listener), AND the primary port chosen by selectPrimarySSHPort (SSH_CLIENT-aware). Error is returned only when no source yields any valid port.

Source-chain semantics match SSHPort's existing priority: ss listener → sshd_config → state file → conf.local. Multi-port discovery is only available from the ss listener source (the other three sources are single-port by file format). When the primary comes from a non-listener source, the ports slice contains just that single primary.

Backward compatibility: SSHPort() and SSHPortWithSource() now delegate to DetectSSHPorts and return the primary, so all existing callers continue to receive a single int with unchanged semantics.

func DetectSSHPortsForRender added in v1.145.0

func DetectSSHPortsForRender(exec executor.Executor, log *logging.Logger) (ports []int, primary int, err error)

DetectSSHPortsForRender returns the FULL SSH-port union (primary-first) plus the SSH_CLIENT-aware primary, for the installer render path.

v1.145 PR-B2: the render must seed EVERY detected SSH port into tcp_ports_in AND ssh_ports, not just the `ss`-listener subset that DetectSSHPorts returns. On a multi-port host where `ss` detection is partial/ordered, DetectSSHPorts could return a subset (observed: 22+55000 but not 2222), leaving the missing port out of the kernel sets → externally DROPPED → lockout for an operator using it. DetectSSHPortsUnion is the authoritative multi-source detector (ss + sshd_config Port + ListenAddress + state + conf.local); this wraps it primary-first for RenderNftablesConfMultiPort. Falls back to DetectSSHPorts' primary when the union is empty.

func DetectSSHPortsUnion added in v1.145.0

func DetectSSHPortsUnion(exec executor.Executor, log *logging.Logger) []int

DetectSSHPortsUnion returns the sorted, de-duplicated union of every SSH port nftban can observe: live `ss` listeners + sshd_config/drop-in `Port` and `ListenAddress` directives + the install state file + conf.local `SSH_PORT`.

v1.145 PR-B runtime hardening: runtime/timer paths must protect EVERY real SSH listener port (lockout-safe), so they consume this conservative union rather than scalar `head -1` detection. The union is intentionally over-broad across address families — it is applied to BOTH ip and ip6 sets; per-family (ipv4_ports/ipv6_ports) precision is a deferred stronger variant. Blocking rule: missing a real listener port is a lockout blocker; over-broad is not.

func HasPanel

func HasPanel(panel PanelType) bool

HasPanel returns true if any panel was detected.

func SSHPort

func SSHPort(exec executor.Executor, log *logging.Logger) (int, error)

SSHPort detects the active SSH port using a 4-source priority chain. Returns the port number (1-65535) or an error if no source yields a valid port.

Priority:

  1. ss listener (most authoritative — reflects actual running sshd)
  2. sshd_config + drop-in dirs (config-declared)
  3. State file from previous install (/var/lib/nftban/state/ssh_port_active.state)
  4. nftban.conf.local override (/etc/nftban/nftban.conf.local SSH_PORT=)

Backward-compat shim around DetectSSHPorts (v1.125 R-1). Returns the primary port; callers that need the full multi-port list (e.g., to render the nftables allow-set) should call DetectSSHPorts directly.

func SSHPortWithSource added in v1.100.4

func SSHPortWithSource(exec executor.Executor, log *logging.Logger) (port int, source string, err error)

SSHPortWithSource returns the resolved SSH port AND a short string identifying which source yielded it: "ss" / "sshd_config" / "state" / "config" — matching the schema enum required by the PR-26-code-D restore evidence record (§39.1 / §48.6 lock).

Same priority chain as SSHPort. Read-only typed introspection; no mutation. Per §51.5-A2 invariant, this is OUTSIDE the bounded mutation surface cap. Added in PR-26-code-D.

Types

type CTLimits

type CTLimits struct {
	SSH  int // DDOS_CLASSIC_SSH_CONN_LIMIT, default 15
	HTTP int // DDOS_CLASSIC_HTTP_CONN_LIMIT, default 200
	Mail int // DDOS_CLASSIC_SMTP_CONN_LIMIT, default 30
}

CTLimits holds DDoS connection tracking limits used in nftables template rendering.

func DefaultCTLimits

func DefaultCTLimits() CTLimits

DefaultCTLimits returns the defaults matching the shell %post.

func ReadCTLimits

func ReadCTLimits(exec executor.Executor, log *logging.Logger) CTLimits

ReadCTLimits reads DDoS connection tracking limits from config files. Reads classic.conf first, then classic.conf.local as override. Returns defaults for any value not found.

type CVEInetFilterVerdict added in v1.161.0

type CVEInetFilterVerdict string

CVEInetFilterVerdict is the classification of the pre-existing `inet filter` table, mirroring the single-token verdict the shell _nftban_classify_inet_filter function echoes.

const (
	// CVEInetFilterNone — no `inet filter` table present (or nft absent).
	CVEInetFilterNone CVEInetFilterVerdict = "NONE"
	// CVEInetFilterRemoved — empty/skeleton table removed (would shadow nftban).
	CVEInetFilterRemoved CVEInetFilterVerdict = "REMOVED"
	// CVEInetFilterRemovedOverride — populated table removed via explicit opt-in.
	CVEInetFilterRemovedOverride CVEInetFilterVerdict = "REMOVED_OVERRIDE"
	// CVEInetFilterPopulated — populated operator-owned table left in place.
	CVEInetFilterPopulated CVEInetFilterVerdict = "POPULATED"
)

func CheckCVEInetFilter added in v1.161.0

func CheckCVEInetFilter(exec executor.Executor, log *logging.Logger) CVEInetFilterVerdict

CheckCVEInetFilter classifies any pre-existing `inet filter` table and acts per the CVE-2025-NFTBAN-001 guard, mirroring the DEB/RPM scriptlets. It is read-only EXCEPT for the documented CVE skeleton removal (and the explicit override removal) — it does not otherwise change firewall behaviour.

Non-fatal by contract: it returns a verdict and never aborts the install itself. The detect phase logs the verdict and continues, consistent with the other detect steps. The empty-skeleton removal is the safe automatic action; the populated case is warned, not auto-deleted.

Idempotent: after the package scriptlet (or a prior call) has removed the skeleton, the table no longer exists -> NONE -> no-op.

type Conflict

type Conflict struct {
	Name    string // e.g., "CSF", "UFW", "firewalld", "iptables", "iptables-nft"
	Service string // systemd unit name; empty for non-service observations
	Active  bool   // always true — if it was observed, it's active
}

Conflict represents a detected conflicting firewall. One observation (service / ghost table / config file) maps to one Conflict. A single firewall may produce multiple Conflicts — CSF with both csf.service and lfd.service active emits two Conflict entries so the takeover path can stop+disable+mask each unit independently.

func DetectConflicts

func DetectConflicts(exec executor.Executor, log *logging.Logger) []Conflict

DetectConflicts returns the conflict list for the current host. Read-only; delegates to extfw.Detect for the underlying signals.

PR-P2-2A: only observations whose Name is in the canonical Active list become Conflicts. Observations from informational-only signals (e.g. iptables ghost-table alone, which does NOT corroborate to a real iptables presence under the Path B rule) are recorded in res.Observations for transparency but excluded from the Conflict list because they do not classify external authority.

type DistroInfo

type DistroInfo struct {
	ID          string // normalized: "rocky", "almalinux", "centos", "rhel", "debian", "ubuntu", "fedora"
	VersionID   string // e.g., "9", "10", "24.04"
	PrettyName  string // e.g., "AlmaLinux 9.7 (Moss Jungle Cat)"
	NftConfPath string // system nftables.conf path for this distro
}

DistroInfo holds detected OS distribution information.

func DetectDistro

func DetectDistro(exec executor.Executor, log *logging.Logger) (*DistroInfo, error)

DetectDistro parses /etc/os-release and determines the nftables.conf path.

type PanelType

type PanelType string

PanelType identifies a hosting control panel.

const (
	PanelNone        PanelType = ""
	PanelDirectAdmin PanelType = "directadmin"
	PanelCPanel      PanelType = "cpanel"
	PanelPlesk       PanelType = "plesk"
	PanelCyberPanel  PanelType = "cyberpanel"
	PanelHestia      PanelType = "hestia"
	PanelVesta       PanelType = "vesta"
	PanelCWP         PanelType = "cwp"
	PanelInterWorx   PanelType = "interworx"
)

func DetectPanel

func DetectPanel(exec executor.Executor, log *logging.Logger) PanelType

DetectPanel checks for installed control panels by directory existence. Returns PanelNone if no panel is detected.

Jump to

Keyboard shortcuts

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