An open API service indexing awesome lists of open source software.

https://github.com/nning/ferronacc


https://github.com/nning/ferronacc

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

          

# ferronacc

> ⚠️ **Vibe-coded proof of concept — use at your own risk.**
> This project was built with AI assistance as an experimental prototype.
> It has not been audited for production use. Do not rely on it as your
> sole security control.

On-access antivirus scanner for Linux. Intercepts file opens at the kernel
level and scans with [ClamAV](https://www.clamav.net/) before allowing access.

## Primary use case: scanning Windows programs before Wine/Bottles runs them

If you download Windows executables and run them with
[Wine](https://www.winehq.org/) or [Bottles](https://usebottles.com/),
those programs are opened as ordinary Linux files before Wine interprets them.
ferronacc intercepts that `open()` call and scans the `.exe` / `.dll` / `.msi`
with ClamAV's Windows PE scanner before Wine is allowed to read a single byte.

**What this protects against:**
- Malicious `.exe` files in `~/Downloads/` before you run them in Wine
- Infected `.dll` files silently loaded by a Windows program inside a Bottles prefix
- `.msi` installers that drop malware into the Wine prefix at install time
- Any file in `~/.wine/` or `~/.local/share/bottles/` that gets written and
then opened (e.g., by a Windows dropper)

**Why ClamAV is right for this job:**
ClamAV has deep Windows PE support: PE header parsing, executable unpacking
(UPX, ASPack, FSG, …), MSI/CAB archive extraction, and a large Windows malware
signature database maintained by Cisco Talos. It is the same engine you would
use to scan a Windows machine remotely.

**Example config for Wine/Bottles use (add to `/etc/ferronacc.toml`):**
```toml
[paths]
include = [
"/home/YOUR_USER/Downloads",
"/home/YOUR_USER/.wine",
"/home/YOUR_USER/.local/share/bottles",
"/tmp",
]
exclude_uid = [] # scan all UIDs, including your own
```

---

## How it works

```
wine foo.exe

▼ (open syscall for foo.exe)
fanotify FAN_OPEN_PERM ──────────────────► ferronacc daemon

cache hit: │
CLEAN ───────────┤──► FAN_ALLOW (instant)
DIRTY ───────────┤──► FAN_DENY (instant)

cache miss: │
cl_scandesc(fd)──┤ (in-process, no socket)
CLEAN ◄──────────┤──► FAN_ALLOW + update cache
DIRTY ◄──────────┘──► FAN_DENY + log denial
```

After the first scan of any file, subsequent opens are served from the LRU
cache — zero additional overhead. The cache key is `(fsid, inode, size,
mtime_ns, db_version)`, so a modified file is automatically re-scanned.

---

## Why not clamonacc?

The existing ClamAV `clamonacc` daemon works but has fundamental limitations:

| | clamonacc | ferronacc |
|---|---|---|
| Scan caching | ✗ (rescans every access) | ✓ LRU cache keyed by inode+mtime |
| File identity | pathname (broken by renames) | `(fsid, inode)` via `FAN_REPORT_FID` |
| Scan transport | clamd socket (per-scan connect) | in-process `cl_scandesc(fd)` |
| Parallelism | global mutex | thread pool, `Arc` |
| Directory watching | inotify DDD (8 k limit) | `FAN_MARK_FILESYSTEM` (one mark) |
| eBPF in-kernel fast path | ✗ | ✓ Phase 2 |

## Status

| Phase | Description | Status |
|-------|-------------|--------|
| Phase 1 | fanotify + libclamav + LRU cache + CLI + GNOME notifier | ✅ Complete and validated |
| Phase 2 | eBPF LSM in-kernel cache fast-path | 🔴 not started |

Phase 1 has been fully validated: unit tests (stub engine), integration tests with real
`libclamav` + fanotify, and end-to-end EICAR blocking all pass. See
[`doc/architecture.md`](doc/architecture.md) for the work package execution plan.

## Requirements

- **Linux 5.9+** (Fedora 35+, RHEL 9, Ubuntu 22.04, Debian 12)
- **ClamAV 1.4+** installed: `sudo dnf install clamav clamav-devel`
- Rust stable toolchain
- `CAP_SYS_ADMIN` or `CAP_DAC_READ_SEARCH` at runtime (fanotify)
- `CAP_BPF` + `CAP_PERFMON` (Phase 2 only)

## Installation on Fedora

### Prerequisites

```bash
sudo dnf install clamav clamav-devel clamav-freshclam rpm-build clang-devel
```

`clamav-devel` is needed to build the ClamAV FFI bindings at compile time.
`clang-devel` is needed by `bindgen` (generates Rust FFI from `clamav.h`).

### Build and install the RPM

```bash
# Build
just rpm

# Install
sudo rpm -ivh packaging/rpmbuild/RPMS/x86_64/ferronacc-0.1.0-1.fc44.x86_64.rpm
```

The RPM installs:

| Path | Contents |
|------|----------|
| `/usr/bin/ferronacc` | Daemon binary |
| `/usr/bin/ferronacc-ctl` | CLI control tool |
| `/usr/bin/ferronacc-notify` | GNOME desktop notifier |
| `/etc/ferronacc/ferronacc.toml` | Config file (`%config noreplace`) |
| `/usr/lib/systemd/system/ferronacc.service` | System service unit |
| `/usr/lib/systemd/user/ferronacc-notify.service` | User service unit |
| `/var/lib/ferronacc/` | State directory (`root:ferronacc 0750`) |

### Post-install setup

```bash
# 1. Edit config (watched paths, cache size, etc.)
sudoedit /etc/ferronacc/ferronacc.toml

# 2. Start and enable the daemon
sudo systemctl enable --now ferronacc

# 3. Add your user to the ferronacc group (required for GNOME notifier)
sudo usermod -aG ferronacc $USER
# Log out and back in for the group change to take effect.

# 4. Enable the GNOME notifier (per-user, runs in your desktop session)
systemctl --user enable --now ferronacc-notify
```

### Verify it works

```bash
# Check daemon status and ClamAV DB version
ferronacc-ctl status

# Try to open the EICAR test file (should return EACCES)
curl -s https://secure.eicar.org/eicar.com -o /tmp/eicar.com
cat /tmp/eicar.com # → cat: /tmp/eicar.com: Permission denied

# Allow a trusted file version (survives DB updates until the file changes)
ferronacc-ctl allow /absolute/path/to/file

# List blocked files
ferronacc-ctl list-denials
```

## Configuration

Configuration is a single TOML file (default `/etc/ferronacc.toml`).
Key sections:

```toml
[paths]
include = ["/home", "/tmp", "/var/www"]
exclude = ["/home/user/.cache"]

[fanotify]
prevention = true # blocking mode; false = log-only (no FAN_DENY)

[scanner]
max_threads = 8

[cache]
size = 65536 # LRU entry count
ttl_seconds = 300

[denial_log]
db_path = "/var/lib/ferronacc/denials.db"
max_entries = 10000 # rotate beyond this
```

See `config/ferronacc.toml` for all options.

## Viewing denials

### CLI (server or desktop)

```bash
# List recent denials
ferronacc-ctl list-denials

# Filter by last 24 hours
ferronacc-ctl list-denials --since 24h

# Show daemon status (uptime, DB version, cache hit rate)
ferronacc-ctl status

# Trust or revoke a specific file version
ferronacc-ctl allow /absolute/path/to/file
ferronacc-ctl unallow /absolute/path/to/file
ferronacc-ctl list-allowed

# Trigger engine reload (also automatic on freshclam DB update)
ferronacc-ctl reload
```

### GNOME desktop (Fedora)

The user-session notifier is enabled as part of the post-install setup above
(see [Installation on Fedora](#installation-on-fedora)). Your user must be a
member of the `ferronacc` group so it can read `denials.db`.

```bash
# Check group membership
groups $USER # should include 'ferronacc'

# Re-enable if needed
systemctl --user enable --now ferronacc-notify
```

When a file is blocked, a GNOME notification appears:
> **ferronacc blocked a file**
> `Eicar-Test-Signature` in `/tmp/test.exe` (accessed by `bash`, PID 1234)

Clicking the notification opens `ferronacc-ctl list-denials` in a terminal.

## Denial policy

Access is **denied** (the calling process receives `EACCES`). Files are **not
quarantined or deleted** — they remain on disk so that false positives don't
cause data loss and the admin can inspect them.

To investigate a blocked file manually:
```bash
# Rescan with verbose output
clamscan --debug /path/to/file

# After confirming: delete or move to safe location
sudo rm /path/to/file
```

## Architecture and design docs

| Document | Contents |
|----------|----------|
| [`doc/architecture.md`](doc/architecture.md) | 3-layer architecture (eBPF LSM + fanotify + userspace daemon), adaptive scanner design, denial management, Rust crate layout, libclamav FFI surface, and the AI-agent execution plan with work packages and handoff rules |
| [`doc/security-enhancements.md`](doc/security-enhancements.md) | Beyond signatures: YARA rules, SaneSecurity, PE entropy, Authenticode, CIRCL HASHLOOKUP, VirusTotal — enrichment pipeline design |
| [`doc/quality.md`](doc/quality.md) | Code quality standards, test pyramid, coverage targets, CI pipeline, security-critical path requirements |
| [`doc/testing.md`](doc/testing.md) | VM test setup (Vagrant + KVM), `just` task runner, integration and e2e test instructions |
| [`doc/dev-setup.md`](doc/dev-setup.md) | Full development setup: host deps, Rust toolchain, VS Code config, debugging, Wine/Bottles testing walkthrough |

## License

TBD