No description
- Python 100%
| ufw_manager | ||
| LICENSE | ||
| pyproject.toml | ||
| readme.md | ||
UFW Manager - TUI Firewall Rule Management System
Project Overview
A Terminal User Interface (TUI) application for managing UFW (Uncomplicated Firewall) rules with advanced features like rule enable/disable, profile management, state tracking, and audit logging. Designed for system administrators who need efficient, repeatable firewall management beyond UFW's basic CLI.
Core Philosophy
- Stateful Management: Track rule state independently from UFW (enabled/disabled/archived)
- Non-Destructive: Never lose rule configurations - disable instead of delete
- Profile-Based: Quick switching between predefined firewall configurations
- Audit Trail: Full history of changes for compliance and debugging
- Declarative Sync: Define desired state, let the tool reconcile with UFW
Technical Stack
Core Technologies
- Language: Python 3.11+
- TUI Framework: Textual - Modern, async Python TUI framework with rich widgets
- Database: SQLite3 - Embedded, zero-config state management
- Privilege Management: Subprocess with
sudofor UFW commands
Key Dependencies
textual>=0.40.0 # TUI framework
rich>=13.0.0 # Terminal formatting
click>=8.0.0 # CLI argument parsing
pydantic>=2.0.0 # Data validation
sqlalchemy>=2.0.0 # Database ORM (optional, or raw sqlite3)
Architecture
Component Structure
ufw-manager/
├── ufw_manager/
│ ├── __init__.py
│ ├── __main__.py # Entry point
│ ├── cli.py # CLI commands (--init, --export, etc.)
│ ├── core/
│ │ ├── database.py # SQLite schema & operations
│ │ ├── ufw_interface.py # UFW command wrapper
│ │ ├── rule_engine.py # Rule reconciliation logic
│ │ ├── profile_manager.py # Profile operations
│ │ └── models.py # Data models (Rule, Profile, AuditLog)
│ ├── tui/
│ │ ├── app.py # Main Textual app
│ │ ├── screens/
│ │ │ ├── main_screen.py # Rule list & management
│ │ │ ├── rule_editor.py # Add/Edit rule form
│ │ │ ├── profile_screen.py # Profile management
│ │ │ └── audit_screen.py # View audit logs
│ │ └── widgets/
│ │ ├── rule_table.py # Custom rule display widget
│ │ ├── status_bar.py # UFW status indicator
│ │ └── confirm_dialog.py # Confirmation prompts
│ └── utils/
│ ├── sudo.py # Sudo privilege handling
│ ├── validators.py # IP/Port/Protocol validation
│ └── export_import.py # YAML/JSON export/import
├── tests/
├── docs/
├── pyproject.toml
└── README.md
Database Schema
-- Rules table: All firewall rules (active, disabled, archived)
CREATE TABLE rules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uuid TEXT UNIQUE NOT NULL, -- Unique identifier
rule_type TEXT NOT NULL, -- 'allow', 'deny', 'reject', 'limit',
-- 'route_allow', 'route_deny', 'route_reject', 'route_limit'
protocol TEXT, -- 'tcp', 'udp', 'any'
port TEXT, -- '80', '8000:9000', NULL
from_ip TEXT, -- Source IP/CIDR
to_ip TEXT, -- Dest IP/CIDR
interface TEXT, -- Network interface
comment TEXT, -- User description
state TEXT NOT NULL DEFAULT 'enabled', -- 'enabled', 'disabled', 'archived'
ufw_rule_number INTEGER, -- Current UFW rule number (if active)
priority INTEGER DEFAULT 1000, -- Rule ordering
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Profiles: Named firewall configurations
CREATE TABLE profiles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
description TEXT,
default_incoming TEXT DEFAULT 'deny', -- 'allow', 'deny', 'reject'
default_outgoing TEXT DEFAULT 'allow', -- 'allow', 'deny', 'reject'
default_routed TEXT DEFAULT 'disabled', -- 'disabled', 'allow', 'deny', 'reject'
is_active BOOLEAN DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Profile-Rule mapping: Many-to-many relationship
CREATE TABLE profile_rules (
profile_id INTEGER,
rule_id INTEGER,
FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE,
FOREIGN KEY (rule_id) REFERENCES rules(id) ON DELETE CASCADE,
PRIMARY KEY (profile_id, rule_id)
);
-- Audit log: All changes for compliance
CREATE TABLE audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
action TEXT NOT NULL, -- 'enable', 'disable', 'create', 'delete', 'profile_switch'
rule_id INTEGER,
profile_id INTEGER,
details TEXT, -- JSON blob with change details
user TEXT, -- System user who made change
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (rule_id) REFERENCES rules(id),
FOREIGN KEY (profile_id) REFERENCES profiles(id)
);
-- Settings: Application configuration
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
Core Features
1. Rule Management
- Enable/Disable: Toggle rules without deletion - preserves configuration
- CRUD Operations: Create, read, update, archive rules
- Bulk Operations: Enable/disable multiple rules at once
- Priority Ordering: Control rule evaluation order
- Rich Rules: Support for complex rules (port ranges, CIDR blocks, interfaces)
- Routing Rules: Full support for UFW routing/forwarding rules (ROUTE ALLOW, ROUTE DENY, etc.)
2. Profile System
- Profile Creation: Define named firewall configurations (production, development, maintenance)
- Quick Switching: Apply entire profile with one command
- Profile Inheritance: Base profiles with overrides
- Diff View: Compare current state vs profile before applying
- UFW Defaults: Each profile stores default policies for incoming, outgoing, and routed traffic
3. State Synchronization
- Import from UFW: Parse existing UFW rules into database on first run
- Reconciliation: Detect drift between database state and actual UFW rules
- Dry-Run Mode: Preview changes before applying
- Rollback: Revert to previous configuration snapshot
4. UFW Defaults Management
- Per-Profile Defaults: Each profile stores its own default policies
- Three Policies: Control default incoming, outgoing, and routed traffic
- Policy Options: Allow, Deny, Reject (plus Disabled for routed)
- Auto-Apply: Defaults are applied when a profile is applied to UFW
- Edit via Profile Screen: Press
ein the profile screen to edit defaults
5. Live Status Panel
- Toggle Panel: Press
sto show/hide the UFW status panel - Raw Output: Displays the full
ufw status verboseoutput - Syntax Highlighting: Status and rules are color-coded for readability
- Auto-Refresh: Panel updates after applying changes or toggling UFW
6. TUI Interface
Main Screen Layout:
┌─ UFW Manager ─────────────────────────────────────────────────────────────────┐
│ Profile: [Production ▼] UFW Status: ● Active │
├──────────────────────────────────────────────────┬────────────────────────────┤
│ ● ID Type Protocol Port From Comment │ UFW Status │
│ ● 1 ALLOW tcp 22 any SSH │ Status: active │
│ ● 2 ALLOW tcp 80 any HTTP │ Default: deny (incoming) │
│ ○ 3 ALLOW tcp 443 any HTTPS-DEV │ Default: allow (outgoing) │
│ ● 4 R.ALLOW tcp 8080 any Forward │ Default: deny (routed) │
│ ● 5 DENY tcp any 10.0.0.0/8 │ │
├──────────────────────────────────────────────────┴────────────────────────────┤
│ [o] Add [e] Edit [d] Delete [g] Toggle [a] Apply [p] Profiles [s] Status [q] │
└───────────────────────────────────────────────────────────────────────────────┘
Key Bindings:
o- Add new rule (opens form)e- Edit selected ruled- Archive rule (soft delete)g- Toggle enable/disablea- Apply changes to UFW (with confirmation)p- Manage profiles (select, create, edit defaults)s- Toggle live UFW status paneli- Import existing UFW rulesr- Refresh displayu- Toggle UFW on/offj/k- Navigate up/down (vim-style)?- Show helpq- Quit (with unsaved changes warning)
Profile Screen Key Bindings:
Enter- Select profilen- Create new profilee- Edit UFW defaults (incoming, outgoing, routed)d- Delete profileEscape- Cancel
7. CLI Interface
# Initialize database and import existing rules
ufw-manager --init
# Launch TUI
ufw-manager
# Non-interactive commands
ufw-manager profile apply production
ufw-manager rule enable --id 5
ufw-manager export --format yaml --output backup.yaml
ufw-manager import --file backup.yaml --merge
# Show current state
ufw-manager status --detailed
Privilege Management
Sudo Strategy
# utils/sudo.py
import os
import subprocess
from typing import List
class SudoManager:
"""Handle sudo privilege elevation for UFW commands"""
def __init__(self):
self.is_root = os.geteuid() == 0
def check_privileges(self) -> bool:
"""Verify we can execute UFW commands"""
try:
result = subprocess.run(
['sudo', '-n', 'ufw', 'status'],
capture_output=True,
timeout=2
)
return result.returncode == 0
except:
return False
def run_ufw_command(self, args: List[str]) -> subprocess.CompletedProcess:
"""Execute UFW command with sudo"""
cmd = ['sudo', 'ufw'] + args
return subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
Security Considerations
- Minimal Sudo Usage: Only UFW commands require sudo, not the entire application
- Sudoers Configuration (optional):
# /etc/sudoers.d/ufw-manager %wheel ALL=(ALL) NOPASSWD: /usr/sbin/ufw - Input Validation: Sanitize all user input before passing to UFW
- Audit Logging: Record all privileged operations
Implementation Phases
Phase 1: Core Infrastructure (MVP)
- Database schema implementation
- UFW command wrapper
- Basic rule CRUD operations
- Simple TUI with rule list
- Enable/disable functionality
Phase 2: Profile System
- Profile creation/management
- Profile-rule associations
- Profile switching logic
- Import existing UFW rules
Phase 3: Advanced Features
- Audit logging
- Rule reconciliation
- Export/import (YAML/JSON)
- Search and filtering
- Bulk operations
Phase 4: Polish & Packaging
- Error handling & user feedback
- Documentation
- Unit tests
- Python package (PyPI)
- Arch Linux PKGBUILD
Packaging
Python Package Structure
# pyproject.toml
[build-system]
requires = ["setuptools>=65.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "ufw-manager"
version = "0.1.0"
description = "TUI-based UFW firewall rule manager"
authors = [{name = "flouda"}]
requires-python = ">=3.11"
dependencies = [
"textual>=0.40.0",
"rich>=13.0.0",
"click>=8.0.0",
"pydantic>=2.0.0",
]
[project.scripts]
ufw-manager = "ufw_manager.__main__:main"
[project.optional-dependencies]
dev = ["pytest", "black", "ruff", "mypy"]
Arch Linux PKGBUILD
# PKGBUILD
pkgname=ufw-manager
pkgver=0.1.0
pkgrel=1
pkgdesc="TUI-based UFW firewall rule manager"
arch=('any')
url="https://github.com/flouda/ufw-manager"
license=('MIT')
depends=('python' 'python-textual' 'python-rich' 'python-click' 'ufw')
makedepends=('python-build' 'python-installer' 'python-wheel')
source=("$pkgname-$pkgver.tar.gz")
sha256sums=('SKIP')
build() {
cd "$pkgname-$pkgver"
python -m build --wheel --no-isolation
}
package() {
cd "$pkgname-$pkgver"
python -m installer --destdir="$pkgdir" dist/*.whl
}
Future Enhancements
- Multi-host Management: Manage UFW across multiple servers
- Template System: Rule templates for common services
- Integration: Export to Ansible/Terraform
- Notifications: Alert on rule changes
- Web UI: Optional web interface for remote management
- IPv6 Support: Full IPv6 rule management
- Advanced Rate Limiting: Enhanced rate limit configurations
- Rule Search/Filter: Search and filter rules by various criteria
- Bulk Operations UI: Select and operate on multiple rules at once
Project Goals:
- Make UFW management efficient for power users
- Provide state management UFW lacks natively
- Enable reproducible firewall configurations
- Maintain audit trail for compliance
- Zero dependencies on external services (fully self-contained)
This should give you a solid foundation to build on. Want to start with the database schema and core rule engine first, or jump straight into the TUI skeleton?