UFW firewall audit tool — cross-checks rules against listening services
Project description
Lire en français · Technical documentation
🔒 ufw-audit
Smart UFW security audit — fast, readable, actionable.
Analyses your UFW configuration, exposed services and logs to detect real risks, with clear recommendations.
⚡ TL;DR
sudo apt install pipx && pipx ensurepath
# open a new terminal, then:
pipx install ufw-audit
sudo ~/.local/bin/ufw-audit --install-completion
sudo ufw-audit
🛠 Installation
Prerequisites
- Linux: Debian, Ubuntu, Mint or derivative
- UFW:
sudo apt install ufw - pipx:
sudo apt install pipx && pipx ensurepath
Open a new terminal after
pipx ensurepathto activate the PATH.
Install
pipx install ufw-audit
Enable sudo + bash completion
pipx installs the binary in ~/.local/bin/, which is not in sudo's restricted PATH.
--install-completion creates the symlink /usr/local/bin/ufw-audit and installs the bash completion script:
sudo ~/.local/bin/ufw-audit --install-completion
source /etc/bash_completion.d/ufw-audit
After this step, sudo ufw-audit works normally.
Update
pipx upgrade ufw-audit
Uninstall
pipx uninstall ufw-audit
🚀 Why ufw-audit?
- 🔍 Full audit — firewall, services, ports, logs, DDNS, Docker, virtualisation
- 🎯 Smart prioritisation — score + classification (OK / Warning / Action required)
- 🧠 Context-aware — network exposure + service criticality
- 🛠 Optional auto-fix — corrections proposed or applied automatically
- 📊 Clear output — human-readable + scriptable
- 🌍 Bilingual EN/FR
🔎 What the tool analyses
🔥 Firewall (UFW)
- Active/inactive status
- Dangerous rules (
allow from any) - IPv4 / IPv6 consistency
- Duplicates and errors
🌐 Exposed services (22+)
- SSH, Redis, PostgreSQL, Docker, etc.
- Detection via systemd / active ports
- Real exposure, risk level, UFW consistency
📡 Ports
- Open ports (
ss) - Interfaces (loopback / LAN / public)
- Unintended exposures
📜 UFW logs
- Suspicious attempts, brute-force detection
- IP analysis (optional GeoIP)
☁️ DDNS / Docker / Virtualisation
- Advanced network correlations
- Indirect exposure detection
📊 Example output
✔ Firewall active
⚠ SSH exposed to the Internet
✖ Redis open without restriction
Score: 6/10
→ Action required
▶️ Usage
sudo ufw-audit # standard audit
sudo ufw-audit -f # interactive fix mode
sudo ufw-audit -f -y # auto-fix without confirmation
sudo ufw-audit -v # verbose
sudo ufw-audit -q # silent — exit code 0/1/2/3
sudo ufw-audit --french # French interface
🔌 Custom services (plugin system)
Drop a .json file into ~/.config/ufw-audit/services.d/ to add services that are not in the built-in registry.
mkdir -p ~/.config/ufw-audit/services.d/
# create my-services.json — same format as ufw_audit/data/services.json
Note (pipx / sudo): ufw-audit requires
sudo. Undersudo,~resolves to/root.
Place your plugin files in/root/.config/ufw-audit/services.d/for them to be active at runtime.This will change in a future
.debrelease, where the system-wide directory/etc/ufw-audit/services.d/will be used instead.
🤖 Automation
- 🕒 Built-in cron (
--install-cron) - 📧 Email notifications (HTML + plain text)
- 📁 Report management (
--manage-logs) - 🔁 Multi-job scheduling (
--manage-cron)
Email notifications require a working Postfix setup. See AUTOMATION.md for step-by-step configuration instructions.
🧪 Quality & reliability
- ✅ 2507 unit tests
- 🧱 Modular architecture (snapshot / check separated)
- 🧪 Tested on Debian, Ubuntu, Kali, Mint
🆕 v1.17.0
- 🔍 CHECK 31 — Linux Audit Framework (auditd) — detects installation, service status, loaded rules, and coverage of sensitive files (/etc/passwd, /etc/shadow, /etc/sudoers); WARN −1 pt each for inactive service, no rules, uncovered sensitive files (server profile)
- 🔐 CHECK 32 — Secure Boot — UEFI Secure Boot state via mokutil/efivars/bootctl; WARN −1 pt if disabled on desktop; INFO if disabled on server/VM or unknown BIOS
- 🗂 CHECK 33 — File integrity monitoring (AIDE/Tripwire) — detects installation, database initialisation, and last check date; WARN −1 pt if no database or no recent check (>30 days)
- 🗣
--explainprofile variants — 17 keys show 3 dedicated sections (server / desktop / container) with profile-adapted explanations; uniform yellow note for keys that don't differ between profiles - 🖥
workstation→desktopprofile — profile renamed for clarity;workstationalias kept for backward compatibility - 🏷
cmd_typeon findings — findings now distinguishfixfromcheckcommands with different prefixes in the summary - 🐛 IPv6 avahi false alarm fixed — avahi-daemon, systemd-resolve, and similar internal processes no longer trigger UFW rule suggestions
- 📋 Logs journald fallback — Debian 13 without rsyslog automatically reads from
journalctl -k - ⚙️ Hardening sysctl persistence — fix commands now write to
/etc/sysctl.d/99-hardening.conf - 🚀 Trusted Publishing — GitHub Actions OIDC → PyPI; no API token required
- ✅ 2507/2507 unit tests (+215)
v1.16.0
- 🖥 CHECK 19 — Desktop application detection — detects known GUI apps (Steam, Discord, Zoom, Signal…) running as processes; INFO findings, no deduction; section shown only when apps detected
- 🕐 CHECK 28 — NTP time synchronisation — checks systemd-timesyncd/chronyd/ntpd; WARN −1 pt if disabled or not yet synchronised
- 🛡 CHECK 29 — Fail2ban intrusion prevention — dedicated standalone check; WARN −1 pt if service inactive or no jails configured; detects active SSH jail
- 🔍 CHECK 30 — Rootkit & integrity scan — rkhunter/chkrootkit detection; WARN −1 pt for outdated DB, missing scan, or stale scan (>30 days)
- 🎯
--target Nexit code 4 — returns exit code 4 when score < target (CI-ready); takes priority over codes 1/2 - 🚨 CLI validation —
--explain=,--profile=,--lang=,--webhook=,--target=with empty value now raise a clear error - 📐 5 thematic group headers — output reorganised into FIREWALL & NETWORK / EXPOSURE & SERVICES / ACCESS CONTROL / SYSTEM HARDENING / DETECTION & HEALTH; thick
━cyan separator - ✅ 2292/2292 unit tests (+153)
v1.15.1
- 🔧 Hotfix bash-completion —
--explainno longer gets a trailing=; value options (--target=,--log-days=,--profile=) no longer add a space after=
v1.15.0
- 🌐 CHECK 26 — IoT/local source dominance — detects when a single private IP accounts for ≥ 70% of all blocked UFW traffic (typical of LAN-scanning IoT devices)
- 📧 CHECK 27 — SMTP local exposure — detects Postfix/Exim/Sendmail listening on all interfaces (0.0.0.0:25) vs. localhost only; WARN −1 pt when publicly reachable
- 🔧
--fixdry-run by default —--fixpreviews corrections without executing;--fix --applyto execute interactively;--fix --apply --yesto auto-confirm with audit trail - 🎯
--target Nscore cible — shows a target line in the summary box: green✔when reached, yellow▲with gap when not - 🎛
--explainTUI — clamped navigation (no wrap), in-curses detail screen (ESC to return), ESC/q behavior corrected, group headers restored on scroll-up; 73→77 keys - ❌ Cancel at any wizard step —
qexits cleanly in--install-cron,--manage-cron,--manage-logs - ✅ 2139/2139 unit tests (+93)
🧠 Philosophy
Not just listing ports — understanding the real risk.
ufw-audit prioritises what matters: real exposure, attack surface, potential impact.
📁 Project structure
Automated-UFW-audit/
├── README.md / README_FR.md # project overview (EN/FR)
├── LICENSE
├── pyproject.toml # build config (pip/pipx install)
├── DOCUMENTS/
│ ├── README_TECH.md / _FR.md # complete technical reference
│ ├── README_DEV.md / _FR.md # developer documentation
│ ├── CHANGELOG_FULL.md / _FR.md # full version history
│ ├── TESTING.md / _FR.md # test plan & validated scenarios
│ └── AUTOMATION.md / _FR.md # cron & automation guide
├── ufw_audit/ # Python package
│ ├── checks/ # firewall, services, ports, logs, ddns, docker, virt, ssh
│ ├── data/
│ │ ├── services.json # 22 built-in service definitions
│ │ ├── profiles/ # built-in audit profiles (server, desktop, container)
│ │ └── ufw-audit.bash-completion
│ │ # ~/.config/ufw-audit/services.d/ ← user plugin directory (sudo: /root/...)
│ │ # ~/.config/ufw-audit/profiles/ ← user-defined audit profiles
│ └── locales/
│ ├── en.json
│ └── fr.json
└── tests/ # 2507 unit tests
📄 License
MIT — © 2026 Cédric Clauzel
🤝 Contributing
Bug reports, new detections, UX improvements — contributions welcome.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ufw_audit-1.17.0.tar.gz.
File metadata
- Download URL: ufw_audit-1.17.0.tar.gz
- Upload date:
- Size: 365.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60edb3d22710fc6c5056784b051b7f45892be3cab96576bb32801f5e01d9acce
|
|
| MD5 |
d11231cf2d830e98e7d175f1a5cac667
|
|
| BLAKE2b-256 |
d347d987251d1e64b53f358d7cdb3d649b1db7834ad336a8787172c9e98568a6
|
Provenance
The following attestation bundles were made for ufw_audit-1.17.0.tar.gz:
Publisher:
publish.yml on Masbateno/Automated-UFW-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ufw_audit-1.17.0.tar.gz -
Subject digest:
60edb3d22710fc6c5056784b051b7f45892be3cab96576bb32801f5e01d9acce - Sigstore transparency entry: 1310274349
- Sigstore integration time:
-
Permalink:
Masbateno/Automated-UFW-audit@ef77439855862ad2cd054406456a1816eae2901e -
Branch / Tag:
refs/tags/v1.17.0 - Owner: https://github.com/Masbateno
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ef77439855862ad2cd054406456a1816eae2901e -
Trigger Event:
push
-
Statement type:
File details
Details for the file ufw_audit-1.17.0-py3-none-any.whl.
File metadata
- Download URL: ufw_audit-1.17.0-py3-none-any.whl
- Upload date:
- Size: 286.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
115911dd64f579ff9a2e2d64f72827e35040cf4997f24ba071907da94183c37f
|
|
| MD5 |
18d66cbff53c892b45d8be04e536e731
|
|
| BLAKE2b-256 |
4fc8f043aa02721231371dbdb109a15ac70268281915e595e55ffce06e4d84ff
|
Provenance
The following attestation bundles were made for ufw_audit-1.17.0-py3-none-any.whl:
Publisher:
publish.yml on Masbateno/Automated-UFW-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ufw_audit-1.17.0-py3-none-any.whl -
Subject digest:
115911dd64f579ff9a2e2d64f72827e35040cf4997f24ba071907da94183c37f - Sigstore transparency entry: 1310274422
- Sigstore integration time:
-
Permalink:
Masbateno/Automated-UFW-audit@ef77439855862ad2cd054406456a1816eae2901e -
Branch / Tag:
refs/tags/v1.17.0 - Owner: https://github.com/Masbateno
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ef77439855862ad2cd054406456a1816eae2901e -
Trigger Event:
push
-
Statement type: