From 55dad05652e0c204bf45b4e61785236fa5791b47 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Tue, 8 Sep 2026 19:54:10 +0200 Subject: [PATCH] refactor: update whitelists to replace Openfactory with Init7 and adjust related configurations --- .env.example | 3 +-- README.md | 5 ++--- app/firewall.py | 2 +- app/utils/constants.py | 8 +++----- app/utils/whitelists.py | 38 +++++++++++++++++++------------------- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/.env.example b/.env.example index 7c0db37..8e78739 100644 --- a/.env.example +++ b/.env.example @@ -40,7 +40,7 @@ ROUTER_PASSWORD=change-me BLOCKLIST_NAME=Blocked # Comma-separated address lists that are treated as whitelisted (never blocked). -WHITELIST_NAMES=Cloudflare,Openfactory +WHITELIST_NAMES=Cloudflare,Init7 # --- WHOIS subnet consolidation -------------------------------------------- @@ -79,7 +79,6 @@ DEFAULT_TOP_PATHS=20 # --- Whitelist sources ----------------------------------------------------- -OPENFACTORY_URL=https://openfactory.net/geofeed.csv CLOUDFLARE_URL_V4=https://www.cloudflare.com/ips-v4 CLOUDFLARE_URL_V6=https://www.cloudflare.com/ips-v6 PALOALTO_URL=https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity \ No newline at end of file diff --git a/README.md b/README.md index 7b05594..68f6952 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,7 @@ intrusion-detection/ │ ├── static/ style.css + app.js (dark-theme UI) │ └── templates/ Jinja2 page templates (dashboard, scan, reports, …) ├── data/ whitelist source files (cached locally) -│ ├── openfactory/ -│ │ └── geofeed.csv +│ ├── init7/ (ranges built into app/utils/whitelists.py — no geofeed) │ ├── cloudflare/ │ │ ├── ips-v4.txt │ │ └── ips-v6.txt @@ -135,7 +134,7 @@ production can set the same variables via the OS and skip `.env` entirely. | `ROUTER_USER` | `admin` | MikroTik connection | | `ROUTER_PASSWORD` | _(set in .env)_ | MikroTik connection | | `BLOCKLIST_NAME` | `Blocked` | MikroTik address list | -| `WHITELIST_NAMES` | `Cloudflare,Openfactory` | MikroTik whitelists | +| `WHITELIST_NAMES` | `Cloudflare,Init7` | MikroTik whitelists | | `WEB_HOST` | `127.0.0.1` | web UI bind host | | `WEB_PORT` | `54666` | web UI port | diff --git a/app/firewall.py b/app/firewall.py index 798874c..8ab21c2 100644 --- a/app/firewall.py +++ b/app/firewall.py @@ -272,7 +272,7 @@ def get_scan_report(report_dir: str = REPORT_DIR) -> dict[str, list[str]]: "/ip firewall address-list": [], "/ipv6 firewall address-list": [], } - # add list=Cloudflare or list=Openfactory to whitelist sections, list=Blocked to blocked section + # add list=Cloudflare or list=Init7 to whitelist sections, list=Blocked to blocked section with open(report_path, "r", encoding="utf-8") as f: current_section = None for line in f: diff --git a/app/utils/constants.py b/app/utils/constants.py index 706d629..8c33eb5 100644 --- a/app/utils/constants.py +++ b/app/utils/constants.py @@ -73,7 +73,8 @@ REPORT_RETENTION_MAX_FILES = int( # Log sources (configurable via environment) # --------------------------------------------------------------------------- -COPYPARTY_LOG_PATH = os.environ.get("COPYPARTY_LOG_PATH", "/srv/projects/copyparty") +COPYPARTY_LOG_PATH = os.environ.get( + "COPYPARTY_LOG_PATH", "/srv/projects/copyparty") NPM_LOG_PATH = os.environ.get("NPM_LOG_PATH", "/mnt/backups/npm/logs") # --------------------------------------------------------------------------- @@ -91,7 +92,7 @@ BLOCKLIST_NAME = os.environ.get("BLOCKLIST_NAME", "Blocked") WHITELIST_NAMES = [ name.strip() for name in os.environ.get( - "WHITELIST_NAMES", "Cloudflare,Openfactory").split(",") + "WHITELIST_NAMES", "Cloudflare,Init7").split(",") if name.strip() ] @@ -131,8 +132,6 @@ WEB_PORT = int(os.environ.get("WEB_PORT", "54666")) # Whitelist sources (configurable via environment) # --------------------------------------------------------------------------- -OPENFACTORY_URL = os.environ.get( - "OPENFACTORY_URL", "https://openfactory.net/geofeed.csv") CLOUDFLARE_URL_V4 = os.environ.get( "CLOUDFLARE_URL_V4", "https://www.cloudflare.com/ips-v4") CLOUDFLARE_URL_V6 = os.environ.get( @@ -143,7 +142,6 @@ PALOALTO_URL = os.environ.get( ) # Local whitelist files (checked before remote download) -OPENFACTORY_FILE = os.path.join(DATA_DIR, "openfactory", "geofeed.csv") CLOUDFLARE_V4_FILE = os.path.join(DATA_DIR, "cloudflare", "ips-v4.txt") CLOUDFLARE_V6_FILE = os.path.join(DATA_DIR, "cloudflare", "ips-v6.txt") PALOALTO_FILE = os.path.join(DATA_DIR, "paloalto", "scanner-ips.txt") diff --git a/app/utils/whitelists.py b/app/utils/whitelists.py index a6bef95..a55a15c 100644 --- a/app/utils/whitelists.py +++ b/app/utils/whitelists.py @@ -23,8 +23,6 @@ from .constants import ( CLOUDFLARE_URL_V6, CLOUDFLARE_V4_FILE, CLOUDFLARE_V6_FILE, - OPENFACTORY_FILE, - OPENFACTORY_URL, PALOALTO_FILE, PALOALTO_URL, ) @@ -40,15 +38,26 @@ CIDR_RE = re.compile( # Local file paths (checked first, before remote download) # --------------------------------------------------------------------------- -# (paths live in app/constants.py as OPENFACTORY_FILE, CLOUDFLARE_V4_FILE, -# CLOUDFLARE_V6_FILE, PALOALTO_FILE; URLs as OPENFACTORY_URL, ...) +# (paths live in app/constants.py as CLOUDFLARE_V4_FILE, +# CLOUDFLARE_V6_FILE, PALOALTO_FILE; URLs as CLOUDFLARE_URL_V4, ...) # --------------------------------------------------------------------------- # Built-in fallback CIDR lists # --------------------------------------------------------------------------- -#: Openfactory AS58299 colocation IP range (https://openfactory.net/geofeed.csv) -OPENFACTORY_IPV4 = ["5.226.144.0/21"] +#: Init7 (Switzerland) Ltd. ranges — AS13030, verified via RIPE RDAP 2026-09-08. +#: Includes the Hybrid7 WAN /24 (router WAN 77.74.80.159), init7 DNS +#: infrastructure, and the PPPoE gateway. init7 publishes no geofeed, so +#: these are maintained here rather than downloaded. +INIT7_IPV4 = [ + "77.74.80.0/24", # Hybrid7 WAN /24 + "77.109.128.0/18", # init7 DNS / infrastructure + "213.144.128.0/19", # init7 DNS / infrastructure + "5.180.132.0/22", # init7 PPPoE gateway +] + +#: init7 IPv6 allocation (contains delegated /48 2001:1620:549f::/48) +INIT7_IPV6 = ["2001:1620::/30"] #: https://www.cloudflare.com/ips-v4 CLOUDFLARE_IPV4 = [ @@ -85,7 +94,7 @@ PALOALTO_IPV6 = [ #: address-list name -> CIDR ranges (v4 + v6 mixed, split at render time) WHITELISTS: dict[str, list[str]] = { - "Openfactory": OPENFACTORY_IPV4, + "Init7": INIT7_IPV4 + INIT7_IPV6, "Cloudflare": CLOUDFLARE_IPV4 + CLOUDFLARE_IPV6, "PaloAlto": PALOALTO_IPV4 + PALOALTO_IPV6, } @@ -141,9 +150,7 @@ def _load_local_whitelists() -> dict[str, list[str]]: successfully parsed CIDRs are included. """ out: dict[str, list[str]] = {} - cidrs = _read_local_file(OPENFACTORY_FILE) - if cidrs: - out["Openfactory"] = cidrs + # Init7 has no published geofeed; its ranges are built-in (INIT7_IPV4/6). cf_v4 = _read_local_file(CLOUDFLARE_V4_FILE) cf_v6 = _read_local_file(CLOUDFLARE_V6_FILE) if cf_v4 or cf_v6: @@ -190,14 +197,7 @@ def _download_whitelists() -> dict[str, list[str]]: Saves each download to the corresponding local file on success. """ out: dict[str, list[str]] = {} - try: - text = _download_text(OPENFACTORY_URL) - cidrs = extract_cidrs(text) - if cidrs: - out["Openfactory"] = cidrs - _save_local_file(OPENFACTORY_FILE, text) - except Exception as e: - print(f"Error downloading Openfactory whitelist: {e}") + # Init7 has no published geofeed; its ranges are built-in (INIT7_IPV4/6). try: text_v4 = _download_text(CLOUDFLARE_URL_V4) text_v6 = _download_text(CLOUDFLARE_URL_V6) @@ -242,7 +242,7 @@ def update_whitelists() -> None: # Start from built-in fallbacks, then layer local, then remote WHITELISTS = { - "Openfactory": OPENFACTORY_IPV4, + "Init7": INIT7_IPV4 + INIT7_IPV6, "Cloudflare": CLOUDFLARE_IPV4 + CLOUDFLARE_IPV6, "PaloAlto": PALOALTO_IPV4 + PALOALTO_IPV6, }