Automatically sync Bunny CDN edge-server IPs to a Fail2ban whitelist — preventing 502 errors caused by accidentally banning Bunny edge proxies.
- How It Works
- Features
- Requirements
- Installation
- Configuration
- Usage
- Generated Config File
- Verification
- Troubleshooting
- Development
- License
Bunny CDN API ──► Fail2Bunny ──► /etc/fail2ban/jail.d/bunny-edges.local ──► Fail2ban reload
- Fetch — Downloads IPv4 and IPv6 edge-server lists from the Bunny CDN API.
- Validate — Parses and deduplicates all IP addresses and CIDR ranges.
- Merge — Combines fetched IPs with your baseline whitelist (localhost, admin IPs, etc.).
- Compare — Diffs against the existing config file; skips writes when nothing changed.
- Write — Atomically writes the new config (temp file → rename, no partial writes).
- Reload — Reloads Fail2ban only when changes were actually made.
| 📥 | Downloads IPv4 + IPv6 edge lists from Bunny CDN API |
| ✔️ | Validates and deduplicates IP/CIDR entries |
| 🔄 | Atomic file updates — no partial writes |
| 🎯 | Reloads Fail2ban only on actual changes |
| 🛡️ | Configurable baseline IPs (localhost, admin, private ranges) |
| 🧪 | Dry-run mode for safe previews |
| 📝 | Systemd-friendly logging (stdout/stderr) |
| 📦 | Zero external dependencies — Python standard library only |
| Dependency | Version |
|---|---|
| Python | 3.9+ |
| Fail2ban | installed & configured |
| Privileges | root / sudo |
sudo cp fail2bunny.py /usr/local/bin/
sudo chmod +x /usr/local/bin/fail2bunny.py
sudo mkdir -p /etc/fail2bunny
sudo cp config.json.example /etc/fail2bunny/config.jsonsudo cp systemd/fail2bunny.service /etc/systemd/system/
sudo cp systemd/fail2bunny.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now fail2bunny.timer# Run every 6 hours
0 */6 * * * /usr/bin/python3 /usr/local/bin/fail2bunny.py 2>&1 | logger -t fail2bunnyEdit /etc/fail2bunny/config.json:
{
"target_file": "/etc/fail2ban/jail.d/bunny-edges.local",
"baseline_ignoreip": [
"127.0.0.1/8",
"::1",
"10.0.0.0/8",
"192.168.1.100"
],
"timeout_seconds": 30,
"reload_method": "auto",
"interval_hint": "6h"
}| Option | Description | Default |
|---|---|---|
target_file |
Path to the generated Fail2ban config file | /etc/fail2ban/jail.d/bunny-edges.local |
baseline_ignoreip |
IPs/CIDRs to always include in the whitelist | ["127.0.0.1/8", "::1"] |
timeout_seconds |
HTTP request timeout (seconds) | 30 |
reload_method |
Fail2ban reload strategy: auto, systemctl, service, or client |
auto |
interval_hint |
Informational hint for scheduling frequency | "6h" |
# Standard run
sudo fail2bunny.py
# Custom config path
sudo fail2bunny.py -c /path/to/config.json
# Dry run — preview changes without writing or reloading
sudo fail2bunny.py --dry-run
# Verbose output
sudo fail2bunny.py -v| Flag | Short | Description |
|---|---|---|
--config |
-c |
Path to config file (default: /etc/fail2bunny/config.json) |
--dry-run |
Show what would change without writing or reloading | |
--verbose |
-v |
Enable debug-level output |
sudo journalctl -u fail2bunny.service -fsudo systemctl status fail2bunny.timer
sudo systemctl list-timers fail2bunny.timerFail2Bunny generates /etc/fail2ban/jail.d/bunny-edges.local:
# Bunny CDN Edge IP Whitelist for Fail2ban
# Auto-generated by fail2bunny — DO NOT EDIT MANUALLY
#
# IPv4 entries: 595
# IPv6 entries: 345
# Baseline entries: 2
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 1.2.3.4/32 5.6.7.8/32 …The [DEFAULT] section extends ignoreip for all Fail2ban jails.
# All ignoreip rules across config
sudo fail2ban-client -d | grep -i "ignoreip"
# Per-jail check (e.g. sshd)
sudo fail2ban-client get sshd ignoreip
# Inspect generated file directly
cat /etc/fail2ban/jail.d/bunny-edges.local
# Overall Fail2ban status
sudo fail2ban-client status --allFail2ban not reloading
sudo systemctl status fail2ban # is it running?
sudo fail2ban-client reload # manual reloadConfiguration syntax errors
sudo fail2ban-client -d # dumps parsed config, shows errorsNetwork connectivity issues
curl -I https://bunnycdn.com/api/system/edgeserverlist/git clone git@github.com:ronaldvdmeer/Fail2Bunny.git
cd Fail2Bunny
# Preview changes locally
python3 fail2bunny.py --dry-runRonald van der Meer