{
  "id": "CB-UBU-NET-005",
  "standard": "ubuntu",
  "version": "main",
  "url": "https://baselines.cirsec.org/b/ubuntu/CB-UBU-NET-005",
  "json": "https://baselines.cirsec.org/b/ubuntu/CB-UBU-NET-005.json",
  "yaml": "https://baselines.cirsec.org/b/ubuntu/CB-UBU-NET-005.yml",
  "profiles_effective": [
    "core",
    "server",
    "server-hardened",
    "desktop",
    "desktop-hardened"
  ],
  "license": "Text CC BY 4.0, code Apache-2.0",
  "attribution": "CIRSEC Baselines, https://baselines.cirsec.org",
  "control": {
    "id": "CB-UBU-NET-005",
    "title": "Run exactly one host firewall",
    "finding": {
      "title": "No host firewall is active, or several firewall tools compete for the same rules",
      "description": "Without a host firewall every listening service is reachable from the network; with several, rules overwrite each other in ways nobody planned."
    },
    "status": "active",
    "profiles": [
      "core"
    ],
    "risk": {
      "severity": "high"
    },
    "assessment": "automated",
    "tags": [
      "firewall",
      "ufw",
      "nftables",
      "network"
    ],
    "description": "The Linux kernel filters packets with netfilter. On Ubuntu, its rules are managed by one of\nthese tools, each started at boot by its own service:\n\n- `ufw`, a simple front end, active when `ufw status` shows `Status: active`;\n- `nftables`, rules loaded from `/etc/nftables.conf` by `nftables.service`;\n- `firewalld`;\n- `iptables-persistent`, rules restored by `netfilter-persistent.service`.\n\nThis control requires exactly one of them to be enabled. Its default policy is covered by\nCB-UBU-NET-006.\n",
    "rationale": "A host firewall limits the services reachable from the network to the ones that are meant to\nbe, even when a package starts a new listener or a service binds to all addresses by mistake.\nTwo firewall tools flush or reorder each other's rules on reload, which leaves the host either\nwide open or cut off after a restart.\n",
    "impact": "The automatic fix installs and enables ufw when no firewall is active. It allows the SSH ports\nfirst, but ufw then drops every other incoming connection: services such as web or database\nservers become unreachable until they are allowed with `ufw allow <port>/<protocol>`. It is\ndisabled by default; list the listening services with `ss -tulpn` and allow them before\nenabling it.\n",
    "notes": "ufw is installed by default on every Ubuntu release but left inactive (`ENABLED=no` in\n`/etc/ufw/ufw.conf`); `ufw.service` is enabled anyway, which is why the check reads `ufw status`\nrather than the unit state. Ubuntu documents ufw and the CIS Benchmarks favour it; nftables,\nfirewalld and iptables-persistent are accepted too. On 22.04 and later, iptables is the\n`iptables-nft` variant, so ufw rules also show in `nft list ruleset`: that does not count as a\nsecond firewall as long as `nftables.service` is not enabled. 20.04 uses the legacy iptables\nback end. Docker and libvirt add their own rules beside the host firewall; they are not counted.\nThe fix reads the SSH ports from `sshd -T`; on 24.04 and later, where sshd is started by\n`ssh.socket`, it first creates `/run/sshd` if no connection has started the service yet, and\nstops without enabling ufw if it cannot find any port.\n",
    "audit": {
      "manual": "1. `ufw status` (if installed): `Status: active` counts as one.\n2. `systemctl is-enabled nftables.service firewalld.service netfilter-persistent.service`:\n   each `enabled` counts as one.\nExactly one must be counted.\n",
      "checks": [
        {
          "id": "single-firewall",
          "engine": "shell",
          "description": "Firewall tools enabled at boot.",
          "spec": {
            "script": "active=\nif command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q '^Status: active'; then\n  active=\"$active ufw\"\nfi\nfor u in nftables firewalld netfilter-persistent; do\n  [ \"$(systemctl is-enabled \"$u.service\" 2>/dev/null)\" = enabled ] && active=\"$active $u\"\ndone\necho \"active firewall tools:${active:- none}\"\nset -- $active\n[ \"$#\" -eq 1 ]\n"
          }
        }
      ]
    },
    "remediation": {
      "manual": "- No firewall: ufw is installed by default (otherwise `apt install ufw`). Allow SSH and the\n  other services that must stay reachable, then enable it:\n  ```\n  ufw allow 22/tcp\n  ufw enable\n  ```\n  Or write `/etc/nftables.conf` (see CB-UBU-NET-006) and run `systemctl enable --now nftables`.\n- Several tools: keep one, then disable the others, for example `ufw disable`,\n  `systemctl disable --now nftables` or `apt purge iptables-persistent`.\n",
      "effects": {
        "restart": "none",
        "disruption": "high",
        "lockout_risk": true
      },
      "rollback": "Run `ufw disable`. Installed packages can stay.\n",
      "scripts": [
        {
          "id": "enable-ufw",
          "engine": "shell",
          "file": "fix.sh"
        }
      ]
    },
    "references": [
      {
        "title": "ufw(8), Ubuntu manual pages",
        "url": "https://manpages.ubuntu.com/manpages/noble/man8/ufw.8.html",
        "publisher": "Canonical",
        "kind": "vendor-doc",
        "accessed": "2026-10-19"
      },
      {
        "title": "Ubuntu Server documentation - Firewalls",
        "url": "https://documentation.ubuntu.com/server/how-to/security/firewalls/",
        "publisher": "Canonical",
        "kind": "vendor-doc",
        "accessed": "2026-10-19"
      },
      {
        "title": "Ubuntu Security documentation - Firewall",
        "url": "https://documentation.ubuntu.com/security/security-features/network/firewall/",
        "publisher": "Canonical",
        "kind": "vendor-doc",
        "accessed": "2026-10-19"
      },
      {
        "title": "NIST SP 800-41 Rev. 1 - Guidelines on Firewalls and Firewall Policy",
        "url": "https://csrc.nist.gov/pubs/sp/800/41/r1/final",
        "publisher": "NIST",
        "kind": "guide",
        "accessed": "2026-10-19"
      }
    ],
    "mappings": [
      {
        "framework": "nist-800-53r5",
        "framework_version": "5.1.1",
        "id": "SC-7",
        "relation": "partial"
      }
    ],
    "threats": [
      {
        "framework": "mitre-attack",
        "id": "T1046"
      },
      {
        "framework": "mitre-attack",
        "id": "T1190"
      },
      {
        "framework": "cwe",
        "id": "CWE-284"
      }
    ],
    "related_controls": [
      {
        "id": "CB-UBU-NET-006",
        "type": "related"
      }
    ],
    "authors": [
      {
        "name": "Alice",
        "github": "Sn0wAlice"
      }
    ],
    "verified": [
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "20.04"
        ],
        "environment": "Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic, BIOS boot",
        "notes": "ufw installed but inactive on a fresh install, reported; fix allows port 22 and enables ufw; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot, other ports dropped. nftables alone passes; iptables-persistent next to ufw reported as a second firewall."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "22.04"
        ],
        "environment": "Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic, BIOS boot",
        "notes": "ufw installed but inactive on a fresh install, reported; fix allows port 22 and enables ufw; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot, other ports dropped; second remediate leaves it alone."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "24.04"
        ],
        "environment": "Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic, BIOS boot",
        "notes": "ufw inactive on a fresh install, reported; fix run before any SSH connection (no /run/sshd) still reads port 22 and enables ufw; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot, other ports dropped."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "26.04"
        ],
        "environment": "Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic, BIOS boot",
        "notes": "ufw inactive on a fresh install, reported; fix allows port 22 and enables ufw; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot. ufw plus nftables.service reported and the fix refuses; after iptables-persistent removed ufw, the fix reinstalled it with apt."
      }
    ],
    "introduced_in": "0.1.0",
    "created": "2026-10-19",
    "updated": "2026-10-19"
  }
}