Refactor web_scan.py for improved readability and maintainability; add cron job script for npm log backups; update start.ps1 for consistent formatting.

This commit is contained in:
zwitschi committed 2026-09-08 19:49:11 +02:00
1 parent 0d1cd21468
commit c2eba88ac8
113 files changed
+772606 -772579

No files matched your search

+84 -84
View File
@@ -1,85 +1,85 @@
# ---------------------------------------------------------------------------
# Intrusion Detection System — environment template
# ---------------------------------------------------------------------------
# Copy this file to `.env` for local development and fill in your values:
#
# copy .env.example .env
#
# Precedence: real system environment variables win over values in `.env`,
# so production deployments can set these via the OS and skip `.env`.
# `.env` is git-ignored — never commit real secrets to it.
# --- Web server (localhost only) -------------------------------------------------
# The Flask web UI binds to localhost so it is only reachable from this machine.
# Do not expose WEB_HOST beyond 127.0.0.1!
WEB_HOST=127.0.0.1
# Please choose a very high port number (e.g. 54666) to avoid conflicts with other services.
WEB_PORT=54666
# --- Log sources -----------------------------------------------------------
# Directory containing copyparty access logs (YYYY-MM-DD.txt files).
COPYPARTY_LOG_PATH=P:\copyparty
# Directory containing Nginx Proxy Manager proxy logs (.log / .gz files).
NPM_LOG_PATH=Y:\npm\logs
# --- MikroTik RouterOS connection -----------------------------------------
# IP/hostname of the router to sync the blocklist to.
ROUTER_IP=192.168.88.1
# SSH user for the router.
ROUTER_USER=admin
# SSH password for the router (required when --update-firewall is used).
ROUTER_PASSWORD=change-me
# Address list on the router that holds blocked IPs/subnets.
BLOCKLIST_NAME=Blocked
# Comma-separated address lists that are treated as whitelisted (never blocked).
WHITELIST_NAMES=Cloudflare,Openfactory
# --- WHOIS subnet consolidation --------------------------------------------
WHOIS_SERVER=whois.radb.net
WHOIS_PORT=43
WHOIS_TIMEOUT=3.0
# Minimum number of same-subnet IPs before blocking the whole subnet.
SUBNET_THRESHOLD=3
# --- Report retention ------------------------------------------------------
# Each subdirectory under /reports/ keeps at most REPORT_RETENTION_MAX_FILES
# files, all newer than REPORT_RETENTION_DAYS days. Older timestamped reports
# are pruned automatically after each consolidated scan. The blocklist files
# in reports/app/data/ are always protected.
REPORT_RETENTION_DAYS=30
REPORT_RETENTION_MAX_FILES=10
# --- Scan / flagging defaults ----------------------------------------------
# Rows in the top-IP report tables.
DEFAULT_TOP=30
# copyparty: minimum denied hits before flagging an IP.
DEFAULT_MIN_DENIED=1
# npm: minimum error responses before flagging an IP.
DEFAULT_MIN_ERRORS=5
# npm: minimum error ratio before flagging an IP.
DEFAULT_ERROR_RATIO=0.5
# Rows in the "top error paths" report section.
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
# ---------------------------------------------------------------------------
# Intrusion Detection System — environment template
# ---------------------------------------------------------------------------
# Copy this file to `.env` for local development and fill in your values:
#
# copy .env.example .env
#
# Precedence: real system environment variables win over values in `.env`,
# so production deployments can set these via the OS and skip `.env`.
# `.env` is git-ignored — never commit real secrets to it.
# --- Web server (localhost only) -------------------------------------------------
# The Flask web UI binds to localhost so it is only reachable from this machine.
# Do not expose WEB_HOST beyond 127.0.0.1!
WEB_HOST=127.0.0.1
# Please choose a very high port number (e.g. 54666) to avoid conflicts with other services.
WEB_PORT=54666
# --- Log sources -----------------------------------------------------------
# Directory containing copyparty access logs (YYYY-MM-DD.txt files).
COPYPARTY_LOG_PATH=P:\copyparty
# Directory containing Nginx Proxy Manager proxy logs (.log / .gz files).
NPM_LOG_PATH=Y:\npm\logs
# --- MikroTik RouterOS connection -----------------------------------------
# IP/hostname of the router to sync the blocklist to.
ROUTER_IP=192.168.88.1
# SSH user for the router.
ROUTER_USER=admin
# SSH password for the router (required when --update-firewall is used).
ROUTER_PASSWORD=change-me
# Address list on the router that holds blocked IPs/subnets.
BLOCKLIST_NAME=Blocked
# Comma-separated address lists that are treated as whitelisted (never blocked).
WHITELIST_NAMES=Cloudflare,Openfactory
# --- WHOIS subnet consolidation --------------------------------------------
WHOIS_SERVER=whois.radb.net
WHOIS_PORT=43
WHOIS_TIMEOUT=3.0
# Minimum number of same-subnet IPs before blocking the whole subnet.
SUBNET_THRESHOLD=3
# --- Report retention ------------------------------------------------------
# Each subdirectory under /reports/ keeps at most REPORT_RETENTION_MAX_FILES
# files, all newer than REPORT_RETENTION_DAYS days. Older timestamped reports
# are pruned automatically after each consolidated scan. The blocklist files
# in reports/app/data/ are always protected.
REPORT_RETENTION_DAYS=30
REPORT_RETENTION_MAX_FILES=10
# --- Scan / flagging defaults ----------------------------------------------
# Rows in the top-IP report tables.
DEFAULT_TOP=30
# copyparty: minimum denied hits before flagging an IP.
DEFAULT_MIN_DENIED=1
# npm: minimum error responses before flagging an IP.
DEFAULT_MIN_ERRORS=5
# npm: minimum error ratio before flagging an IP.
DEFAULT_ERROR_RATIO=0.5
# Rows in the "top error paths" report section.
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
+19 -19
View File
@@ -1,20 +1,20 @@
# instructions for agents
.github/instructions/
.agents
skills-lock.json
# environment variables
.env
# python cache
__pycache__/
# incremental-scan state (regenerated each run)
data/scan_state.json
# reports data
reports/copyparty/
reports/mikrotik/
reports/npm/
# timestamped app blocklist change reports (reports/app/data/ stays tracked)
# instructions for agents
.github/instructions/
.agents
skills-lock.json
# environment variables
.env
# python cache
__pycache__/
# incremental-scan state (regenerated each run)
data/scan_state.json
# reports data
reports/copyparty/
reports/mikrotik/
reports/npm/
# timestamped app blocklist change reports (reports/app/data/ stays tracked)
reports/app/*.json
+13
View File
@@ -142,6 +142,19 @@ production can set the same variables via the OS and skip `.env` entirely.
See `.env.example` for the complete list of supported variables (WHOIS
tuning, scan thresholds, whitelist source URLs, and more).
### Network context (2026-09-08)
Connectivity provider switched Openfactory → Init7 on 2026-09-08:
- WAN IPv4: `77.74.80.159/32` (init7 `77.74.80.0/24`, "Hybrid7-NET").
- IPv6: delegated `/48` `2001:1620:549f::/48` (init7 allocation `2001:1620::/30`).
- Upstream DNS: `77.109.128.2`, `213.144.129.20`.
The `Openfactory` whitelist (old AS58299 geofeed) is obsolete and must be
replaced with an `Init7` whitelist — see
[`.github/instructions/TODO.md`](.github/instructions/TODO.md) for the
switchover plan and the verified init7 CIDR ranges.
## Usage
```powershell
+55 -55
View File
@@ -1,55 +1,55 @@
#!/usr/bin/env python3
"""Intrusion Detection System — unified entry point.
By default this starts the localhost-only Flask web UI. Pass ``scan`` to
run the consolidated CLI scan instead.
Usage:
python app.py # start the web UI (default)
python app.py --web-port 54666 # web UI with a custom port
python app.py scan [options] # run the consolidated CLI scan
"""
from __future__ import annotations
import argparse
import sys
from app.utils.constants import WEB_HOST, WEB_PORT
def _web_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="app.py",
description="Intrusion Detection System: web UI (default) or 'scan' subcommand.",
)
parser.add_argument("--web-host", default=WEB_HOST,
help=f"web UI bind host (default: {WEB_HOST})")
parser.add_argument("--web-port", type=int, default=WEB_PORT,
help=f"web UI port (default: {WEB_PORT})")
return parser
def _run_web(host: str, port: int) -> None:
from app.web import serve
serve(host=host, port=port)
def _run_scan(argv: list[str]) -> None:
from app.scan import main as scan_main
scan_main(argv)
def main() -> None:
# `python app.py scan ...` runs the consolidated CLI scan.
if len(sys.argv) > 1 and sys.argv[1] == "scan":
_run_scan(sys.argv[2:])
return
# Default: start the web UI (parse_known_args tolerates stray flags).
args, _ = _web_parser().parse_known_args()
_run_web(args.web_host, args.web_port)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Intrusion Detection System — unified entry point.
By default this starts the localhost-only Flask web UI. Pass ``scan`` to
run the consolidated CLI scan instead.
Usage:
python app.py # start the web UI (default)
python app.py --web-port 54666 # web UI with a custom port
python app.py scan [options] # run the consolidated CLI scan
"""
from __future__ import annotations
import argparse
import sys
from app.utils.constants import WEB_HOST, WEB_PORT
def _web_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="app.py",
description="Intrusion Detection System: web UI (default) or 'scan' subcommand.",
)
parser.add_argument("--web-host", default=WEB_HOST,
help=f"web UI bind host (default: {WEB_HOST})")
parser.add_argument("--web-port", type=int, default=WEB_PORT,
help=f"web UI port (default: {WEB_PORT})")
return parser
def _run_web(host: str, port: int) -> None:
from app.web import serve
serve(host=host, port=port)
def _run_scan(argv: list[str]) -> None:
from app.scan import main as scan_main
scan_main(argv)
def main() -> None:
# `python app.py scan ...` runs the consolidated CLI scan.
if len(sys.argv) > 1 and sys.argv[1] == "scan":
_run_scan(sys.argv[2:])
return
# Default: start the web UI (parse_known_args tolerates stray flags).
args, _ = _web_parser().parse_known_args()
_run_web(args.web_host, args.web_port)
if __name__ == "__main__":
main()
+9 -9
View File
@@ -1,9 +1,9 @@
# Intrusion Detection System — app package
#
# Package structure:
# app/ core domain (analyzers, firewall, detection rules)
# app/web/ Flask web UI (app factory, routes, background scan runner)
# app/scan/ consolidated scan pipeline + incremental scan state
# app/utils/ shared utilities (constants, I/O, models, whitelists, etc.)
# app/static/ static assets (CSS, JS)
# app/templates/ Jinja2 templates
# Intrusion Detection System — app package
#
# Package structure:
# app/ core domain (analyzers, firewall, detection rules)
# app/web/ Flask web UI (app factory, routes, background scan runner)
# app/scan/ consolidated scan pipeline + incremental scan state
# app/utils/ shared utilities (constants, I/O, models, whitelists, etc.)
# app/static/ static assets (CSS, JS)
# app/templates/ Jinja2 templates
+290 -290
View File
@@ -1,290 +1,290 @@
#!/usr/bin/env python3
"""Analysis pipeline for the intrusion-detection system.
`Analyzer` is the log-source-agnostic base class. Subclasses implement
`parse_line()` and `flag()`.
"""
from __future__ import annotations
import os
import re
from collections import Counter
from datetime import datetime
from typing import Any, Sequence
from .utils.files import ensure_dirs, find_logs, read_lines, read_lines_from, validate_dir, write_csv, write_json, write_lines
from .flags import by_total, flag_malicious_patterns
from .utils.ip_utils import is_whitelisted, split_versions
from .mikrotik import write_mikrotik
from .utils.models import IPStats, Request, aggregate
from .utils.reporting import Column, columns_header, columns_row, render_kv, render_table, timestamp_name
from .utils.constants import DEFAULT_TOP, DEFAULT_TOP_PATHS
from .scan import scan_state
from .utils.whitelists import refresh_whitelists
class Analyzer:
"""Log-source-agnostic analysis pipeline.
Subclasses must set the class attributes below and implement
`parse_line()` and `flag()`.
"""
name = "ids" # short id, used in file names / tags
title = "IDS log analysis report"
log_pattern: re.Pattern | None = None
log_suffixes: tuple[str, ...] = ()
exclude_prefixes: tuple[str, ...] = ()
ip_columns: Sequence[Column] = ()
request_columns: Sequence[Column] = ()
paths_file = "error_paths.csv"
paths_label = "error paths"
flag_files = ("flagged_ips.txt", "flagged_ipv6.txt")
flag_label = "Flagged IPs"
flag_note = ""
def __init__(self, log_path: str, report_dir: str, top: int = DEFAULT_TOP,
quiet: bool = False, write_rsc: bool = True,
full: bool = False):
self.log_path = log_path
self.report_dir = report_dir
self.data_dir = os.path.join(report_dir, "data")
self.top = top
self.quiet = quiet
self.write_rsc = write_rsc
self.full = full
self.files: list[str] = []
self.requests: list[Request] = []
self.stats: dict[str, IPStats] = {}
self.flagged: dict[str, IPStats] = {}
self.per_file: dict[str, int] = {}
# --- hooks -------------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
raise NotImplementedError
def flag(self, stats: dict[str, IPStats]) -> dict[str, IPStats]:
raise NotImplementedError
def flag_comment(self, s: IPStats) -> str:
return (f"errors={s.errors} total={s.total} ratio={s.error_ratio} "
f"first={s.first} last={s.last}")
def block_candidates(self) -> set[str]:
malicious = flag_malicious_patterns(self.stats)
return set(self.flagged) | set(malicious)
def extra_summary_rows(self) -> list[tuple[str, Any]]:
return []
def write_extra(self, data_dir: str) -> list[str]:
return []
# --- pipeline ----------------------------------------------------------
def discover(self) -> list[str]:
self.files = find_logs(self.log_path, self.log_pattern,
self.log_suffixes, self.exclude_prefixes)
if not self.files:
raise FileNotFoundError(f"no log files found in: {self.log_path}")
return self.files
def load(self) -> list[Request]:
"""Read log entries, resuming from the last processed offset.
Non-gzip logs are read incrementally (only new bytes since the last
scan) unless ``full`` is set; gzip archives are always fully read
because they cannot be seeked.
"""
state: dict[str, int] = {}
if not self.full:
state = scan_state.load_state()
# Prune entries whose log file no longer exists (safe across
# analyzers: only removes dead keys, keeps live ones).
state = {k: v for k, v in state.items() if os.path.exists(k)}
for name in self.files:
full_path = os.path.join(self.log_path, name)
count = 0
if self.full or full_path.endswith(".gz"):
for line in read_lines(full_path):
req = self.parse_line(line)
if req is not None:
self.requests.append(req)
count += 1
else:
try:
size = os.path.getsize(full_path)
except OSError:
size = 0
recorded = state.get(full_path, 0)
# Reset to the start if the file shrank or was truncated.
start = recorded if 0 < recorded <= size else 0
last_resume = start
for line, resume in read_lines_from(full_path, start):
req = self.parse_line(line)
if req is not None:
self.requests.append(req)
count += 1
last_resume = resume
state[full_path] = last_resume
self.per_file[name] = count
if not self.full:
scan_state.save_state(state)
return self.requests
def analyze(self) -> dict[str, IPStats]:
self.stats = aggregate(self.requests)
self.flagged = self.flag(self.stats)
return self.stats
# --- derived data ------------------------------------------------------
def error_paths(self) -> Counter:
return Counter(r.path for r in self.requests if r.is_error and r.path)
def flagged_split(self) -> tuple[list[IPStats], list[IPStats]]:
v4 = [s for s in self.flagged.values() if s.version == 4]
v6 = [s for s in self.flagged.values() if s.version == 6]
def key(s): return (-s.errors, s.ip)
return sorted(v4, key=key), sorted(v6, key=key)
def summary_rows(self) -> list[tuple[str, Any]]:
v4, v6 = split_versions(self.stats)
rows = [
("log path", self.log_path),
("log files", len(self.files)),
("total requests", len(self.requests)),
("unique IPs",
f"{len(self.stats)} (IPv4 {len(v4)} / IPv6 {len(v6)})"),
("error requests", sum(1 for r in self.requests if r.is_error)),
(f"unique {self.paths_label}", len(self.error_paths())),
]
rows += self.extra_summary_rows()
rows += [
(self.flag_label.lower(), len(self.flagged)),
("whitelisted IPs seen",
sum(1 for ip in self.stats if is_whitelisted(ip))),
("block candidates", len(self.block_candidates())),
]
return rows
# --- reporting ---------------------------------------------------------
def text_report(self) -> str:
out = [self.title,
f"generated: {datetime.now().isoformat(timespec='seconds')}",
"",
render_kv(self.summary_rows()), ""]
out.append(f"== top {self.top} IPs ==")
rows = [columns_row(self.ip_columns, s)
for s in by_total(self.stats)[:self.top]]
out.append(render_table(columns_header(self.ip_columns), rows))
if len(self.stats) > self.top:
out.append(f"... {len(self.stats) - self.top} more IPs omitted")
out.append("")
out.append(f"== top {DEFAULT_TOP_PATHS} {self.paths_label} ==")
for path, n in self.error_paths().most_common(DEFAULT_TOP_PATHS):
out.append(f" {n:>5} {path}")
out.append("")
v4, v6 = self.flagged_split()
out.append(f"== {self.flag_label} ({len(self.flagged)}) ==")
if self.flag_note:
out.append(self.flag_note)
for label, group in (("IPv4", v4), ("IPv6", v6)):
if not group:
continue
out.append(f"-- {label} ({len(group)}) --")
rows = [columns_row(self.ip_columns, s) for s in group]
out.append(render_table(columns_header(self.ip_columns), rows))
out.append("")
return "\n".join(out)
# --- writing -----------------------------------------------------------
def write_data(self) -> list[str]:
ensure_dirs(self.report_dir, self.data_dir)
written: list[str] = []
d = self.data_dir
header = columns_header(self.ip_columns)
ordered = by_total(self.stats)
for version, fname in ((4, "ips_ipv4.csv"), (6, "ips_ipv6.csv")):
rows = [columns_row(self.ip_columns, s)
for s in ordered if s.version == version]
written.append(write_csv(os.path.join(d, fname), header, rows))
written.append(write_json(
os.path.join(d, "ips.json"),
{s.ip: s.to_dict() for s in ordered}))
written.append(write_csv(
os.path.join(d, self.paths_file), ["path", "count"],
self.error_paths().most_common()))
v4, v6 = self.flagged_split()
for group, fname in zip((v4, v6), self.flag_files):
written.append(write_lines(
os.path.join(d, fname),
[f"{s.ip} # {self.flag_comment(s)}" for s in group]))
blocked_v4, blocked_v6 = split_versions(
ip for ip in self.block_candidates() if not is_whitelisted(ip))
written.append(write_lines(
os.path.join(d, "blocked_ipv4.txt"), blocked_v4))
written.append(write_lines(
os.path.join(d, "blocked_ipv6.txt"), blocked_v6))
written.append(write_csv(
os.path.join(d, "requests.csv"),
columns_header(self.request_columns),
(columns_row(self.request_columns, r) for r in self.requests)))
written += self.write_extra(d)
return written
def write_report(self) -> str:
ensure_dirs(self.report_dir)
path = os.path.join(self.report_dir, f"{timestamp_name()}.txt")
with open(path, "w", encoding="utf-8") as f:
f.write(self.text_report())
return path
def write_rsc_file(self) -> tuple[str, int, int]:
ensure_dirs(self.data_dir)
return write_mikrotik(
os.path.join(self.data_dir, "mikrotik-block.rsc"),
f"{self.name}-ids", self.block_candidates())
# --- entrypoint --------------------------------------------------------
def run(self) -> dict[str, Any]:
validate_dir(self.log_path)
ensure_dirs(self.report_dir, self.data_dir)
refresh_whitelists()
self.discover()
self.load()
self.analyze()
if not self.quiet:
print(self.text_report())
self.write_data()
report_path = self.write_report()
print(f"data files: {self.data_dir}")
print(f"summary report: {report_path}")
result: dict[str, Any] = {"report": report_path,
"data_dir": self.data_dir}
if self.write_rsc:
rsc, n_blocked, n_whitelisted = self.write_rsc_file()
print(f"mikrotik script: {rsc}")
print(f" {n_blocked} IPs blocked, "
f"{n_whitelisted} CIDR ranges whitelisted")
result.update(rsc=rsc, blocked=n_blocked,
whitelisted=n_whitelisted)
return result
#!/usr/bin/env python3
"""Analysis pipeline for the intrusion-detection system.
`Analyzer` is the log-source-agnostic base class. Subclasses implement
`parse_line()` and `flag()`.
"""
from __future__ import annotations
import os
import re
from collections import Counter
from datetime import datetime
from typing import Any, Sequence
from .utils.files import ensure_dirs, find_logs, read_lines, read_lines_from, validate_dir, write_csv, write_json, write_lines
from .flags import by_total, flag_malicious_patterns
from .utils.ip_utils import is_whitelisted, split_versions
from .mikrotik import write_mikrotik
from .utils.models import IPStats, Request, aggregate
from .utils.reporting import Column, columns_header, columns_row, render_kv, render_table, timestamp_name
from .utils.constants import DEFAULT_TOP, DEFAULT_TOP_PATHS
from .scan import scan_state
from .utils.whitelists import refresh_whitelists
class Analyzer:
"""Log-source-agnostic analysis pipeline.
Subclasses must set the class attributes below and implement
`parse_line()` and `flag()`.
"""
name = "ids" # short id, used in file names / tags
title = "IDS log analysis report"
log_pattern: re.Pattern | None = None
log_suffixes: tuple[str, ...] = ()
exclude_prefixes: tuple[str, ...] = ()
ip_columns: Sequence[Column] = ()
request_columns: Sequence[Column] = ()
paths_file = "error_paths.csv"
paths_label = "error paths"
flag_files = ("flagged_ips.txt", "flagged_ipv6.txt")
flag_label = "Flagged IPs"
flag_note = ""
def __init__(self, log_path: str, report_dir: str, top: int = DEFAULT_TOP,
quiet: bool = False, write_rsc: bool = True,
full: bool = False):
self.log_path = log_path
self.report_dir = report_dir
self.data_dir = os.path.join(report_dir, "data")
self.top = top
self.quiet = quiet
self.write_rsc = write_rsc
self.full = full
self.files: list[str] = []
self.requests: list[Request] = []
self.stats: dict[str, IPStats] = {}
self.flagged: dict[str, IPStats] = {}
self.per_file: dict[str, int] = {}
# --- hooks -------------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
raise NotImplementedError
def flag(self, stats: dict[str, IPStats]) -> dict[str, IPStats]:
raise NotImplementedError
def flag_comment(self, s: IPStats) -> str:
return (f"errors={s.errors} total={s.total} ratio={s.error_ratio} "
f"first={s.first} last={s.last}")
def block_candidates(self) -> set[str]:
malicious = flag_malicious_patterns(self.stats)
return set(self.flagged) | set(malicious)
def extra_summary_rows(self) -> list[tuple[str, Any]]:
return []
def write_extra(self, data_dir: str) -> list[str]:
return []
# --- pipeline ----------------------------------------------------------
def discover(self) -> list[str]:
self.files = find_logs(self.log_path, self.log_pattern,
self.log_suffixes, self.exclude_prefixes)
if not self.files:
raise FileNotFoundError(f"no log files found in: {self.log_path}")
return self.files
def load(self) -> list[Request]:
"""Read log entries, resuming from the last processed offset.
Non-gzip logs are read incrementally (only new bytes since the last
scan) unless ``full`` is set; gzip archives are always fully read
because they cannot be seeked.
"""
state: dict[str, int] = {}
if not self.full:
state = scan_state.load_state()
# Prune entries whose log file no longer exists (safe across
# analyzers: only removes dead keys, keeps live ones).
state = {k: v for k, v in state.items() if os.path.exists(k)}
for name in self.files:
full_path = os.path.join(self.log_path, name)
count = 0
if self.full or full_path.endswith(".gz"):
for line in read_lines(full_path):
req = self.parse_line(line)
if req is not None:
self.requests.append(req)
count += 1
else:
try:
size = os.path.getsize(full_path)
except OSError:
size = 0
recorded = state.get(full_path, 0)
# Reset to the start if the file shrank or was truncated.
start = recorded if 0 < recorded <= size else 0
last_resume = start
for line, resume in read_lines_from(full_path, start):
req = self.parse_line(line)
if req is not None:
self.requests.append(req)
count += 1
last_resume = resume
state[full_path] = last_resume
self.per_file[name] = count
if not self.full:
scan_state.save_state(state)
return self.requests
def analyze(self) -> dict[str, IPStats]:
self.stats = aggregate(self.requests)
self.flagged = self.flag(self.stats)
return self.stats
# --- derived data ------------------------------------------------------
def error_paths(self) -> Counter:
return Counter(r.path for r in self.requests if r.is_error and r.path)
def flagged_split(self) -> tuple[list[IPStats], list[IPStats]]:
v4 = [s for s in self.flagged.values() if s.version == 4]
v6 = [s for s in self.flagged.values() if s.version == 6]
def key(s): return (-s.errors, s.ip)
return sorted(v4, key=key), sorted(v6, key=key)
def summary_rows(self) -> list[tuple[str, Any]]:
v4, v6 = split_versions(self.stats)
rows = [
("log path", self.log_path),
("log files", len(self.files)),
("total requests", len(self.requests)),
("unique IPs",
f"{len(self.stats)} (IPv4 {len(v4)} / IPv6 {len(v6)})"),
("error requests", sum(1 for r in self.requests if r.is_error)),
(f"unique {self.paths_label}", len(self.error_paths())),
]
rows += self.extra_summary_rows()
rows += [
(self.flag_label.lower(), len(self.flagged)),
("whitelisted IPs seen",
sum(1 for ip in self.stats if is_whitelisted(ip))),
("block candidates", len(self.block_candidates())),
]
return rows
# --- reporting ---------------------------------------------------------
def text_report(self) -> str:
out = [self.title,
f"generated: {datetime.now().isoformat(timespec='seconds')}",
"",
render_kv(self.summary_rows()), ""]
out.append(f"== top {self.top} IPs ==")
rows = [columns_row(self.ip_columns, s)
for s in by_total(self.stats)[:self.top]]
out.append(render_table(columns_header(self.ip_columns), rows))
if len(self.stats) > self.top:
out.append(f"... {len(self.stats) - self.top} more IPs omitted")
out.append("")
out.append(f"== top {DEFAULT_TOP_PATHS} {self.paths_label} ==")
for path, n in self.error_paths().most_common(DEFAULT_TOP_PATHS):
out.append(f" {n:>5} {path}")
out.append("")
v4, v6 = self.flagged_split()
out.append(f"== {self.flag_label} ({len(self.flagged)}) ==")
if self.flag_note:
out.append(self.flag_note)
for label, group in (("IPv4", v4), ("IPv6", v6)):
if not group:
continue
out.append(f"-- {label} ({len(group)}) --")
rows = [columns_row(self.ip_columns, s) for s in group]
out.append(render_table(columns_header(self.ip_columns), rows))
out.append("")
return "\n".join(out)
# --- writing -----------------------------------------------------------
def write_data(self) -> list[str]:
ensure_dirs(self.report_dir, self.data_dir)
written: list[str] = []
d = self.data_dir
header = columns_header(self.ip_columns)
ordered = by_total(self.stats)
for version, fname in ((4, "ips_ipv4.csv"), (6, "ips_ipv6.csv")):
rows = [columns_row(self.ip_columns, s)
for s in ordered if s.version == version]
written.append(write_csv(os.path.join(d, fname), header, rows))
written.append(write_json(
os.path.join(d, "ips.json"),
{s.ip: s.to_dict() for s in ordered}))
written.append(write_csv(
os.path.join(d, self.paths_file), ["path", "count"],
self.error_paths().most_common()))
v4, v6 = self.flagged_split()
for group, fname in zip((v4, v6), self.flag_files):
written.append(write_lines(
os.path.join(d, fname),
[f"{s.ip} # {self.flag_comment(s)}" for s in group]))
blocked_v4, blocked_v6 = split_versions(
ip for ip in self.block_candidates() if not is_whitelisted(ip))
written.append(write_lines(
os.path.join(d, "blocked_ipv4.txt"), blocked_v4))
written.append(write_lines(
os.path.join(d, "blocked_ipv6.txt"), blocked_v6))
written.append(write_csv(
os.path.join(d, "requests.csv"),
columns_header(self.request_columns),
(columns_row(self.request_columns, r) for r in self.requests)))
written += self.write_extra(d)
return written
def write_report(self) -> str:
ensure_dirs(self.report_dir)
path = os.path.join(self.report_dir, f"{timestamp_name()}.txt")
with open(path, "w", encoding="utf-8") as f:
f.write(self.text_report())
return path
def write_rsc_file(self) -> tuple[str, int, int]:
ensure_dirs(self.data_dir)
return write_mikrotik(
os.path.join(self.data_dir, "mikrotik-block.rsc"),
f"{self.name}-ids", self.block_candidates())
# --- entrypoint --------------------------------------------------------
def run(self) -> dict[str, Any]:
validate_dir(self.log_path)
ensure_dirs(self.report_dir, self.data_dir)
refresh_whitelists()
self.discover()
self.load()
self.analyze()
if not self.quiet:
print(self.text_report())
self.write_data()
report_path = self.write_report()
print(f"data files: {self.data_dir}")
print(f"summary report: {report_path}")
result: dict[str, Any] = {"report": report_path,
"data_dir": self.data_dir}
if self.write_rsc:
rsc, n_blocked, n_whitelisted = self.write_rsc_file()
print(f"mikrotik script: {rsc}")
print(f" {n_blocked} IPs blocked, "
f"{n_whitelisted} CIDR ranges whitelisted")
result.update(rsc=rsc, blocked=n_blocked,
whitelisted=n_whitelisted)
return result
+190 -190
View File
@@ -1,190 +1,190 @@
#!/usr/bin/env python3
"""Malicious-pattern detection rules for the intrusion-detection system.
Defines compiled regex patterns and classifiers that identify
probing/scanning URLs (e.g. env files, wp-admin, webshells) and
suspicious file names. Imported by analyzers to flag IPs hitting
these patterns as blocklist candidates.
"""
from __future__ import annotations
import re
from dataclasses import dataclass, field
from typing import ClassVar, Pattern
# ---------------------------------------------------------------------------
# Pattern categories
# ---------------------------------------------------------------------------
@dataclass(frozen=True)
class BadPattern:
"""A single detection rule.
Attributes:
name: Short identifier (e.g. "env_file", "wp_admin").
label: Human-readable description for reports.
regex: Compiled regex matched against the request path.
severity: 1 = moderate, 2 = high, 3 = critical (auto-block).
"""
name: str
label: str
regex: Pattern[str]
severity: int = 2
def matches(self, path: str) -> bool:
return bool(self.regex.search(path))
# ---------------------------------------------------------------------------
# Compiled pattern bank
# ---------------------------------------------------------------------------
# -- env / config file probes -------------------------------------------------
ENV_FILE = BadPattern(
"env_file",
"env/config file probe (.env, .aws/credentials, config.json)",
re.compile(
r"/\.(?:env|config)(?:\.\w+)*|"
r"/\.aws/credentials|"
r"/config\.json",
re.IGNORECASE,
),
severity=3,
)
# -- version control probes ---------------------------------------------------
VCS_PROBE = BadPattern(
"vcs_probe",
"version-control probe (.git, .svn)",
re.compile(
r"/\.(?:git|svn)(?:/|$)",
re.IGNORECASE,
),
severity=3,
)
# -- WordPress / CMS probes ---------------------------------------------------
WP_PROBE = BadPattern(
"wp_probe",
"WordPress/CMS probe (wp-admin, wp-login, wp-content, wp-includes)",
re.compile(
r"/wp-(?:admin|login|content|includes|load|cron|xmlrpc)(?:/|\.php)",
re.IGNORECASE,
),
severity=2,
)
# -- well-known / common probe paths ------------------------------------------
WELL_KNOWN_PROBE = BadPattern(
"well_known_probe",
".well-known probe",
re.compile(
r"/\.well-known/",
re.IGNORECASE,
),
severity=1,
)
# -- webshell / backdoor probes -----------------------------------------------
WEBSHELL_PROBE = BadPattern(
"webshell_probe",
"webshell/backdoor probe (known shell filenames, phpinfo, file managers)",
re.compile(
r"/(?:"
r"phpinfo|info|shell|cmd|upload|"
r"wp_filemanager|filemanager|"
r"xstelth|adminfuns|hellopress|"
r"fpwch|crgio|coffexium|"
r"ccou|biufile|"
r"ms-edit|classwithtostring|"
r"this_is_a_new_hello_world|"
r"chosen|ops|simple|inputs"
r")\.php",
re.IGNORECASE,
),
severity=3,
)
# -- suspicious generic PHP file requests -------------------------------------
GENERIC_PHP_PROBE = BadPattern(
"generic_php_probe",
"generic/random PHP file probe (single-char, numeric names)",
re.compile(
r"/(?:"
r"[a-z]\.php|" # single letter: a.php, k.php, x.php
r"\d{1,3}\.php|" # numeric: 1.php, 222.php, 155.php
r"[a-z]{2}\.php|" # two-letter: aa.php, dx.php
r"a\d\.php|" # a1.php
r"\w+\.php" # generic: anything.php
r")",
re.IGNORECASE,
),
severity=1,
)
# -- sensitive file probes ----------------------------------------------------
SENSITIVE_FILE = BadPattern(
"sensitive_file",
"sensitive file probe (id_rsa, id_dsa, .pem, .key)",
re.compile(
r"/(?:id_rsa|id_dsa|id_ecdsa|id_ed25519|.*\.(?:pem|key|ppk|pfx|p12))",
re.IGNORECASE,
),
severity=3,
)
# -- suspicious user-agent (optional, path-based only for now) -----------------
# ---------------------------------------------------------------------------
# All active patterns (ordered by severity, highest first)
# ---------------------------------------------------------------------------
ALL_PATTERNS: list[BadPattern] = [
ENV_FILE,
VCS_PROBE,
SENSITIVE_FILE,
WEBSHELL_PROBE,
WP_PROBE,
GENERIC_PHP_PROBE,
WELL_KNOWN_PROBE,
]
# Quick lookup by name
PATTERNS_BY_NAME: dict[str, BadPattern] = {p.name: p for p in ALL_PATTERNS}
# ---------------------------------------------------------------------------
# Classification API
# ---------------------------------------------------------------------------
def classify_path(path: str) -> list[BadPattern]:
"""Return all patterns that match a given request path."""
return [p for p in ALL_PATTERNS if p.matches(path)]
def is_malicious(path: str) -> bool:
"""Return True if any pattern matches the path."""
return any(p.matches(path) for p in ALL_PATTERNS)
def malicious_severity(path: str) -> int:
"""Return the highest severity among matching patterns, or 0 if none."""
matched = classify_path(path)
return max((p.severity for p in matched), default=0)
def pattern_names(path: str) -> list[str]:
"""Return names of all patterns matching the path."""
return [p.name for p in classify_path(path)]
#!/usr/bin/env python3
"""Malicious-pattern detection rules for the intrusion-detection system.
Defines compiled regex patterns and classifiers that identify
probing/scanning URLs (e.g. env files, wp-admin, webshells) and
suspicious file names. Imported by analyzers to flag IPs hitting
these patterns as blocklist candidates.
"""
from __future__ import annotations
import re
from dataclasses import dataclass, field
from typing import ClassVar, Pattern
# ---------------------------------------------------------------------------
# Pattern categories
# ---------------------------------------------------------------------------
@dataclass(frozen=True)
class BadPattern:
"""A single detection rule.
Attributes:
name: Short identifier (e.g. "env_file", "wp_admin").
label: Human-readable description for reports.
regex: Compiled regex matched against the request path.
severity: 1 = moderate, 2 = high, 3 = critical (auto-block).
"""
name: str
label: str
regex: Pattern[str]
severity: int = 2
def matches(self, path: str) -> bool:
return bool(self.regex.search(path))
# ---------------------------------------------------------------------------
# Compiled pattern bank
# ---------------------------------------------------------------------------
# -- env / config file probes -------------------------------------------------
ENV_FILE = BadPattern(
"env_file",
"env/config file probe (.env, .aws/credentials, config.json)",
re.compile(
r"/\.(?:env|config)(?:\.\w+)*|"
r"/\.aws/credentials|"
r"/config\.json",
re.IGNORECASE,
),
severity=3,
)
# -- version control probes ---------------------------------------------------
VCS_PROBE = BadPattern(
"vcs_probe",
"version-control probe (.git, .svn)",
re.compile(
r"/\.(?:git|svn)(?:/|$)",
re.IGNORECASE,
),
severity=3,
)
# -- WordPress / CMS probes ---------------------------------------------------
WP_PROBE = BadPattern(
"wp_probe",
"WordPress/CMS probe (wp-admin, wp-login, wp-content, wp-includes)",
re.compile(
r"/wp-(?:admin|login|content|includes|load|cron|xmlrpc)(?:/|\.php)",
re.IGNORECASE,
),
severity=2,
)
# -- well-known / common probe paths ------------------------------------------
WELL_KNOWN_PROBE = BadPattern(
"well_known_probe",
".well-known probe",
re.compile(
r"/\.well-known/",
re.IGNORECASE,
),
severity=1,
)
# -- webshell / backdoor probes -----------------------------------------------
WEBSHELL_PROBE = BadPattern(
"webshell_probe",
"webshell/backdoor probe (known shell filenames, phpinfo, file managers)",
re.compile(
r"/(?:"
r"phpinfo|info|shell|cmd|upload|"
r"wp_filemanager|filemanager|"
r"xstelth|adminfuns|hellopress|"
r"fpwch|crgio|coffexium|"
r"ccou|biufile|"
r"ms-edit|classwithtostring|"
r"this_is_a_new_hello_world|"
r"chosen|ops|simple|inputs"
r")\.php",
re.IGNORECASE,
),
severity=3,
)
# -- suspicious generic PHP file requests -------------------------------------
GENERIC_PHP_PROBE = BadPattern(
"generic_php_probe",
"generic/random PHP file probe (single-char, numeric names)",
re.compile(
r"/(?:"
r"[a-z]\.php|" # single letter: a.php, k.php, x.php
r"\d{1,3}\.php|" # numeric: 1.php, 222.php, 155.php
r"[a-z]{2}\.php|" # two-letter: aa.php, dx.php
r"a\d\.php|" # a1.php
r"\w+\.php" # generic: anything.php
r")",
re.IGNORECASE,
),
severity=1,
)
# -- sensitive file probes ----------------------------------------------------
SENSITIVE_FILE = BadPattern(
"sensitive_file",
"sensitive file probe (id_rsa, id_dsa, .pem, .key)",
re.compile(
r"/(?:id_rsa|id_dsa|id_ecdsa|id_ed25519|.*\.(?:pem|key|ppk|pfx|p12))",
re.IGNORECASE,
),
severity=3,
)
# -- suspicious user-agent (optional, path-based only for now) -----------------
# ---------------------------------------------------------------------------
# All active patterns (ordered by severity, highest first)
# ---------------------------------------------------------------------------
ALL_PATTERNS: list[BadPattern] = [
ENV_FILE,
VCS_PROBE,
SENSITIVE_FILE,
WEBSHELL_PROBE,
WP_PROBE,
GENERIC_PHP_PROBE,
WELL_KNOWN_PROBE,
]
# Quick lookup by name
PATTERNS_BY_NAME: dict[str, BadPattern] = {p.name: p for p in ALL_PATTERNS}
# ---------------------------------------------------------------------------
# Classification API
# ---------------------------------------------------------------------------
def classify_path(path: str) -> list[BadPattern]:
"""Return all patterns that match a given request path."""
return [p for p in ALL_PATTERNS if p.matches(path)]
def is_malicious(path: str) -> bool:
"""Return True if any pattern matches the path."""
return any(p.matches(path) for p in ALL_PATTERNS)
def malicious_severity(path: str) -> int:
"""Return the highest severity among matching patterns, or 0 if none."""
matched = classify_path(path)
return max((p.severity for p in matched), default=0)
def pattern_names(path: str) -> list[str]:
"""Return names of all patterns matching the path."""
return [p.name for p in classify_path(path)]
+182 -182
View File
@@ -1,182 +1,182 @@
#!/usr/bin/env python3
"""copyparty access-log analyzer.
Parses copyparty server logs, aggregates per-IP behaviour and flags
"denied-only" clients: IPs that never authenticated and only ever hit
`@* has no access to '...'`. Those plus copyparty's own auto-bans become
the MikroTik block list.
"""
from __future__ import annotations
import os
import re
from .analyzer import Analyzer
from .utils.constants import (
COPYPARTY_LOG_PATH,
COPYPARTY_REPORT_DIR,
DEFAULT_MIN_DENIED,
)
from .utils.ip_utils import split_versions
from .utils.files import write_json, write_lines
from .flags import flag_denied_only
from .utils.models import IPStats, Request
from .utils.utils import arg_parser
# "HH:MM:SS.mmm <ip> <port> LEVEL: message"
# System lines ("hsrv", "root", ...) have no port and are skipped.
LINE_RE = re.compile(
r"^(\d{2}:\d{2}:\d{2}\.\d{3})\s+" # timestamp
r"(\S+)\s+" # ip
r"(\d+)\s+" # port
r"(LOG|WARN|CRIT|BTW|INFO|ERR|DEBUG):\s" # level
r"(.*)$" # message
)
METHOD_RE = re.compile(
r"^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS|PROPFIND|PROPPATCH|MKCOL|"
r"MOVE|COPY|LOCK|UNLOCK)\s+(\S+)(?:\s+@(\S+))?")
DENY_RE = re.compile(r"^@(\S+) has no access to '([^']+)'")
CLIENT_BAN_RE = re.compile(r"client banned")
BAN_SECS_RE = re.compile(r"banned for (\d+) sec")
class CopypartyAnalyzer(Analyzer):
name = "copyparty"
title = "copyparty log analysis report"
log_pattern = re.compile(r"\d{4}-\d{2}-\d{2}\.txt(\.\d+)?$")
paths_file = "denied_paths.csv"
paths_label = "denied paths"
flag_files = ("denied_ips.txt", "denied_ipv6.txt")
flag_label = "Denied-only IPs"
flag_note = "never authenticated -- ban candidates"
ip_columns = (
("ip", lambda s: s.ip),
("total", lambda s: s.total),
("denied", lambda s: s.denied),
("banned", lambda s: s.banned),
("first", lambda s: s.first),
("last", lambda s: s.last),
("users", lambda s: s.users_str),
("whitelist", lambda s: s.whitelist),
)
request_columns = (
("time", lambda r: r.ts),
("ip", lambda r: r.ip),
("port", lambda r: r.extra.get("port")),
("level", lambda r: r.extra.get("level")),
("method", lambda r: r.method),
("path", lambda r: r.path),
("user", lambda r: r.user),
("denied", lambda r: r.denied),
("banned", lambda r: r.banned),
("ban_secs", lambda r: r.extra.get("ban_secs")),
)
def __init__(self, *args, min_denied: int = DEFAULT_MIN_DENIED, **kwargs):
super().__init__(*args, **kwargs)
self.min_denied = min_denied
# --- parsing -----------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
if not line:
return None
m = LINE_RE.match(line)
if not m:
return None
ts, ip, port, level, msg = m.groups()
req = Request(ts=ts, ip=ip, user=None,
extra={"port": int(port), "level": level})
mm = METHOD_RE.match(msg)
if mm:
req.method, req.path, user = mm.groups()
req.user = user or "*"
return req
dm = DENY_RE.match(msg)
if dm:
req.user, req.path = dm.groups()
req.denied = True
return req
if CLIENT_BAN_RE.search(msg):
req.banned = True
bs = BAN_SECS_RE.search(msg)
if bs:
req.extra["ban_secs"] = int(bs.group(1))
return req
bs = BAN_SECS_RE.search(msg)
if bs:
req.banned = True
req.extra["ban_secs"] = int(bs.group(1))
return req
# --- flagging ----------------------------------------------------------
def flag(self, stats):
return flag_denied_only(stats, min_denied=self.min_denied)
def flag_comment(self, s):
return (f"denied={s.denied} total={s.total} "
f"first={s.first} last={s.last}")
def block_candidates(self) -> set[str]:
banned = {ip for ip, s in self.stats.items() if s.banned}
return set(self.flagged) | banned
# --- extras ------------------------------------------------------------
def banned_ips(self) -> dict[str, IPStats]:
return {ip: s for ip, s in self.stats.items() if s.banned}
def authed_users(self) -> dict[str, int]:
counts: dict[str, int] = {}
for r in self.requests:
if r.user and r.user != "*":
counts[r.user] = counts.get(r.user, 0) + 1
return dict(sorted(counts.items(), key=lambda kv: -kv[1]))
def extra_summary_rows(self):
return [("denied requests",
sum(1 for r in self.requests if r.denied)),
("banned IPs", len(self.banned_ips())),
("authenticated users", self.authed_users() or "{}")]
def write_extra(self, data_dir: str) -> list[str]:
v4, v6 = split_versions(self.banned_ips())
return [
write_lines(os.path.join(data_dir, "banned_ips.txt"), v4),
write_lines(os.path.join(data_dir, "banned_ipv6.txt"), v6),
write_json(os.path.join(data_dir, "authed_users.json"),
self.authed_users()),
]
def main() -> None:
parser = arg_parser(
"analyze copyparty logs, flag denied-only IPs, export MikroTik rules",
COPYPARTY_LOG_PATH, COPYPARTY_REPORT_DIR)
parser.add_argument("--min-denied", type=int, default=DEFAULT_MIN_DENIED,
help=f"minimum denied hits before flagging (default: {DEFAULT_MIN_DENIED})")
parser.add_argument("--full", action="store_true",
help="rescan all logs from the start (ignore incremental state)")
args = parser.parse_args()
CopypartyAnalyzer(
log_path=args.log_path,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
min_denied=args.min_denied,
).run()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""copyparty access-log analyzer.
Parses copyparty server logs, aggregates per-IP behaviour and flags
"denied-only" clients: IPs that never authenticated and only ever hit
`@* has no access to '...'`. Those plus copyparty's own auto-bans become
the MikroTik block list.
"""
from __future__ import annotations
import os
import re
from .analyzer import Analyzer
from .utils.constants import (
COPYPARTY_LOG_PATH,
COPYPARTY_REPORT_DIR,
DEFAULT_MIN_DENIED,
)
from .utils.ip_utils import split_versions
from .utils.files import write_json, write_lines
from .flags import flag_denied_only
from .utils.models import IPStats, Request
from .utils.utils import arg_parser
# "HH:MM:SS.mmm <ip> <port> LEVEL: message"
# System lines ("hsrv", "root", ...) have no port and are skipped.
LINE_RE = re.compile(
r"^(\d{2}:\d{2}:\d{2}\.\d{3})\s+" # timestamp
r"(\S+)\s+" # ip
r"(\d+)\s+" # port
r"(LOG|WARN|CRIT|BTW|INFO|ERR|DEBUG):\s" # level
r"(.*)$" # message
)
METHOD_RE = re.compile(
r"^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS|PROPFIND|PROPPATCH|MKCOL|"
r"MOVE|COPY|LOCK|UNLOCK)\s+(\S+)(?:\s+@(\S+))?")
DENY_RE = re.compile(r"^@(\S+) has no access to '([^']+)'")
CLIENT_BAN_RE = re.compile(r"client banned")
BAN_SECS_RE = re.compile(r"banned for (\d+) sec")
class CopypartyAnalyzer(Analyzer):
name = "copyparty"
title = "copyparty log analysis report"
log_pattern = re.compile(r"\d{4}-\d{2}-\d{2}\.txt(\.\d+)?$")
paths_file = "denied_paths.csv"
paths_label = "denied paths"
flag_files = ("denied_ips.txt", "denied_ipv6.txt")
flag_label = "Denied-only IPs"
flag_note = "never authenticated -- ban candidates"
ip_columns = (
("ip", lambda s: s.ip),
("total", lambda s: s.total),
("denied", lambda s: s.denied),
("banned", lambda s: s.banned),
("first", lambda s: s.first),
("last", lambda s: s.last),
("users", lambda s: s.users_str),
("whitelist", lambda s: s.whitelist),
)
request_columns = (
("time", lambda r: r.ts),
("ip", lambda r: r.ip),
("port", lambda r: r.extra.get("port")),
("level", lambda r: r.extra.get("level")),
("method", lambda r: r.method),
("path", lambda r: r.path),
("user", lambda r: r.user),
("denied", lambda r: r.denied),
("banned", lambda r: r.banned),
("ban_secs", lambda r: r.extra.get("ban_secs")),
)
def __init__(self, *args, min_denied: int = DEFAULT_MIN_DENIED, **kwargs):
super().__init__(*args, **kwargs)
self.min_denied = min_denied
# --- parsing -----------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
if not line:
return None
m = LINE_RE.match(line)
if not m:
return None
ts, ip, port, level, msg = m.groups()
req = Request(ts=ts, ip=ip, user=None,
extra={"port": int(port), "level": level})
mm = METHOD_RE.match(msg)
if mm:
req.method, req.path, user = mm.groups()
req.user = user or "*"
return req
dm = DENY_RE.match(msg)
if dm:
req.user, req.path = dm.groups()
req.denied = True
return req
if CLIENT_BAN_RE.search(msg):
req.banned = True
bs = BAN_SECS_RE.search(msg)
if bs:
req.extra["ban_secs"] = int(bs.group(1))
return req
bs = BAN_SECS_RE.search(msg)
if bs:
req.banned = True
req.extra["ban_secs"] = int(bs.group(1))
return req
# --- flagging ----------------------------------------------------------
def flag(self, stats):
return flag_denied_only(stats, min_denied=self.min_denied)
def flag_comment(self, s):
return (f"denied={s.denied} total={s.total} "
f"first={s.first} last={s.last}")
def block_candidates(self) -> set[str]:
banned = {ip for ip, s in self.stats.items() if s.banned}
return set(self.flagged) | banned
# --- extras ------------------------------------------------------------
def banned_ips(self) -> dict[str, IPStats]:
return {ip: s for ip, s in self.stats.items() if s.banned}
def authed_users(self) -> dict[str, int]:
counts: dict[str, int] = {}
for r in self.requests:
if r.user and r.user != "*":
counts[r.user] = counts.get(r.user, 0) + 1
return dict(sorted(counts.items(), key=lambda kv: -kv[1]))
def extra_summary_rows(self):
return [("denied requests",
sum(1 for r in self.requests if r.denied)),
("banned IPs", len(self.banned_ips())),
("authenticated users", self.authed_users() or "{}")]
def write_extra(self, data_dir: str) -> list[str]:
v4, v6 = split_versions(self.banned_ips())
return [
write_lines(os.path.join(data_dir, "banned_ips.txt"), v4),
write_lines(os.path.join(data_dir, "banned_ipv6.txt"), v6),
write_json(os.path.join(data_dir, "authed_users.json"),
self.authed_users()),
]
def main() -> None:
parser = arg_parser(
"analyze copyparty logs, flag denied-only IPs, export MikroTik rules",
COPYPARTY_LOG_PATH, COPYPARTY_REPORT_DIR)
parser.add_argument("--min-denied", type=int, default=DEFAULT_MIN_DENIED,
help=f"minimum denied hits before flagging (default: {DEFAULT_MIN_DENIED})")
parser.add_argument("--full", action="store_true",
help="rescan all logs from the start (ignore incremental state)")
args = parser.parse_args()
CopypartyAnalyzer(
log_path=args.log_path,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
min_denied=args.min_denied,
).run()
if __name__ == "__main__":
main()
+15 -15
View File
@@ -1,15 +1,15 @@
# Data directory for allucanget-ids
This directory contains data files used by the `allucanget-ids` Intrusion Detection System application, including whitelists, blocklists, and other configuration files. The data files are organized into subdirectories for easier management and maintenance.
## Data files
- [whois cache](./whois_cache.json): Local cache of WHOIS queries to reduce network requests and improve performance. The cache is automatically updated when new IP addresses are queried.
- [Cloudflare IPv4 list](./cloudflare/ips-v4.txt): Contains a list of Cloudflare IPv4 addresses from `https://www.cloudflare.com/ips-v4`, used for whitelisting traffic from Cloudflare services.
- [Cloudflare IPv6 list](./cloudflare/ips-v6.txt): Contains a list of Cloudflare IPv6 addresses from `https://www.cloudflare.com/ips-v6`, used for whitelisting traffic from Cloudflare services.
- [MikroTik RouterOS IPv4 Firewall rules](./mikrotik/firewall_ipv4.json): Current MikroTik RouterOS IPv4 firewall rules.
- [MikroTik RouterOS IPv6 Firewall rules](./mikrotik/firewall_ipv6.json): Current MikroTik RouterOS IPv6 firewall rules.
- [MikroTik RouterOS IPv4 address list](./mikrotik/address_list_ipv4.json): Current MikroTik RouterOS IPv4 address list.
- [MikroTik RouterOS IPv6 address list](./mikrotik/address_list_ipv6.json): Current MikroTik RouterOS IPv6 address list.
- [Openfactory Geofeed](./openfactory/geofeed.csv): Contains Openfactory IP addresses and associated geolocation data from `https://openfactory.net/geofeed.csv`. Used for identifying and whitelisting traffic from known Openfactory sources.
- [PaloAlto Scanner IP list](./paloalto/scanner-ips.txt): List of known PaloAlto scanner IP addresses from `https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity`, used for whitelisting traffic from PaloAlto scanners. !NOTE: This list can not be scraped easily (Javascript-based), so it is maintained manually and may be outdated. Please verify the list against the official source if needed.
# Data directory for allucanget-ids
This directory contains data files used by the `allucanget-ids` Intrusion Detection System application, including whitelists, blocklists, and other configuration files. The data files are organized into subdirectories for easier management and maintenance.
## Data files
- [whois cache](./whois_cache.json): Local cache of WHOIS queries to reduce network requests and improve performance. The cache is automatically updated when new IP addresses are queried.
- [Cloudflare IPv4 list](./cloudflare/ips-v4.txt): Contains a list of Cloudflare IPv4 addresses from `https://www.cloudflare.com/ips-v4`, used for whitelisting traffic from Cloudflare services.
- [Cloudflare IPv6 list](./cloudflare/ips-v6.txt): Contains a list of Cloudflare IPv6 addresses from `https://www.cloudflare.com/ips-v6`, used for whitelisting traffic from Cloudflare services.
- [MikroTik RouterOS IPv4 Firewall rules](./mikrotik/firewall_ipv4.json): Current MikroTik RouterOS IPv4 firewall rules.
- [MikroTik RouterOS IPv6 Firewall rules](./mikrotik/firewall_ipv6.json): Current MikroTik RouterOS IPv6 firewall rules.
- [MikroTik RouterOS IPv4 address list](./mikrotik/address_list_ipv4.json): Current MikroTik RouterOS IPv4 address list.
- [MikroTik RouterOS IPv6 address list](./mikrotik/address_list_ipv6.json): Current MikroTik RouterOS IPv6 address list.
- [Openfactory Geofeed](./openfactory/geofeed.csv): **Obsolete since 2026-09-08** (provider switched to Init7). Kept for historical reference; the replacement `Init7` ranges are documented in the switchover plan (`.github/instructions/TODO.md`).
- [PaloAlto Scanner IP list](./paloalto/scanner-ips.txt): List of known PaloAlto scanner IP addresses from `https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity`, used for whitelisting traffic from PaloAlto scanners. !NOTE: This list can not be scraped easily (Javascript-based), so it is maintained manually and may be outdated. Please verify the list against the official source if needed.
+1 -1
View File
@@ -1 +1 @@
$ = cloudflare
$ = cloudflare
+14 -14
View File
@@ -1,15 +1,15 @@
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22
+6 -6
View File
@@ -1,7 +1,7 @@
2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2c0f:f248::/32
File diff suppressed because it is too large. Load diff
+383 -383
View File
@@ -1,384 +1,384 @@
[
{
"address": "::/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::1/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "fec0::/10",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::ffff:0.0.0.0/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "100::/64",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:db8::/32",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:10::/28",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "3ffe::/16",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2a0e:8f04::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f05::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f06::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f07::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2080::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:67c:2648::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:200::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:600::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:800::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2400:cb00::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2606:4700::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2803:f800::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:b500::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:8100::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2a06:98c0::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2c0f:f248::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2604:a940:300:5b6::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:301:225::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:302:118::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2001:4ca0:108:42::24/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:62ff:fe9a:e1c2/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3000::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c09::2000:5cff:fe99:c802/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:53ff:fe31:8c0b/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59:10:a3a::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:2a8:a0dd:1::1012/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000:0:d09:97ab:43b1:a59a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:c300::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:4d/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:88/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:ba0:24c:a500::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:9cff:fef0:8ad6/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59::/40",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:64cc:9116:beb2:1931/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe82:2775/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:4f8:c014:7f9e::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:4400:0:537:cdd2:7250:95db/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a05:4140:3::37cd/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a06:a880:5:7fb3::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac1:76c0:460::5e:6a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a13:adc0::2ed:89ff:fe58:19c5/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:beff:fea3:5a44/128",
"creation-time": "2026-08-05",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-06",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2017:3810::/64",
"comment": "hosting",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:8d8:5ff:5f:82:165:82:154/128",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::/32",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:448a:a071:520:e18f:3d1f:944e:174d/128",
"creation-time": "2026-08-08",
"dynamic": "no",
"list": "Blocked"
}
[
{
"address": "::/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::1/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "fec0::/10",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::ffff:0.0.0.0/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "100::/64",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:db8::/32",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:10::/28",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "3ffe::/16",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2a0e:8f04::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f05::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f06::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f07::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2080::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:67c:2648::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:200::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:600::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:800::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2400:cb00::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2606:4700::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2803:f800::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:b500::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:8100::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2a06:98c0::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2c0f:f248::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2604:a940:300:5b6::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:301:225::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:302:118::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2001:4ca0:108:42::24/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:62ff:fe9a:e1c2/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3000::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c09::2000:5cff:fe99:c802/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:53ff:fe31:8c0b/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59:10:a3a::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:2a8:a0dd:1::1012/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000:0:d09:97ab:43b1:a59a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:c300::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:4d/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:88/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:ba0:24c:a500::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:9cff:fef0:8ad6/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59::/40",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:64cc:9116:beb2:1931/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe82:2775/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:4f8:c014:7f9e::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:4400:0:537:cdd2:7250:95db/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a05:4140:3::37cd/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a06:a880:5:7fb3::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac1:76c0:460::5e:6a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a13:adc0::2ed:89ff:fe58:19c5/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:beff:fea3:5a44/128",
"creation-time": "2026-08-05",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-06",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2017:3810::/64",
"comment": "hosting",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:8d8:5ff:5f:82:165:82:154/128",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::/32",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:448a:a071:520:e18f:3d1f:944e:174d/128",
"creation-time": "2026-08-08",
"dynamic": "no",
"list": "Blocked"
}
]
+136 -136
View File
@@ -1,137 +1,137 @@
[
{
"action": "passthrough",
"chain": "forward",
"comment": "special"
},
{
"action": "fasttrack-connection",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"hw-offload": "yes",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"log": "no",
"log-prefix": ""
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "Allow",
"connection-nat-state": "dstnat"
},
{
"action": "accept",
"chain": "forward",
"comment": "allow",
"connection-state": "new",
"dst-address": "192.168.88.25",
"dst-port": "6667",
"log": "no",
"log-prefix": "",
"protocol": "tcp"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-nat-state": "!dstnat",
"connection-state": "new",
"in-interface-list": "WAN",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"log": "no",
"log-prefix": "",
"protocol": "icmp"
},
{
"action": "accept",
"chain": "input",
"comment": "accept",
"connection-state": "established",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"dst-port": "500",
"protocol": "udp"
},
{
"action": "drop",
"chain": "input",
"comment": "Block",
"dst-port": "80,443",
"in-interface-list": "WAN",
"protocol": "tcp"
},
{
"action": "accept",
"chain": "input",
"comment": "Allow",
"dst-port": "80,443",
"in-interface-list": "LAN",
"protocol": "tcp",
"src-address": "192.168.88.0/24"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "input",
"comment": "drop",
"in-interface": "pppoe-out1",
"log": "no",
"log-prefix": ""
}
[
{
"action": "passthrough",
"chain": "forward",
"comment": "special"
},
{
"action": "fasttrack-connection",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"hw-offload": "yes",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"log": "no",
"log-prefix": ""
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "Allow",
"connection-nat-state": "dstnat"
},
{
"action": "accept",
"chain": "forward",
"comment": "allow",
"connection-state": "new",
"dst-address": "192.168.88.25",
"dst-port": "6667",
"log": "no",
"log-prefix": "",
"protocol": "tcp"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-nat-state": "!dstnat",
"connection-state": "new",
"in-interface-list": "WAN",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"log": "no",
"log-prefix": "",
"protocol": "icmp"
},
{
"action": "accept",
"chain": "input",
"comment": "accept",
"connection-state": "established",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"dst-port": "500",
"protocol": "udp"
},
{
"action": "drop",
"chain": "input",
"comment": "Block",
"dst-port": "80,443",
"in-interface-list": "WAN",
"protocol": "tcp"
},
{
"action": "accept",
"chain": "input",
"comment": "Allow",
"dst-port": "80,443",
"in-interface-list": "LAN",
"protocol": "tcp",
"src-address": "192.168.88.0/24"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "input",
"comment": "drop",
"in-interface": "pppoe-out1",
"log": "no",
"log-prefix": ""
}
]
+185 -185
View File
@@ -1,186 +1,186 @@
[
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"port": "33434-33534",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "546",
"protocol": "udp",
"src-address": "fe80::/10"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"src-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"dst-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"hop-limit": "equal:1",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "ids",
"log": "no",
"log-prefix": "",
"src-address-list": "Openfactory"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"log": "no",
"log-prefix": "",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "139"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
}
[
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"port": "33434-33534",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "546",
"protocol": "udp",
"src-address": "fe80::/10"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"src-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"dst-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"hop-limit": "equal:1",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "ids",
"log": "no",
"log-prefix": "",
"src-address-list": "Openfactory"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"log": "no",
"log-prefix": "",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "139"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
}
]
+1 -1
View File
@@ -1 +1 @@
$ = openfactory
$ = openfactory
+46 -46
View File
@@ -1,46 +1,46 @@
45.11.248.0/23,DE,DE-HE,Frankfurt Am Main,
45.11.250.0/24,NL,NL-NH,Amsterdam,
45.11.251.0/24,AT,AT-9,Vienna,
2a0e:8f04::/32,DE,DE-HE,Frankfurt Am Main,
2a0e:8f05::/32,GB,GB-LND,London,
2a0e:8f06::/32,NL,NL-NH,Amsterdam,
2a0e:8f07::/32,AT,AT-9,Vienna,
5.226.144.0/21,CH,CH-TG,Frauenfeld,
5.226.144.192/26,CH,CH-ZH,Winterthur,
5.226.145.0/26,CH,CH-ZH,Wangen-Bruettisellen,
5.226.145.64/26,LI,LI-07,Schaan,
5.226.145.128/25,CH,CH-ZH,Kloten,
5.226.148.0/29,CH,CH-ZH,Zurich,
5.226.148.8/29,CH,CH-ZH,Kloten,
5.226.148.16/28,CH,CH-ZH,Zurich,
5.226.148.32/27,CH,CH-ZH,Kloten,
5.226.148.64/26,CH,CH-ZH,Zurich,
5.226.148.96/27,CH,CH-ZH,Zurich,
5.226.148.128/25,CH,CH-ZH,Zurich,
5.226.149.0/26,CH,CH-ZH,Zurich,
5.226.149.64/28,CH,CH-LU,Lutzern,
5.226.149.128/26,CH,CH-ZH,Glattfelden,
5.226.149.240/30,CH,CH-SZ,Wollerau,
5.226.150.0/27,CH,CH-ZH,Glattfelden,
5.226.150.32/27,CH,CH-BE,Biel,
5.226.150.152/29,LI,LI-07,Schaan,
5.226.150.160/28,CH,CH-ZH,Winterthur,
5.226.150.224/27,CH,CH-BE,Bern,
5.226.151.0/26,NL,NL-NH,Amsterdam,
5.226.151.64/27,CH,CH-ZH,Ruemlang,
185.86.228.0/23,CH,CH-ZH,Zurich,
195.138.203.0/24,CH,CH-ZH,Zurich,
2a00:6340::/32,CH,CH-TG,Frauenfeld,
2a00:6340:2080::/48,NL,NL-NH,Amsterdam,
2001:67c:2648::/48,CH,CH-ZH,Winterthur,
# Customer geofeed details on request
# Having issues with your geolocation? send us a ticket!
45.11.248.94/32,DE,DE-NW,Dortmund,
2a00:6340:2044:200::/56,DE,DE-NW,Dortmund,
2a00:6340:2044:600::/56,DE,DE-BW,Stuttgart,
45.11.248.96/32,DE,DE-BW,Stuttgart,
45.11.248.37/32,DE,DE-BE,Berlin,
2a00:6340:2044:800::/56,DE,DE-BE,Berlin,
5.226.146.49/32,CH,CH-ZH,Winterthur,8405,47.472502,8.779930
45.11.248.0/23,DE,DE-HE,Frankfurt Am Main,
45.11.250.0/24,NL,NL-NH,Amsterdam,
45.11.251.0/24,AT,AT-9,Vienna,
2a0e:8f04::/32,DE,DE-HE,Frankfurt Am Main,
2a0e:8f05::/32,GB,GB-LND,London,
2a0e:8f06::/32,NL,NL-NH,Amsterdam,
2a0e:8f07::/32,AT,AT-9,Vienna,
5.226.144.0/21,CH,CH-TG,Frauenfeld,
5.226.144.192/26,CH,CH-ZH,Winterthur,
5.226.145.0/26,CH,CH-ZH,Wangen-Bruettisellen,
5.226.145.64/26,LI,LI-07,Schaan,
5.226.145.128/25,CH,CH-ZH,Kloten,
5.226.148.0/29,CH,CH-ZH,Zurich,
5.226.148.8/29,CH,CH-ZH,Kloten,
5.226.148.16/28,CH,CH-ZH,Zurich,
5.226.148.32/27,CH,CH-ZH,Kloten,
5.226.148.64/26,CH,CH-ZH,Zurich,
5.226.148.96/27,CH,CH-ZH,Zurich,
5.226.148.128/25,CH,CH-ZH,Zurich,
5.226.149.0/26,CH,CH-ZH,Zurich,
5.226.149.64/28,CH,CH-LU,Lutzern,
5.226.149.128/26,CH,CH-ZH,Glattfelden,
5.226.149.240/30,CH,CH-SZ,Wollerau,
5.226.150.0/27,CH,CH-ZH,Glattfelden,
5.226.150.32/27,CH,CH-BE,Biel,
5.226.150.152/29,LI,LI-07,Schaan,
5.226.150.160/28,CH,CH-ZH,Winterthur,
5.226.150.224/27,CH,CH-BE,Bern,
5.226.151.0/26,NL,NL-NH,Amsterdam,
5.226.151.64/27,CH,CH-ZH,Ruemlang,
185.86.228.0/23,CH,CH-ZH,Zurich,
195.138.203.0/24,CH,CH-ZH,Zurich,
2a00:6340::/32,CH,CH-TG,Frauenfeld,
2a00:6340:2080::/48,NL,NL-NH,Amsterdam,
2001:67c:2648::/48,CH,CH-ZH,Winterthur,
# Customer geofeed details on request
# Having issues with your geolocation? send us a ticket!
45.11.248.94/32,DE,DE-NW,Dortmund,
2a00:6340:2044:200::/56,DE,DE-NW,Dortmund,
2a00:6340:2044:600::/56,DE,DE-BW,Stuttgart,
45.11.248.96/32,DE,DE-BW,Stuttgart,
45.11.248.37/32,DE,DE-BE,Berlin,
2a00:6340:2044:800::/56,DE,DE-BE,Berlin,
5.226.146.49/32,CH,CH-ZH,Winterthur,8405,47.472502,8.779930
1 45.11.248.0/23 DE DE-HE Frankfurt Am Main
2 45.11.250.0/24 NL NL-NH Amsterdam
3 45.11.251.0/24 AT AT-9 Vienna
4 2a0e:8f04::/32 DE DE-HE Frankfurt Am Main
5 2a0e:8f05::/32 GB GB-LND London
6 2a0e:8f06::/32 NL NL-NH Amsterdam
7 2a0e:8f07::/32 AT AT-9 Vienna
8 5.226.144.0/21 CH CH-TG Frauenfeld
9 5.226.144.192/26 CH CH-ZH Winterthur
10 5.226.145.0/26 CH CH-ZH Wangen-Bruettisellen
11 5.226.145.64/26 LI LI-07 Schaan
12 5.226.145.128/25 CH CH-ZH Kloten
13 5.226.148.0/29 CH CH-ZH Zurich
14 5.226.148.8/29 CH CH-ZH Kloten
15 5.226.148.16/28 CH CH-ZH Zurich
16 5.226.148.32/27 CH CH-ZH Kloten
17 5.226.148.64/26 CH CH-ZH Zurich
18 5.226.148.96/27 CH CH-ZH Zurich
19 5.226.148.128/25 CH CH-ZH Zurich
20 5.226.149.0/26 CH CH-ZH Zurich
21 5.226.149.64/28 CH CH-LU Lutzern
22 5.226.149.128/26 CH CH-ZH Glattfelden
23 5.226.149.240/30 CH CH-SZ Wollerau
24 5.226.150.0/27 CH CH-ZH Glattfelden
25 5.226.150.32/27 CH CH-BE Biel
26 5.226.150.152/29 LI LI-07 Schaan
27 5.226.150.160/28 CH CH-ZH Winterthur
28 5.226.150.224/27 CH CH-BE Bern
29 5.226.151.0/26 NL NL-NH Amsterdam
30 5.226.151.64/27 CH CH-ZH Ruemlang
31 185.86.228.0/23 CH CH-ZH Zurich
32 195.138.203.0/24 CH CH-ZH Zurich
33 2a00:6340::/32 CH CH-TG Frauenfeld
34 2a00:6340:2080::/48 NL NL-NH Amsterdam
35 2001:67c:2648::/48 CH CH-ZH Winterthur
36 # Customer geofeed details on request
37 # Having issues with your geolocation? send us a ticket!
38 45.11.248.94/32 DE DE-NW Dortmund
39 2a00:6340:2044:200::/56 DE DE-NW Dortmund
40 2a00:6340:2044:600::/56 DE DE-BW Stuttgart
41 45.11.248.96/32 DE DE-BW Stuttgart
42 45.11.248.37/32 DE DE-BE Berlin
43 2a00:6340:2044:800::/56 DE DE-BE Berlin
44 5.226.146.49/32 CH CH-ZH Winterthur 8405
45
46
+1 -1
View File
@@ -1 +1 @@
$ = paloalto
$ = paloalto
+11 -11
View File
@@ -1,12 +1,12 @@
35.203.210.0/23
144.86.173.0/24
147.185.132.0/23
162.216.149.0/24
162.216.150.0/24
172.105.147.0/24
198.235.24.0/24
205.210.31.0/24
216.25.88.0/21
2604:a940:300:5b6:0:0:0:0/64
2604:a940:301:225:0:0:0:0/64
35.203.210.0/23
144.86.173.0/24
147.185.132.0/23
162.216.149.0/24
162.216.150.0/24
172.105.147.0/24
198.235.24.0/24
205.210.31.0/24
216.25.88.0/21
2604:a940:300:5b6:0:0:0:0/64
2604:a940:301:225:0:0:0:0/64
2604:a940:302:118:0:0:0:0/64
+10819 -10819
View File
File diff suppressed because it is too large. Load diff
+232 -232
View File
@@ -1,233 +1,233 @@
{
"P:\\copyparty\\2026-07-11.txt": 7403,
"P:\\copyparty\\2026-07-11.txt.1": 84622,
"P:\\copyparty\\2026-07-12.txt": 99031,
"P:\\copyparty\\2026-07-13.txt": 92896,
"P:\\copyparty\\2026-07-14.txt": 191781,
"P:\\copyparty\\2026-07-15.txt": 55394,
"P:\\copyparty\\2026-07-15.txt.1": 8770,
"P:\\copyparty\\2026-07-15.txt.2": 9606,
"P:\\copyparty\\2026-07-16.txt": 35715,
"P:\\copyparty\\2026-07-17.txt": 102469,
"P:\\copyparty\\2026-07-17.txt.1": 35820,
"P:\\copyparty\\2026-07-18.txt": 1784,
"P:\\copyparty\\2026-07-19.txt": 273815,
"P:\\copyparty\\2026-07-20.txt": 572443,
"P:\\copyparty\\2026-07-21.txt": 56055,
"P:\\copyparty\\2026-07-22.txt": 135922,
"P:\\copyparty\\2026-07-23.txt": 2468,
"P:\\copyparty\\2026-07-23.txt.1": 349125,
"P:\\copyparty\\2026-07-23.txt.2": 199809,
"P:\\copyparty\\2026-07-23.txt.3": 1023,
"P:\\copyparty\\2026-07-23.txt.4": 1023,
"P:\\copyparty\\2026-07-23.txt.5": 1041,
"P:\\copyparty\\2026-07-23.txt.6": 114042,
"P:\\copyparty\\2026-07-23.txt.7": 19621,
"P:\\copyparty\\2026-07-23.txt.8": 29806,
"P:\\copyparty\\2026-07-23.txt.9": 15526221,
"P:\\copyparty\\2026-07-24.txt": 99348,
"P:\\copyparty\\2026-07-25.txt": 63410,
"P:\\copyparty\\2026-07-26.txt": 217801,
"P:\\copyparty\\2026-07-27.txt": 66457,
"P:\\copyparty\\2026-07-28.txt": 59236,
"P:\\copyparty\\2026-07-29.txt": 153562,
"P:\\copyparty\\2026-07-29.txt.1": 24147,
"P:\\copyparty\\2026-07-30.txt": 1212354,
"P:\\copyparty\\2026-07-31.txt": 49026,
"P:\\copyparty\\2026-08-01.txt": 298970,
"P:\\copyparty\\2026-08-01.txt.1": 274541,
"P:\\copyparty\\2026-08-02.txt": 45372,
"P:\\copyparty\\2026-08-03.txt": 34302,
"P:\\copyparty\\2026-08-04.txt": 33282,
"P:\\copyparty\\2026-08-05.txt": 75013,
"P:\\copyparty\\2026-08-06.txt": 64948,
"P:\\copyparty\\2026-08-07.txt": 38873,
"Y:\\npm\\logs\\fallback_error.log": 20586,
"Y:\\npm\\logs\\fallback_http_access.log": 1966362,
"Y:\\npm\\logs\\fallback_http_error.log": 2930280,
"Y:\\npm\\logs\\fallback_stream_access.log": 0,
"Y:\\npm\\logs\\proxy-host-10_access.log": 495244,
"Y:\\npm\\logs\\proxy-host-10_error.log": 316,
"Y:\\npm\\logs\\proxy-host-11_access.log": 2618795,
"Y:\\npm\\logs\\proxy-host-11_error.log": 53360,
"Y:\\npm\\logs\\proxy-host-12_access.log": 3171885,
"Y:\\npm\\logs\\proxy-host-12_error.log": 40987,
"Y:\\npm\\logs\\proxy-host-13_access.log": 1032922,
"Y:\\npm\\logs\\proxy-host-13_error.log": 160173,
"Y:\\npm\\logs\\proxy-host-14_access.log": 0,
"Y:\\npm\\logs\\proxy-host-14_error.log": 0,
"Y:\\npm\\logs\\proxy-host-15_access.log": 0,
"Y:\\npm\\logs\\proxy-host-15_error.log": 0,
"Y:\\npm\\logs\\proxy-host-16_access.log": 0,
"Y:\\npm\\logs\\proxy-host-16_error.log": 0,
"Y:\\npm\\logs\\proxy-host-17_access.log": 249525,
"Y:\\npm\\logs\\proxy-host-17_error.log": 45568,
"Y:\\npm\\logs\\proxy-host-18_access.log": 210292,
"Y:\\npm\\logs\\proxy-host-18_error.log": 45944,
"Y:\\npm\\logs\\proxy-host-19_access.log": 56437,
"Y:\\npm\\logs\\proxy-host-19_error.log": 41305,
"Y:\\npm\\logs\\proxy-host-1_access.log": 421346,
"Y:\\npm\\logs\\proxy-host-1_error.log": 46031,
"Y:\\npm\\logs\\proxy-host-20_access.log": 2074017,
"Y:\\npm\\logs\\proxy-host-20_error.log": 50956,
"Y:\\npm\\logs\\proxy-host-21_access.log": 0,
"Y:\\npm\\logs\\proxy-host-21_error.log": 0,
"Y:\\npm\\logs\\proxy-host-22_access.log": 263312,
"Y:\\npm\\logs\\proxy-host-22_error.log": 3733,
"Y:\\npm\\logs\\proxy-host-23_access.log": 4268,
"Y:\\npm\\logs\\proxy-host-23_error.log": 4454,
"Y:\\npm\\logs\\proxy-host-24_access.log": 0,
"Y:\\npm\\logs\\proxy-host-24_error.log": 0,
"Y:\\npm\\logs\\proxy-host-25_access.log": 0,
"Y:\\npm\\logs\\proxy-host-25_error.log": 0,
"Y:\\npm\\logs\\proxy-host-26_access.log": 0,
"Y:\\npm\\logs\\proxy-host-26_error.log": 0,
"Y:\\npm\\logs\\proxy-host-27_access.log": 0,
"Y:\\npm\\logs\\proxy-host-27_error.log": 0,
"Y:\\npm\\logs\\proxy-host-28_access.log": 107302,
"Y:\\npm\\logs\\proxy-host-28_error.log": 116208,
"Y:\\npm\\logs\\proxy-host-29_access.log": 158185,
"Y:\\npm\\logs\\proxy-host-29_error.log": 90709,
"Y:\\npm\\logs\\proxy-host-2_access.log": 0,
"Y:\\npm\\logs\\proxy-host-2_error.log": 0,
"Y:\\npm\\logs\\proxy-host-30_access.log": 0,
"Y:\\npm\\logs\\proxy-host-30_error.log": 0,
"Y:\\npm\\logs\\proxy-host-31_access.log": 3846085,
"Y:\\npm\\logs\\proxy-host-31_error.log": 282448,
"Y:\\npm\\logs\\proxy-host-3_access.log": 658178,
"Y:\\npm\\logs\\proxy-host-3_error.log": 46739,
"Y:\\npm\\logs\\proxy-host-4_access.log": 0,
"Y:\\npm\\logs\\proxy-host-4_error.log": 0,
"Y:\\npm\\logs\\proxy-host-5_access.log": 0,
"Y:\\npm\\logs\\proxy-host-5_error.log": 0,
"Y:\\npm\\logs\\proxy-host-6_access.log": 0,
"Y:\\npm\\logs\\proxy-host-6_error.log": 0,
"Y:\\npm\\logs\\proxy-host-7_access.log": 0,
"Y:\\npm\\logs\\proxy-host-7_error.log": 0,
"Y:\\npm\\logs\\proxy-host-8_access.log": 558598,
"Y:\\npm\\logs\\proxy-host-8_error.log": 45468,
"Y:\\npm\\logs\\proxy-host-9_access.log": 34788693,
"Y:\\npm\\logs\\proxy-host-9_error.log": 292624,
"Y:\\npm\\logs\\stream-1_access.log": 0,
"Y:\\npm\\logs\\stream-1_error.log": 0,
"Y:\\npm\\logs\\stream-2_access.log": 0,
"Y:\\npm\\logs\\stream-2_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_error.log": 2342,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_http_access.log": 444743,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_http_error.log": 507761,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_stream_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-10_access.log": 131738,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-10_error.log": 314,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-11_access.log": 1345373,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-11_error.log": 11526,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-12_access.log": 692484,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-12_error.log": 13649,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-13_access.log": 907343,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-13_error.log": 31479,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-14_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-14_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-15_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-15_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-16_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-16_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-17_access.log": 18521,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-17_error.log": 11333,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-18_access.log": 610146,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-18_error.log": 12622,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-19_access.log": 2708,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-19_error.log": 1937,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-1_access.log": 87903,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-1_error.log": 11003,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-20_access.log": 827861,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-20_error.log": 11032,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-21_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-21_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-22_access.log": 200379,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-22_error.log": 1052,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-23_access.log": 453,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-23_error.log": 525,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-24_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-24_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-25_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-25_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-26_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-26_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-27_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-27_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-28_access.log": 2104,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-28_error.log": 2174,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-29_access.log": 9608,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-29_error.log": 2462,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-2_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-2_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-30_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-30_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-31_access.log": 41817,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-31_error.log": 1547,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-3_access.log": 277282,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-3_error.log": 10645,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-4_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-4_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-5_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-5_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-6_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-6_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-7_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-7_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-8_access.log": 163769,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-8_error.log": 10207,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-9_access.log": 2603446,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-9_error.log": 55751,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-1_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-1_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-2_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-2_error.log": 0,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-11.txt": 7403,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-11.txt.1": 84622,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-12.txt": 99031,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-13.txt": 92896,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-14.txt": 191781,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt": 55394,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt.1": 8770,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt.2": 9606,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-16.txt": 35715,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-17.txt": 102469,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-17.txt.1": 35820,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-18.txt": 1784,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-19.txt": 273815,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-20.txt": 572443,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-21.txt": 56055,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-22.txt": 135922,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt": 2468,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.1": 349125,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.2": 199809,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.3": 1023,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.4": 1023,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.5": 1041,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.6": 114042,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.7": 19621,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.8": 29806,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.9": 15526221,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-24.txt": 99348,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-25.txt": 63410,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-26.txt": 217801,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-27.txt": 66457,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-28.txt": 59236,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-29.txt": 153562,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-29.txt.1": 24147,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-30.txt": 1212354,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-31.txt": 49026,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-01.txt": 298970,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-01.txt.1": 274541,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-02.txt": 45372,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-03.txt": 34302,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-04.txt": 33282,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-05.txt": 75013,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-06.txt": 64948,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-07.txt": 48371,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-08.txt": 39365,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-09.txt": 154216,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-09.txt.1": 12568,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-10.txt": 85753,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-11.txt": 6042
{
"P:\\copyparty\\2026-07-11.txt": 7403,
"P:\\copyparty\\2026-07-11.txt.1": 84622,
"P:\\copyparty\\2026-07-12.txt": 99031,
"P:\\copyparty\\2026-07-13.txt": 92896,
"P:\\copyparty\\2026-07-14.txt": 191781,
"P:\\copyparty\\2026-07-15.txt": 55394,
"P:\\copyparty\\2026-07-15.txt.1": 8770,
"P:\\copyparty\\2026-07-15.txt.2": 9606,
"P:\\copyparty\\2026-07-16.txt": 35715,
"P:\\copyparty\\2026-07-17.txt": 102469,
"P:\\copyparty\\2026-07-17.txt.1": 35820,
"P:\\copyparty\\2026-07-18.txt": 1784,
"P:\\copyparty\\2026-07-19.txt": 273815,
"P:\\copyparty\\2026-07-20.txt": 572443,
"P:\\copyparty\\2026-07-21.txt": 56055,
"P:\\copyparty\\2026-07-22.txt": 135922,
"P:\\copyparty\\2026-07-23.txt": 2468,
"P:\\copyparty\\2026-07-23.txt.1": 349125,
"P:\\copyparty\\2026-07-23.txt.2": 199809,
"P:\\copyparty\\2026-07-23.txt.3": 1023,
"P:\\copyparty\\2026-07-23.txt.4": 1023,
"P:\\copyparty\\2026-07-23.txt.5": 1041,
"P:\\copyparty\\2026-07-23.txt.6": 114042,
"P:\\copyparty\\2026-07-23.txt.7": 19621,
"P:\\copyparty\\2026-07-23.txt.8": 29806,
"P:\\copyparty\\2026-07-23.txt.9": 15526221,
"P:\\copyparty\\2026-07-24.txt": 99348,
"P:\\copyparty\\2026-07-25.txt": 63410,
"P:\\copyparty\\2026-07-26.txt": 217801,
"P:\\copyparty\\2026-07-27.txt": 66457,
"P:\\copyparty\\2026-07-28.txt": 59236,
"P:\\copyparty\\2026-07-29.txt": 153562,
"P:\\copyparty\\2026-07-29.txt.1": 24147,
"P:\\copyparty\\2026-07-30.txt": 1212354,
"P:\\copyparty\\2026-07-31.txt": 49026,
"P:\\copyparty\\2026-08-01.txt": 298970,
"P:\\copyparty\\2026-08-01.txt.1": 274541,
"P:\\copyparty\\2026-08-02.txt": 45372,
"P:\\copyparty\\2026-08-03.txt": 34302,
"P:\\copyparty\\2026-08-04.txt": 33282,
"P:\\copyparty\\2026-08-05.txt": 75013,
"P:\\copyparty\\2026-08-06.txt": 64948,
"P:\\copyparty\\2026-08-07.txt": 38873,
"Y:\\npm\\logs\\fallback_error.log": 20586,
"Y:\\npm\\logs\\fallback_http_access.log": 1966362,
"Y:\\npm\\logs\\fallback_http_error.log": 2930280,
"Y:\\npm\\logs\\fallback_stream_access.log": 0,
"Y:\\npm\\logs\\proxy-host-10_access.log": 495244,
"Y:\\npm\\logs\\proxy-host-10_error.log": 316,
"Y:\\npm\\logs\\proxy-host-11_access.log": 2618795,
"Y:\\npm\\logs\\proxy-host-11_error.log": 53360,
"Y:\\npm\\logs\\proxy-host-12_access.log": 3171885,
"Y:\\npm\\logs\\proxy-host-12_error.log": 40987,
"Y:\\npm\\logs\\proxy-host-13_access.log": 1032922,
"Y:\\npm\\logs\\proxy-host-13_error.log": 160173,
"Y:\\npm\\logs\\proxy-host-14_access.log": 0,
"Y:\\npm\\logs\\proxy-host-14_error.log": 0,
"Y:\\npm\\logs\\proxy-host-15_access.log": 0,
"Y:\\npm\\logs\\proxy-host-15_error.log": 0,
"Y:\\npm\\logs\\proxy-host-16_access.log": 0,
"Y:\\npm\\logs\\proxy-host-16_error.log": 0,
"Y:\\npm\\logs\\proxy-host-17_access.log": 249525,
"Y:\\npm\\logs\\proxy-host-17_error.log": 45568,
"Y:\\npm\\logs\\proxy-host-18_access.log": 210292,
"Y:\\npm\\logs\\proxy-host-18_error.log": 45944,
"Y:\\npm\\logs\\proxy-host-19_access.log": 56437,
"Y:\\npm\\logs\\proxy-host-19_error.log": 41305,
"Y:\\npm\\logs\\proxy-host-1_access.log": 421346,
"Y:\\npm\\logs\\proxy-host-1_error.log": 46031,
"Y:\\npm\\logs\\proxy-host-20_access.log": 2074017,
"Y:\\npm\\logs\\proxy-host-20_error.log": 50956,
"Y:\\npm\\logs\\proxy-host-21_access.log": 0,
"Y:\\npm\\logs\\proxy-host-21_error.log": 0,
"Y:\\npm\\logs\\proxy-host-22_access.log": 263312,
"Y:\\npm\\logs\\proxy-host-22_error.log": 3733,
"Y:\\npm\\logs\\proxy-host-23_access.log": 4268,
"Y:\\npm\\logs\\proxy-host-23_error.log": 4454,
"Y:\\npm\\logs\\proxy-host-24_access.log": 0,
"Y:\\npm\\logs\\proxy-host-24_error.log": 0,
"Y:\\npm\\logs\\proxy-host-25_access.log": 0,
"Y:\\npm\\logs\\proxy-host-25_error.log": 0,
"Y:\\npm\\logs\\proxy-host-26_access.log": 0,
"Y:\\npm\\logs\\proxy-host-26_error.log": 0,
"Y:\\npm\\logs\\proxy-host-27_access.log": 0,
"Y:\\npm\\logs\\proxy-host-27_error.log": 0,
"Y:\\npm\\logs\\proxy-host-28_access.log": 107302,
"Y:\\npm\\logs\\proxy-host-28_error.log": 116208,
"Y:\\npm\\logs\\proxy-host-29_access.log": 158185,
"Y:\\npm\\logs\\proxy-host-29_error.log": 90709,
"Y:\\npm\\logs\\proxy-host-2_access.log": 0,
"Y:\\npm\\logs\\proxy-host-2_error.log": 0,
"Y:\\npm\\logs\\proxy-host-30_access.log": 0,
"Y:\\npm\\logs\\proxy-host-30_error.log": 0,
"Y:\\npm\\logs\\proxy-host-31_access.log": 3846085,
"Y:\\npm\\logs\\proxy-host-31_error.log": 282448,
"Y:\\npm\\logs\\proxy-host-3_access.log": 658178,
"Y:\\npm\\logs\\proxy-host-3_error.log": 46739,
"Y:\\npm\\logs\\proxy-host-4_access.log": 0,
"Y:\\npm\\logs\\proxy-host-4_error.log": 0,
"Y:\\npm\\logs\\proxy-host-5_access.log": 0,
"Y:\\npm\\logs\\proxy-host-5_error.log": 0,
"Y:\\npm\\logs\\proxy-host-6_access.log": 0,
"Y:\\npm\\logs\\proxy-host-6_error.log": 0,
"Y:\\npm\\logs\\proxy-host-7_access.log": 0,
"Y:\\npm\\logs\\proxy-host-7_error.log": 0,
"Y:\\npm\\logs\\proxy-host-8_access.log": 558598,
"Y:\\npm\\logs\\proxy-host-8_error.log": 45468,
"Y:\\npm\\logs\\proxy-host-9_access.log": 34788693,
"Y:\\npm\\logs\\proxy-host-9_error.log": 292624,
"Y:\\npm\\logs\\stream-1_access.log": 0,
"Y:\\npm\\logs\\stream-1_error.log": 0,
"Y:\\npm\\logs\\stream-2_access.log": 0,
"Y:\\npm\\logs\\stream-2_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_error.log": 2342,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_http_access.log": 444743,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_http_error.log": 507761,
"\\\\naspve\\nas\\backups\\npm\\logs\\fallback_stream_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-10_access.log": 131738,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-10_error.log": 314,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-11_access.log": 1345373,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-11_error.log": 11526,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-12_access.log": 692484,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-12_error.log": 13649,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-13_access.log": 907343,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-13_error.log": 31479,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-14_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-14_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-15_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-15_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-16_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-16_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-17_access.log": 18521,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-17_error.log": 11333,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-18_access.log": 610146,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-18_error.log": 12622,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-19_access.log": 2708,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-19_error.log": 1937,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-1_access.log": 87903,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-1_error.log": 11003,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-20_access.log": 827861,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-20_error.log": 11032,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-21_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-21_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-22_access.log": 200379,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-22_error.log": 1052,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-23_access.log": 453,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-23_error.log": 525,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-24_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-24_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-25_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-25_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-26_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-26_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-27_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-27_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-28_access.log": 2104,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-28_error.log": 2174,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-29_access.log": 9608,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-29_error.log": 2462,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-2_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-2_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-30_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-30_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-31_access.log": 41817,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-31_error.log": 1547,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-3_access.log": 277282,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-3_error.log": 10645,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-4_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-4_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-5_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-5_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-6_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-6_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-7_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-7_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-8_access.log": 163769,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-8_error.log": 10207,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-9_access.log": 2603446,
"\\\\naspve\\nas\\backups\\npm\\logs\\proxy-host-9_error.log": 55751,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-1_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-1_error.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-2_access.log": 0,
"\\\\naspve\\nas\\backups\\npm\\logs\\stream-2_error.log": 0,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-11.txt": 7403,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-11.txt.1": 84622,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-12.txt": 99031,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-13.txt": 92896,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-14.txt": 191781,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt": 55394,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt.1": 8770,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-15.txt.2": 9606,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-16.txt": 35715,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-17.txt": 102469,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-17.txt.1": 35820,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-18.txt": 1784,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-19.txt": 273815,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-20.txt": 572443,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-21.txt": 56055,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-22.txt": 135922,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt": 2468,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.1": 349125,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.2": 199809,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.3": 1023,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.4": 1023,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.5": 1041,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.6": 114042,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.7": 19621,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.8": 29806,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-23.txt.9": 15526221,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-24.txt": 99348,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-25.txt": 63410,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-26.txt": 217801,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-27.txt": 66457,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-28.txt": 59236,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-29.txt": 153562,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-29.txt.1": 24147,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-30.txt": 1212354,
"\\\\naspve\\nas\\projects\\copyparty\\2026-07-31.txt": 49026,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-01.txt": 298970,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-01.txt.1": 274541,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-02.txt": 45372,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-03.txt": 34302,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-04.txt": 33282,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-05.txt": 75013,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-06.txt": 64948,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-07.txt": 48371,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-08.txt": 39365,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-09.txt": 154216,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-09.txt.1": 12568,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-10.txt": 85753,
"\\\\naspve\\nas\\projects\\copyparty\\2026-08-11.txt": 6042
}
+1130 -1130
View File
File diff suppressed because it is too large. Load diff
+364 -364
View File
@@ -1,364 +1,364 @@
"""
firewall.py -
Module for interacting with the Mikrotik routeros shell to manage firewall rules and IP address lists.
Provides functions to read the current firewall configuration, add and remove IPs from the blocklist.
Reads the latest report from the IDS scan, reads the current firewall configuration, and updates the router's blocklist accordingly.
"""
from __future__ import annotations
import os
import json
import paramiko
from datetime import datetime
import shlex
from typing import Iterable
from .utils.constants import (
BLOCKLIST_NAME,
MIKROTIK_DATA_DIR,
REPORT_DIR,
ROUTER_IP,
ROUTER_PASSWORD,
ROUTER_USER,
SSH_PORT,
SSH_TIMEOUT,
WHITELIST_NAMES,
)
from .utils.files import write_lines
from .utils.ip_utils import is_whitelisted
from .utils.blocklist_history import compute_changes, cumulative_blocklist
class MikrotikFirewall:
"""
Class to manage Mikrotik firewall rules and IP address lists.
Provides methods to read the current blocklist, add/remove IPs, and update the blocklist based on IDS scan reports.
"""
def __init__(self, router_ip: str = ROUTER_IP, username: str = ROUTER_USER,
password: str = ROUTER_PASSWORD):
self.router_ip = router_ip
self.username = username
self.password = password
self.client: paramiko.SSHClient | None = None
def connect(self) -> None:
"""Establish an SSH connection to the Mikrotik router."""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# RouterOS 7.20.x exposes an RSA host key and classic SSH ciphers.
client.connect(
self.router_ip,
port=SSH_PORT,
username=self.username,
password=self.password,
timeout=SSH_TIMEOUT,
banner_timeout=SSH_TIMEOUT,
auth_timeout=SSH_TIMEOUT,
allow_agent=False,
look_for_keys=False,
compress=False,
disabled_algorithms={"pubkeys": ["rsa-sha2-512"]},
)
except Exception:
client.close()
raise
self.client = client
def disconnect(self) -> None:
"""Close the SSH connection."""
if self.client:
self.client.close()
self.client = None
def execute_command(self, command: str) -> str:
"""Execute a command on the Mikrotik router via SSH and return the output."""
if not self.client:
raise RuntimeError("SSH client is not connected.")
stdin, stdout, stderr = self.client.exec_command(command)
output = stdout.read().decode("utf-8")
error = stderr.read().decode("utf-8")
if error:
raise RuntimeError(f"Error executing command '{command}': {error}")
return output
def get_address_list_ipv4(self, name: str) -> set[str]:
"""Retrieve the current IPv4 address list from the Mikrotik router."""
output = self.execute_command("/ip firewall address-list print")
ips = set()
for line in output.splitlines():
parts = line.split()
if len(parts) >= 3 and parts[1] == "list" and parts[2] == name:
ip = parts[0]
ips.add(ip)
return ips
def get_address_list_ipv6(self, name: str) -> set[str]:
"""Retrieve the current IPv6 address list from the Mikrotik router."""
output = self.execute_command("/ipv6 firewall address-list print")
ips = set()
for line in output.splitlines():
parts = line.split()
if len(parts) >= 3 and parts[1] == "list" and parts[2] == name:
ip = parts[0]
ips.add(ip)
return ips
@staticmethod
def _parse_terse_output(output: str) -> list[dict[str, str]]:
"""Parse RouterOS `print terse` records into key/value dictionaries."""
records = []
for line in output.splitlines():
fields = {}
for field in shlex.split(line):
key, separator, value = field.partition("=")
if separator:
fields[key] = value
if fields:
records.append(fields)
return records
def get_address_lists(self, ipv6: bool = False) -> list[dict[str, str]]:
"""Retrieve all address-list entries in structured form."""
path = "/ipv6" if ipv6 else "/ip"
output = self.execute_command(
f"{path} firewall address-list print terse")
return self._parse_terse_output(output)
def get_firewall_rules(self, ipv6: bool = False) -> list[dict[str, str]]:
"""Retrieve all firewall filter rules in structured form."""
path = "/ipv6" if ipv6 else "/ip"
output = self.execute_command(
f"{path} firewall filter print terse")
return self._parse_terse_output(output)
@staticmethod
def _write_json(path: str, obj) -> None:
with open(path, "w", encoding="utf-8") as file:
json.dump(obj, file, indent=2, sort_keys=True)
def save_state_report(self, report_dir: str = REPORT_DIR,
changes: dict | None = None) -> str:
"""Save current address lists and firewall rules for auditing.
Writes structured snapshots to ``<report_dir>/mikrotik/data/`` and to
the common ``data/mikrotik/`` directory (overwritten every run so git
can diff changes to the firewall state over time), plus a timestamped
JSON report under ``<report_dir>/mikrotik/``.
"""
state = {
"router": self.router_ip,
"collected_at": datetime.now().astimezone().isoformat(),
"address_lists": {
"ipv4": self.get_address_lists(),
"ipv6": self.get_address_lists(ipv6=True),
},
"firewall_rules": {
"ipv4": self.get_firewall_rules(),
"ipv6": self.get_firewall_rules(ipv6=True),
},
}
if changes is not None:
state["changes"] = changes
report_data_dir = os.path.join(report_dir, "mikrotik", "data")
os.makedirs(report_data_dir, exist_ok=True)
os.makedirs(MIKROTIK_DATA_DIR, exist_ok=True)
for version in ("ipv4", "ipv6"):
for data_dir in (report_data_dir, MIKROTIK_DATA_DIR):
self._write_json(
os.path.join(data_dir, f"address_list_{version}.json"),
state["address_lists"][version])
self._write_json(
os.path.join(data_dir, f"firewall_{version}.json"),
state["firewall_rules"][version])
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
report_path = os.path.join(report_dir, "mikrotik", f"{timestamp}.json")
self._write_json(report_path, state)
return report_path
def sync_blocklist(self, blocked_ipv4: Iterable[str],
blocked_ipv6: Iterable[str],
dry_run: bool = False,
report_dir: str = REPORT_DIR) -> dict[str, list[str]]:
"""Synchronize the Blocked list cumulatively and audit the result.
The blocklist is grow-only: targets are added when present in the
complete set (all git history of the blocklist files + the current
working files + this scan's targets) and never removed automatically.
Only router entries absent from the complete set — i.e. never blocked
by the system — are pruned. See ``app.blocklist_history``.
"""
desired_ipv4 = set(blocked_ipv4)
desired_ipv6 = set(blocked_ipv6)
current_ipv4 = self.get_address_list_ipv4(BLOCKLIST_NAME)
current_ipv6 = self.get_address_list_ipv6(BLOCKLIST_NAME)
whitelisted_ipv4 = set()
whitelisted_ipv6 = set()
for name in WHITELIST_NAMES:
whitelisted_ipv4.update(self.get_address_list_ipv4(name))
whitelisted_ipv6.update(self.get_address_list_ipv6(name))
v4_path = os.path.join(
report_dir, "app", "data", "blocklist_ipv4.txt")
v6_path = os.path.join(
report_dir, "app", "data", "blocklist_ipv6.txt")
complete_v4, complete_v6 = cumulative_blocklist(
v4_path, v6_path, desired_ipv4, desired_ipv6)
changes = compute_changes(
current_ipv4, current_ipv6,
complete_v4, complete_v6,
whitelisted_ipv4, whitelisted_ipv6)
changes["dry_run"] = dry_run
if not dry_run:
for ip in changes["removed_ipv4"]:
self.execute_command(
f"/ip firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
for ip in changes["removed_ipv6"]:
self.execute_command(
f"/ipv6 firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
self.write_address_list_ipv4(BLOCKLIST_NAME, changes["added_ipv4"])
self.write_address_list_ipv6(BLOCKLIST_NAME, changes["added_ipv6"])
self.save_state_report(report_dir, changes)
return changes
def write_address_list_ipv4(self, name: str, ips: Iterable[str]) -> None:
"""Write a list of IPv4 addresses to the Mikrotik router's address list."""
for ip in ips:
if is_whitelisted(ip):
continue # Skip whitelisted IPs
self.execute_command(
f"/ip firewall address-list add list={name} address={ip}")
def write_address_list_ipv6(self, name: str, ips: Iterable[str]) -> None:
"""Write a list of IPv6 addresses to the Mikrotik router's address list."""
for ip in ips:
if is_whitelisted(ip):
continue # Skip whitelisted IPs
self.execute_command(
f"/ipv6 firewall address-list add list={name} address={ip}")
def write_blocklist_files(blocked_ipv4: Iterable[str],
blocked_ipv6: Iterable[str],
report_dir: str = REPORT_DIR) -> tuple[str, str]:
"""Write the final consolidated blocklist to ``<report_dir>/app/data/``.
Returns the paths of the IPv4 and IPv6 blocklist files
(``blocklist_ipv4.txt`` / ``blocklist_ipv6.txt``).
"""
data_dir = os.path.join(report_dir, "app", "data")
os.makedirs(data_dir, exist_ok=True)
v4_path = os.path.join(data_dir, "blocklist_ipv4.txt")
v6_path = os.path.join(data_dir, "blocklist_ipv6.txt")
write_lines(v4_path, sorted(blocked_ipv4))
write_lines(v6_path, sorted(blocked_ipv6))
return v4_path, v6_path
def get_scan_report(report_dir: str = REPORT_DIR) -> dict[str, list[str]]:
"""Read the latest scan report `mikrotik-block.rsc` from the report directory and return the list of blocked IPs."""
report_path = os.path.join(report_dir, "mikrotik-block.rsc")
if not os.path.exists(report_path):
raise FileNotFoundError(f"Scan report not found: {report_path}")
# add sections, they start with `/ip firewall address-list` or `/ipv6 firewall address-list` and end with a blank line or EOF
sections = {
"/ip firewall address-list": [],
"/ipv6 firewall address-list": [],
}
# add list=Cloudflare or list=Openfactory 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:
line = line.strip()
if not line:
current_section = None
continue
if line.startswith("/ip firewall address-list"):
current_section = "/ip firewall address-list"
continue
if line.startswith("/ipv6 firewall address-list"):
current_section = "/ipv6 firewall address-list"
continue
if current_section:
sections[current_section].append(line)
return sections
def main():
"""Legacy entry point for applying the latest generated RouterOS report."""
# Read the latest scan report
scan_report = get_scan_report(REPORT_DIR)
# Connect to the Mikrotik router
firewall = MikrotikFirewall()
firewall.connect()
# read current blocked IPs from the router
current_blocked_ipv4 = firewall.get_address_list_ipv4(BLOCKLIST_NAME)
current_blocked_ipv6 = firewall.get_address_list_ipv6(BLOCKLIST_NAME)
# read whitelisted IPs from the router
whitelisted_ipv4 = set()
whitelisted_ipv6 = set()
for wl_name in WHITELIST_NAMES:
whitelisted_ipv4.update(firewall.get_address_list_ipv4(wl_name))
whitelisted_ipv6.update(firewall.get_address_list_ipv6(wl_name))
# read blocked IPs from the scan report
blocked_ipv4 = set()
blocked_ipv6 = set()
for line in scan_report["/ip firewall address-list"]:
if "list=Blocked" in line:
parts = line.split()
for part in parts:
if part.startswith("address="):
ip = part.split("=")[1]
blocked_ipv4.add(ip)
for line in scan_report["/ipv6 firewall address-list"]:
if "list=Blocked" in line:
parts = line.split()
for part in parts:
if part.startswith("address="):
ip = part.split("=")[1]
blocked_ipv6.add(ip)
# Determine which IPs to add and remove
to_add_ipv4 = blocked_ipv4 - current_blocked_ipv4 - whitelisted_ipv4
to_add_ipv6 = blocked_ipv6 - current_blocked_ipv6 - whitelisted_ipv6
to_remove_ipv4 = current_blocked_ipv4 - blocked_ipv4
to_remove_ipv6 = current_blocked_ipv6 - blocked_ipv6
# Remove old blocked IPs
for ip in to_remove_ipv4:
firewall.execute_command(
f"/ip firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
for ip in to_remove_ipv6:
firewall.execute_command(
f"/ipv6 firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
# Add new blocked IPs
firewall.write_address_list_ipv4(BLOCKLIST_NAME, to_add_ipv4)
firewall.write_address_list_ipv6(BLOCKLIST_NAME, to_add_ipv6)
firewall.save_state_report(REPORT_DIR)
# Disconnect from the router
firewall.disconnect()
# Print summary
print(
f"Removed {len(to_remove_ipv4)} IPv4 and {len(to_remove_ipv6)} IPv6 addresses from the blocklist.")
print(
f"Added {len(to_add_ipv4)} IPv4 and {len(to_add_ipv6)} IPv6 addresses to the blocklist.")
if __name__ == "__main__":
main()
"""
firewall.py -
Module for interacting with the Mikrotik routeros shell to manage firewall rules and IP address lists.
Provides functions to read the current firewall configuration, add and remove IPs from the blocklist.
Reads the latest report from the IDS scan, reads the current firewall configuration, and updates the router's blocklist accordingly.
"""
from __future__ import annotations
import os
import json
import paramiko
from datetime import datetime
import shlex
from typing import Iterable
from .utils.constants import (
BLOCKLIST_NAME,
MIKROTIK_DATA_DIR,
REPORT_DIR,
ROUTER_IP,
ROUTER_PASSWORD,
ROUTER_USER,
SSH_PORT,
SSH_TIMEOUT,
WHITELIST_NAMES,
)
from .utils.files import write_lines
from .utils.ip_utils import is_whitelisted
from .utils.blocklist_history import compute_changes, cumulative_blocklist
class MikrotikFirewall:
"""
Class to manage Mikrotik firewall rules and IP address lists.
Provides methods to read the current blocklist, add/remove IPs, and update the blocklist based on IDS scan reports.
"""
def __init__(self, router_ip: str = ROUTER_IP, username: str = ROUTER_USER,
password: str = ROUTER_PASSWORD):
self.router_ip = router_ip
self.username = username
self.password = password
self.client: paramiko.SSHClient | None = None
def connect(self) -> None:
"""Establish an SSH connection to the Mikrotik router."""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# RouterOS 7.20.x exposes an RSA host key and classic SSH ciphers.
client.connect(
self.router_ip,
port=SSH_PORT,
username=self.username,
password=self.password,
timeout=SSH_TIMEOUT,
banner_timeout=SSH_TIMEOUT,
auth_timeout=SSH_TIMEOUT,
allow_agent=False,
look_for_keys=False,
compress=False,
disabled_algorithms={"pubkeys": ["rsa-sha2-512"]},
)
except Exception:
client.close()
raise
self.client = client
def disconnect(self) -> None:
"""Close the SSH connection."""
if self.client:
self.client.close()
self.client = None
def execute_command(self, command: str) -> str:
"""Execute a command on the Mikrotik router via SSH and return the output."""
if not self.client:
raise RuntimeError("SSH client is not connected.")
stdin, stdout, stderr = self.client.exec_command(command)
output = stdout.read().decode("utf-8")
error = stderr.read().decode("utf-8")
if error:
raise RuntimeError(f"Error executing command '{command}': {error}")
return output
def get_address_list_ipv4(self, name: str) -> set[str]:
"""Retrieve the current IPv4 address list from the Mikrotik router."""
output = self.execute_command("/ip firewall address-list print")
ips = set()
for line in output.splitlines():
parts = line.split()
if len(parts) >= 3 and parts[1] == "list" and parts[2] == name:
ip = parts[0]
ips.add(ip)
return ips
def get_address_list_ipv6(self, name: str) -> set[str]:
"""Retrieve the current IPv6 address list from the Mikrotik router."""
output = self.execute_command("/ipv6 firewall address-list print")
ips = set()
for line in output.splitlines():
parts = line.split()
if len(parts) >= 3 and parts[1] == "list" and parts[2] == name:
ip = parts[0]
ips.add(ip)
return ips
@staticmethod
def _parse_terse_output(output: str) -> list[dict[str, str]]:
"""Parse RouterOS `print terse` records into key/value dictionaries."""
records = []
for line in output.splitlines():
fields = {}
for field in shlex.split(line):
key, separator, value = field.partition("=")
if separator:
fields[key] = value
if fields:
records.append(fields)
return records
def get_address_lists(self, ipv6: bool = False) -> list[dict[str, str]]:
"""Retrieve all address-list entries in structured form."""
path = "/ipv6" if ipv6 else "/ip"
output = self.execute_command(
f"{path} firewall address-list print terse")
return self._parse_terse_output(output)
def get_firewall_rules(self, ipv6: bool = False) -> list[dict[str, str]]:
"""Retrieve all firewall filter rules in structured form."""
path = "/ipv6" if ipv6 else "/ip"
output = self.execute_command(
f"{path} firewall filter print terse")
return self._parse_terse_output(output)
@staticmethod
def _write_json(path: str, obj) -> None:
with open(path, "w", encoding="utf-8") as file:
json.dump(obj, file, indent=2, sort_keys=True)
def save_state_report(self, report_dir: str = REPORT_DIR,
changes: dict | None = None) -> str:
"""Save current address lists and firewall rules for auditing.
Writes structured snapshots to ``<report_dir>/mikrotik/data/`` and to
the common ``data/mikrotik/`` directory (overwritten every run so git
can diff changes to the firewall state over time), plus a timestamped
JSON report under ``<report_dir>/mikrotik/``.
"""
state = {
"router": self.router_ip,
"collected_at": datetime.now().astimezone().isoformat(),
"address_lists": {
"ipv4": self.get_address_lists(),
"ipv6": self.get_address_lists(ipv6=True),
},
"firewall_rules": {
"ipv4": self.get_firewall_rules(),
"ipv6": self.get_firewall_rules(ipv6=True),
},
}
if changes is not None:
state["changes"] = changes
report_data_dir = os.path.join(report_dir, "mikrotik", "data")
os.makedirs(report_data_dir, exist_ok=True)
os.makedirs(MIKROTIK_DATA_DIR, exist_ok=True)
for version in ("ipv4", "ipv6"):
for data_dir in (report_data_dir, MIKROTIK_DATA_DIR):
self._write_json(
os.path.join(data_dir, f"address_list_{version}.json"),
state["address_lists"][version])
self._write_json(
os.path.join(data_dir, f"firewall_{version}.json"),
state["firewall_rules"][version])
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
report_path = os.path.join(report_dir, "mikrotik", f"{timestamp}.json")
self._write_json(report_path, state)
return report_path
def sync_blocklist(self, blocked_ipv4: Iterable[str],
blocked_ipv6: Iterable[str],
dry_run: bool = False,
report_dir: str = REPORT_DIR) -> dict[str, list[str]]:
"""Synchronize the Blocked list cumulatively and audit the result.
The blocklist is grow-only: targets are added when present in the
complete set (all git history of the blocklist files + the current
working files + this scan's targets) and never removed automatically.
Only router entries absent from the complete set — i.e. never blocked
by the system — are pruned. See ``app.blocklist_history``.
"""
desired_ipv4 = set(blocked_ipv4)
desired_ipv6 = set(blocked_ipv6)
current_ipv4 = self.get_address_list_ipv4(BLOCKLIST_NAME)
current_ipv6 = self.get_address_list_ipv6(BLOCKLIST_NAME)
whitelisted_ipv4 = set()
whitelisted_ipv6 = set()
for name in WHITELIST_NAMES:
whitelisted_ipv4.update(self.get_address_list_ipv4(name))
whitelisted_ipv6.update(self.get_address_list_ipv6(name))
v4_path = os.path.join(
report_dir, "app", "data", "blocklist_ipv4.txt")
v6_path = os.path.join(
report_dir, "app", "data", "blocklist_ipv6.txt")
complete_v4, complete_v6 = cumulative_blocklist(
v4_path, v6_path, desired_ipv4, desired_ipv6)
changes = compute_changes(
current_ipv4, current_ipv6,
complete_v4, complete_v6,
whitelisted_ipv4, whitelisted_ipv6)
changes["dry_run"] = dry_run
if not dry_run:
for ip in changes["removed_ipv4"]:
self.execute_command(
f"/ip firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
for ip in changes["removed_ipv6"]:
self.execute_command(
f"/ipv6 firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
self.write_address_list_ipv4(BLOCKLIST_NAME, changes["added_ipv4"])
self.write_address_list_ipv6(BLOCKLIST_NAME, changes["added_ipv6"])
self.save_state_report(report_dir, changes)
return changes
def write_address_list_ipv4(self, name: str, ips: Iterable[str]) -> None:
"""Write a list of IPv4 addresses to the Mikrotik router's address list."""
for ip in ips:
if is_whitelisted(ip):
continue # Skip whitelisted IPs
self.execute_command(
f"/ip firewall address-list add list={name} address={ip}")
def write_address_list_ipv6(self, name: str, ips: Iterable[str]) -> None:
"""Write a list of IPv6 addresses to the Mikrotik router's address list."""
for ip in ips:
if is_whitelisted(ip):
continue # Skip whitelisted IPs
self.execute_command(
f"/ipv6 firewall address-list add list={name} address={ip}")
def write_blocklist_files(blocked_ipv4: Iterable[str],
blocked_ipv6: Iterable[str],
report_dir: str = REPORT_DIR) -> tuple[str, str]:
"""Write the final consolidated blocklist to ``<report_dir>/app/data/``.
Returns the paths of the IPv4 and IPv6 blocklist files
(``blocklist_ipv4.txt`` / ``blocklist_ipv6.txt``).
"""
data_dir = os.path.join(report_dir, "app", "data")
os.makedirs(data_dir, exist_ok=True)
v4_path = os.path.join(data_dir, "blocklist_ipv4.txt")
v6_path = os.path.join(data_dir, "blocklist_ipv6.txt")
write_lines(v4_path, sorted(blocked_ipv4))
write_lines(v6_path, sorted(blocked_ipv6))
return v4_path, v6_path
def get_scan_report(report_dir: str = REPORT_DIR) -> dict[str, list[str]]:
"""Read the latest scan report `mikrotik-block.rsc` from the report directory and return the list of blocked IPs."""
report_path = os.path.join(report_dir, "mikrotik-block.rsc")
if not os.path.exists(report_path):
raise FileNotFoundError(f"Scan report not found: {report_path}")
# add sections, they start with `/ip firewall address-list` or `/ipv6 firewall address-list` and end with a blank line or EOF
sections = {
"/ip firewall address-list": [],
"/ipv6 firewall address-list": [],
}
# add list=Cloudflare or list=Openfactory 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:
line = line.strip()
if not line:
current_section = None
continue
if line.startswith("/ip firewall address-list"):
current_section = "/ip firewall address-list"
continue
if line.startswith("/ipv6 firewall address-list"):
current_section = "/ipv6 firewall address-list"
continue
if current_section:
sections[current_section].append(line)
return sections
def main():
"""Legacy entry point for applying the latest generated RouterOS report."""
# Read the latest scan report
scan_report = get_scan_report(REPORT_DIR)
# Connect to the Mikrotik router
firewall = MikrotikFirewall()
firewall.connect()
# read current blocked IPs from the router
current_blocked_ipv4 = firewall.get_address_list_ipv4(BLOCKLIST_NAME)
current_blocked_ipv6 = firewall.get_address_list_ipv6(BLOCKLIST_NAME)
# read whitelisted IPs from the router
whitelisted_ipv4 = set()
whitelisted_ipv6 = set()
for wl_name in WHITELIST_NAMES:
whitelisted_ipv4.update(firewall.get_address_list_ipv4(wl_name))
whitelisted_ipv6.update(firewall.get_address_list_ipv6(wl_name))
# read blocked IPs from the scan report
blocked_ipv4 = set()
blocked_ipv6 = set()
for line in scan_report["/ip firewall address-list"]:
if "list=Blocked" in line:
parts = line.split()
for part in parts:
if part.startswith("address="):
ip = part.split("=")[1]
blocked_ipv4.add(ip)
for line in scan_report["/ipv6 firewall address-list"]:
if "list=Blocked" in line:
parts = line.split()
for part in parts:
if part.startswith("address="):
ip = part.split("=")[1]
blocked_ipv6.add(ip)
# Determine which IPs to add and remove
to_add_ipv4 = blocked_ipv4 - current_blocked_ipv4 - whitelisted_ipv4
to_add_ipv6 = blocked_ipv6 - current_blocked_ipv6 - whitelisted_ipv6
to_remove_ipv4 = current_blocked_ipv4 - blocked_ipv4
to_remove_ipv6 = current_blocked_ipv6 - blocked_ipv6
# Remove old blocked IPs
for ip in to_remove_ipv4:
firewall.execute_command(
f"/ip firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
for ip in to_remove_ipv6:
firewall.execute_command(
f"/ipv6 firewall address-list remove [find list={BLOCKLIST_NAME} address={ip}]")
# Add new blocked IPs
firewall.write_address_list_ipv4(BLOCKLIST_NAME, to_add_ipv4)
firewall.write_address_list_ipv6(BLOCKLIST_NAME, to_add_ipv6)
firewall.save_state_report(REPORT_DIR)
# Disconnect from the router
firewall.disconnect()
# Print summary
print(
f"Removed {len(to_remove_ipv4)} IPv4 and {len(to_remove_ipv6)} IPv6 addresses from the blocklist.")
print(
f"Added {len(to_add_ipv4)} IPv4 and {len(to_add_ipv6)} IPv6 addresses to the blocklist.")
if __name__ == "__main__":
main()
+47 -47
View File
@@ -1,47 +1,47 @@
#!/usr/bin/env python3
"""Flagging rules for the intrusion-detection system.
Detection functions that identify hostile IPs based on aggregated stats.
"""
from __future__ import annotations
from . import bad_patterns
from .utils.constants import DEFAULT_ERROR_RATIO, DEFAULT_MIN_DENIED, DEFAULT_MIN_ERRORS
from .utils.models import IPStats
def flag_scanners(stats: dict[str, IPStats], min_errors: int = DEFAULT_MIN_ERRORS,
min_ratio: float = DEFAULT_ERROR_RATIO) -> dict[str, IPStats]:
"""IPs with many errors AND a high error ratio."""
return {
ip: s for ip, s in stats.items()
if s.errors >= min_errors and s.error_ratio >= min_ratio
}
def flag_denied_only(stats: dict[str, IPStats],
min_denied: int = DEFAULT_MIN_DENIED) -> dict[str, IPStats]:
"""IPs that only ever hit denied paths and never authenticated."""
return {
ip: s for ip, s in stats.items()
if s.denied >= min_denied and not s.authenticated
}
def flag_malicious_patterns(stats: dict[str, IPStats],
min_severity: int = 2,
min_hits: int = 1) -> dict[str, IPStats]:
"""IPs with hits against malicious path patterns at or above severity threshold."""
return {
ip: s for ip, s in stats.items()
if s.malicious_hits >= min_hits and any(
bad_patterns.PATTERNS_BY_NAME[name].severity >= min_severity
for name in s.malicious_patterns
)
}
def by_total(stats: dict[str, IPStats]) -> list[IPStats]:
"""Stats sorted by request count, descending."""
return sorted(stats.values(), key=lambda s: (-s.total, s.ip))
#!/usr/bin/env python3
"""Flagging rules for the intrusion-detection system.
Detection functions that identify hostile IPs based on aggregated stats.
"""
from __future__ import annotations
from . import bad_patterns
from .utils.constants import DEFAULT_ERROR_RATIO, DEFAULT_MIN_DENIED, DEFAULT_MIN_ERRORS
from .utils.models import IPStats
def flag_scanners(stats: dict[str, IPStats], min_errors: int = DEFAULT_MIN_ERRORS,
min_ratio: float = DEFAULT_ERROR_RATIO) -> dict[str, IPStats]:
"""IPs with many errors AND a high error ratio."""
return {
ip: s for ip, s in stats.items()
if s.errors >= min_errors and s.error_ratio >= min_ratio
}
def flag_denied_only(stats: dict[str, IPStats],
min_denied: int = DEFAULT_MIN_DENIED) -> dict[str, IPStats]:
"""IPs that only ever hit denied paths and never authenticated."""
return {
ip: s for ip, s in stats.items()
if s.denied >= min_denied and not s.authenticated
}
def flag_malicious_patterns(stats: dict[str, IPStats],
min_severity: int = 2,
min_hits: int = 1) -> dict[str, IPStats]:
"""IPs with hits against malicious path patterns at or above severity threshold."""
return {
ip: s for ip, s in stats.items()
if s.malicious_hits >= min_hits and any(
bad_patterns.PATTERNS_BY_NAME[name].severity >= min_severity
for name in s.malicious_patterns
)
}
def by_total(stats: dict[str, IPStats]) -> list[IPStats]:
"""Stats sorted by request count, descending."""
return sorted(stats.values(), key=lambda s: (-s.total, s.ip))
+111 -111
View File
@@ -1,111 +1,111 @@
#!/usr/bin/env python3
"""MikroTik RouterOS script generation."""
from __future__ import annotations
import ipaddress
from datetime import datetime
from typing import Iterable
from .utils.ip_utils import is_ipv4, is_ipv6, is_whitelisted, parse_ip
from .utils.whitelists import WHITELISTS
from .utils.constants import BLOCKLIST_NAME
def split_cidr_versions(targets: Iterable[str]) -> tuple[list[str], list[str]]:
"""Split target CIDRs/IPs into (sorted IPv4 list, sorted IPv6 list)."""
v4 = []
v6 = []
for t in targets:
ip = t.split("/")[0]
if is_ipv4(ip):
v4.append(t)
elif is_ipv6(ip):
v6.append(t)
def key_cidr(cidr: str):
ip = cidr.split("/")[0]
addr = parse_ip(ip)
if addr is None:
return (9, b"", cidr)
return (addr.version, addr.packed, cidr)
return sorted(v4, key=key_cidr), sorted(v6, key=key_cidr)
def mikrotik_script(tag: str, blocked_ips_or_subnets: Iterable[str],
whitelists: dict[str, list[str]] | None = None,
generated: str | None = None) -> tuple[str, int, int]:
"""Build a RouterOS .rsc script.
Whitelisted ranges become `accept` rules placed above the `drop` rules.
Blocked targets can be individual IPs (e.g. 1.2.3.4/32) or CIDR blocks
(e.g. 1.2.3.0/24).
Returns (script_text, blocked_count, whitelisted_cidr_count).
"""
whitelists = WHITELISTS if whitelists is None else whitelists
generated = generated or datetime.now().isoformat(timespec="seconds")
def clean_blocked(targets: Iterable[str]) -> list[str]:
cleaned = []
for t in targets:
ip = t.split("/")[0]
if not is_whitelisted(ip):
cleaned.append(t)
return cleaned
blocked = clean_blocked(set(blocked_ips_or_subnets))
block_v4, block_v6 = split_cidr_versions(blocked)
lines: list[str] = [f"# {tag} firewall export - generated {generated}", ""]
wl_count = 0
for name, cidrs in whitelists.items():
nets = [ipaddress.ip_network(c) for c in cidrs]
wl_count += len(nets)
for version, cmd in ((4, "/ip firewall address-list"),
(6, "/ipv6 firewall address-list")):
chunk = [n for n in nets if n.version == version]
if not chunk:
continue
lines.append(f"# {name} IPv{version} ranges (whitelisted)")
lines.append(cmd)
lines += [f"add list={name} address={n}" for n in chunk]
lines.append("")
if block_v4:
lines.append(f"# Blocked IPv4 ({len(block_v4)}, non-whitelisted)")
lines.append("/ip firewall address-list")
lines += [f"add list={BLOCKLIST_NAME} address={t}" for t in block_v4]
lines.append("")
if block_v6:
lines.append(f"# Blocked IPv6 ({len(block_v6)}, non-whitelisted)")
lines.append("/ipv6 firewall address-list")
lines += [f"add list={BLOCKLIST_NAME} address={t}" for t in block_v6]
lines.append("")
for version, cmd, blocks in ((4, "/ip firewall filter", block_v4),
(6, "/ipv6 firewall filter", block_v6)):
lines.append(cmd)
for name in whitelists:
lines.append(
f"add chain=input action=accept src-address-list={name} "
f'comment="{tag} {name.lower()} whitelist (v{version})"')
if blocks:
for chain in ("input", "forward"):
lines.append(
f"add chain={chain} action=drop src-address-list={BLOCKLIST_NAME} "
f'comment="{tag} blocked (v{version})"')
lines.append("")
return "\n".join(lines), len(blocked), wl_count
def write_mikrotik(path: str, tag: str,
blocked_ips_or_subnets: Iterable[str]) -> tuple[str, int, int]:
text, n_blocked, n_whitelisted = mikrotik_script(
tag, blocked_ips_or_subnets)
with open(path, "w", encoding="utf-8") as f:
f.write(text)
return path, n_blocked, n_whitelisted
#!/usr/bin/env python3
"""MikroTik RouterOS script generation."""
from __future__ import annotations
import ipaddress
from datetime import datetime
from typing import Iterable
from .utils.ip_utils import is_ipv4, is_ipv6, is_whitelisted, parse_ip
from .utils.whitelists import WHITELISTS
from .utils.constants import BLOCKLIST_NAME
def split_cidr_versions(targets: Iterable[str]) -> tuple[list[str], list[str]]:
"""Split target CIDRs/IPs into (sorted IPv4 list, sorted IPv6 list)."""
v4 = []
v6 = []
for t in targets:
ip = t.split("/")[0]
if is_ipv4(ip):
v4.append(t)
elif is_ipv6(ip):
v6.append(t)
def key_cidr(cidr: str):
ip = cidr.split("/")[0]
addr = parse_ip(ip)
if addr is None:
return (9, b"", cidr)
return (addr.version, addr.packed, cidr)
return sorted(v4, key=key_cidr), sorted(v6, key=key_cidr)
def mikrotik_script(tag: str, blocked_ips_or_subnets: Iterable[str],
whitelists: dict[str, list[str]] | None = None,
generated: str | None = None) -> tuple[str, int, int]:
"""Build a RouterOS .rsc script.
Whitelisted ranges become `accept` rules placed above the `drop` rules.
Blocked targets can be individual IPs (e.g. 1.2.3.4/32) or CIDR blocks
(e.g. 1.2.3.0/24).
Returns (script_text, blocked_count, whitelisted_cidr_count).
"""
whitelists = WHITELISTS if whitelists is None else whitelists
generated = generated or datetime.now().isoformat(timespec="seconds")
def clean_blocked(targets: Iterable[str]) -> list[str]:
cleaned = []
for t in targets:
ip = t.split("/")[0]
if not is_whitelisted(ip):
cleaned.append(t)
return cleaned
blocked = clean_blocked(set(blocked_ips_or_subnets))
block_v4, block_v6 = split_cidr_versions(blocked)
lines: list[str] = [f"# {tag} firewall export - generated {generated}", ""]
wl_count = 0
for name, cidrs in whitelists.items():
nets = [ipaddress.ip_network(c) for c in cidrs]
wl_count += len(nets)
for version, cmd in ((4, "/ip firewall address-list"),
(6, "/ipv6 firewall address-list")):
chunk = [n for n in nets if n.version == version]
if not chunk:
continue
lines.append(f"# {name} IPv{version} ranges (whitelisted)")
lines.append(cmd)
lines += [f"add list={name} address={n}" for n in chunk]
lines.append("")
if block_v4:
lines.append(f"# Blocked IPv4 ({len(block_v4)}, non-whitelisted)")
lines.append("/ip firewall address-list")
lines += [f"add list={BLOCKLIST_NAME} address={t}" for t in block_v4]
lines.append("")
if block_v6:
lines.append(f"# Blocked IPv6 ({len(block_v6)}, non-whitelisted)")
lines.append("/ipv6 firewall address-list")
lines += [f"add list={BLOCKLIST_NAME} address={t}" for t in block_v6]
lines.append("")
for version, cmd, blocks in ((4, "/ip firewall filter", block_v4),
(6, "/ipv6 firewall filter", block_v6)):
lines.append(cmd)
for name in whitelists:
lines.append(
f"add chain=input action=accept src-address-list={name} "
f'comment="{tag} {name.lower()} whitelist (v{version})"')
if blocks:
for chain in ("input", "forward"):
lines.append(
f"add chain={chain} action=drop src-address-list={BLOCKLIST_NAME} "
f'comment="{tag} blocked (v{version})"')
lines.append("")
return "\n".join(lines), len(blocked), wl_count
def write_mikrotik(path: str, tag: str,
blocked_ips_or_subnets: Iterable[str]) -> tuple[str, int, int]:
text, n_blocked, n_whitelisted = mikrotik_script(
tag, blocked_ips_or_subnets)
with open(path, "w", encoding="utf-8") as f:
f.write(text)
return path, n_blocked, n_whitelisted
+170 -170
View File
@@ -1,170 +1,170 @@
#!/usr/bin/env python3
"""Nginx Proxy Manager access-log analyzer.
Parses NPM proxy access logs (plain + gzipped), aggregates per-IP
behaviour and flags scanner IPs: clients with many error responses and a
high error ratio. Flagged IPs become the MikroTik block list.
"""
from __future__ import annotations
import os
import re
from collections import Counter
from .analyzer import Analyzer
from .utils.constants import (
DEFAULT_ERROR_RATIO,
DEFAULT_MIN_ERRORS,
NPM_LOG_PATH,
NPM_REPORT_DIR,
)
from .utils.files import write_csv
from .flags import flag_scanners
from .utils.models import Request
from .utils.utils import arg_parser
# [02/Aug/2026:05:01:31 +0200] - 401 401 - GET https host "/path"
# [Client IP] [Length N] [Gzip X] [Sent-to IP] "UA" "Referer"
LINE_RE = re.compile(
r"^\[(\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}\s+[+-]\d{4})\]\s+" # [datetime]
r"-\s+"
r"(\d+|-)\s+" # upstream
r"(\d+)\s+" # status
r"-\s+"
r"(\S+)\s+" # method
r"(\S+)\s+" # scheme
r"(\S+)\s+" # host
r'"([^"]*)"\s+' # "path"
r"\[Client\s+(\S+)\]\s+"
r"\[Length\s+(\d+|-)\]\s+"
r"\[Gzip\s+(\S+)\]\s+"
r"\[Sent-to\s+(\S+)\]\s+"
r'"([^"]*)"\s+' # "UA"
r'"([^"]*)"' # "Referer"
)
class NpmAnalyzer(Analyzer):
name = "npm"
title = "Nginx Proxy Manager log analysis report"
log_suffixes = (".log", ".gz")
exclude_prefixes = ("letsencrypt",)
paths_file = "error_paths.csv"
paths_label = "error paths"
flag_files = ("scanner_ips.txt", "scanner_ipv6.txt")
flag_label = "Scanner IPs"
flag_note = "high error rate -- probable scanners/attackers"
ip_columns = (
("ip", lambda s: s.ip),
("total", lambda s: s.total),
("4xx", lambda s: s.c4xx),
("5xx", lambda s: s.c5xx),
("ratio", lambda s: s.error_ratio),
("first", lambda s: s.first),
("last", lambda s: s.last),
("methods", lambda s: s.methods_str),
("whitelist", lambda s: s.whitelist),
)
request_columns = (
("datetime", lambda r: r.ts),
("ip", lambda r: r.ip),
("method", lambda r: r.method),
("scheme", lambda r: r.extra.get("scheme")),
("host", lambda r: r.host),
("path", lambda r: r.path),
("status", lambda r: r.status),
("upstream_status", lambda r: r.upstream_status),
("length", lambda r: r.extra.get("length")),
("gzip", lambda r: r.extra.get("gzip")),
("sent_to", lambda r: r.extra.get("sent_to")),
("referer", lambda r: r.referer),
("ua", lambda r: r.ua),
)
def __init__(self, *args, min_errors: int = DEFAULT_MIN_ERRORS,
error_ratio: float = DEFAULT_ERROR_RATIO, **kwargs):
super().__init__(*args, **kwargs)
self.min_errors = min_errors
self.min_ratio = error_ratio
# --- parsing -----------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
if not line:
return None
m = LINE_RE.match(line)
if not m:
return None
(ts, upstream, status, method, scheme, host, path, ip,
length, gz, sent_to, ua, referer) = m.groups()
return Request(
ts=ts,
ip=ip,
method=method,
path=path,
status=int(status),
upstream_status=int(upstream) if upstream.isdigit() else None,
host=host,
ua=ua,
referer=referer,
extra={"scheme": scheme, "length": length,
"gzip": gz, "sent_to": sent_to},
)
# --- flagging ----------------------------------------------------------
def flag(self, stats):
return flag_scanners(stats, min_errors=self.min_errors,
min_ratio=self.min_ratio)
# --- extras ------------------------------------------------------------
def extra_summary_rows(self):
c4 = sum(1 for r in self.requests if r.is_client_error)
c5 = sum(1 for r in self.requests if r.is_server_error)
return [
("4xx / 5xx", f"{c4} / {c5}"),
("hosts seen", len({r.host for r in self.requests if r.host})),
("scanner threshold",
f">= {self.min_errors} errors and ratio >= {self.min_ratio}"),
]
def write_extra(self, data_dir: str) -> list[str]:
uas = Counter(r.ua for r in self.requests if r.ua and r.ua != "-")
hosts = Counter(r.host for r in self.requests if r.host)
return [
write_csv(os.path.join(data_dir, "ua_summary.csv"),
["user_agent", "count"], uas.most_common()),
write_csv(os.path.join(data_dir, "host_summary.csv"),
["host", "count"], hosts.most_common()),
]
def main() -> None:
parser = arg_parser(
"analyze NPM proxy logs, flag scanner IPs, export MikroTik rules",
NPM_LOG_PATH, NPM_REPORT_DIR)
parser.add_argument("--min-errors", type=int, default=DEFAULT_MIN_ERRORS,
help=f"minimum error responses to flag (default: {DEFAULT_MIN_ERRORS})")
parser.add_argument("--error-ratio", type=float, default=DEFAULT_ERROR_RATIO,
help=f"minimum error ratio to flag (default: {DEFAULT_ERROR_RATIO})")
parser.add_argument("--full", action="store_true",
help="rescan all logs from the start (ignore incremental state)")
args = parser.parse_args()
NpmAnalyzer(
log_path=args.log_path,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
min_errors=args.min_errors,
error_ratio=args.error_ratio,
).run()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Nginx Proxy Manager access-log analyzer.
Parses NPM proxy access logs (plain + gzipped), aggregates per-IP
behaviour and flags scanner IPs: clients with many error responses and a
high error ratio. Flagged IPs become the MikroTik block list.
"""
from __future__ import annotations
import os
import re
from collections import Counter
from .analyzer import Analyzer
from .utils.constants import (
DEFAULT_ERROR_RATIO,
DEFAULT_MIN_ERRORS,
NPM_LOG_PATH,
NPM_REPORT_DIR,
)
from .utils.files import write_csv
from .flags import flag_scanners
from .utils.models import Request
from .utils.utils import arg_parser
# [02/Aug/2026:05:01:31 +0200] - 401 401 - GET https host "/path"
# [Client IP] [Length N] [Gzip X] [Sent-to IP] "UA" "Referer"
LINE_RE = re.compile(
r"^\[(\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}\s+[+-]\d{4})\]\s+" # [datetime]
r"-\s+"
r"(\d+|-)\s+" # upstream
r"(\d+)\s+" # status
r"-\s+"
r"(\S+)\s+" # method
r"(\S+)\s+" # scheme
r"(\S+)\s+" # host
r'"([^"]*)"\s+' # "path"
r"\[Client\s+(\S+)\]\s+"
r"\[Length\s+(\d+|-)\]\s+"
r"\[Gzip\s+(\S+)\]\s+"
r"\[Sent-to\s+(\S+)\]\s+"
r'"([^"]*)"\s+' # "UA"
r'"([^"]*)"' # "Referer"
)
class NpmAnalyzer(Analyzer):
name = "npm"
title = "Nginx Proxy Manager log analysis report"
log_suffixes = (".log", ".gz")
exclude_prefixes = ("letsencrypt",)
paths_file = "error_paths.csv"
paths_label = "error paths"
flag_files = ("scanner_ips.txt", "scanner_ipv6.txt")
flag_label = "Scanner IPs"
flag_note = "high error rate -- probable scanners/attackers"
ip_columns = (
("ip", lambda s: s.ip),
("total", lambda s: s.total),
("4xx", lambda s: s.c4xx),
("5xx", lambda s: s.c5xx),
("ratio", lambda s: s.error_ratio),
("first", lambda s: s.first),
("last", lambda s: s.last),
("methods", lambda s: s.methods_str),
("whitelist", lambda s: s.whitelist),
)
request_columns = (
("datetime", lambda r: r.ts),
("ip", lambda r: r.ip),
("method", lambda r: r.method),
("scheme", lambda r: r.extra.get("scheme")),
("host", lambda r: r.host),
("path", lambda r: r.path),
("status", lambda r: r.status),
("upstream_status", lambda r: r.upstream_status),
("length", lambda r: r.extra.get("length")),
("gzip", lambda r: r.extra.get("gzip")),
("sent_to", lambda r: r.extra.get("sent_to")),
("referer", lambda r: r.referer),
("ua", lambda r: r.ua),
)
def __init__(self, *args, min_errors: int = DEFAULT_MIN_ERRORS,
error_ratio: float = DEFAULT_ERROR_RATIO, **kwargs):
super().__init__(*args, **kwargs)
self.min_errors = min_errors
self.min_ratio = error_ratio
# --- parsing -----------------------------------------------------------
def parse_line(self, line: str) -> Request | None:
if not line:
return None
m = LINE_RE.match(line)
if not m:
return None
(ts, upstream, status, method, scheme, host, path, ip,
length, gz, sent_to, ua, referer) = m.groups()
return Request(
ts=ts,
ip=ip,
method=method,
path=path,
status=int(status),
upstream_status=int(upstream) if upstream.isdigit() else None,
host=host,
ua=ua,
referer=referer,
extra={"scheme": scheme, "length": length,
"gzip": gz, "sent_to": sent_to},
)
# --- flagging ----------------------------------------------------------
def flag(self, stats):
return flag_scanners(stats, min_errors=self.min_errors,
min_ratio=self.min_ratio)
# --- extras ------------------------------------------------------------
def extra_summary_rows(self):
c4 = sum(1 for r in self.requests if r.is_client_error)
c5 = sum(1 for r in self.requests if r.is_server_error)
return [
("4xx / 5xx", f"{c4} / {c5}"),
("hosts seen", len({r.host for r in self.requests if r.host})),
("scanner threshold",
f">= {self.min_errors} errors and ratio >= {self.min_ratio}"),
]
def write_extra(self, data_dir: str) -> list[str]:
uas = Counter(r.ua for r in self.requests if r.ua and r.ua != "-")
hosts = Counter(r.host for r in self.requests if r.host)
return [
write_csv(os.path.join(data_dir, "ua_summary.csv"),
["user_agent", "count"], uas.most_common()),
write_csv(os.path.join(data_dir, "host_summary.csv"),
["host", "count"], hosts.most_common()),
]
def main() -> None:
parser = arg_parser(
"analyze NPM proxy logs, flag scanner IPs, export MikroTik rules",
NPM_LOG_PATH, NPM_REPORT_DIR)
parser.add_argument("--min-errors", type=int, default=DEFAULT_MIN_ERRORS,
help=f"minimum error responses to flag (default: {DEFAULT_MIN_ERRORS})")
parser.add_argument("--error-ratio", type=float, default=DEFAULT_ERROR_RATIO,
help=f"minimum error ratio to flag (default: {DEFAULT_ERROR_RATIO})")
parser.add_argument("--full", action="store_true",
help="rescan all logs from the start (ignore incremental state)")
args = parser.parse_args()
NpmAnalyzer(
log_path=args.log_path,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
min_errors=args.min_errors,
error_ratio=args.error_ratio,
).run()
if __name__ == "__main__":
main()
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+21 -21
View File
@@ -1,21 +1,21 @@
2001:4ca0:108:42::24/128
2001:ba0:24c:a500::1/128
2400:8901::2000:62ff:fe9a:e1c2/128
2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128
2600:3000::/32
2600:3c09::2000:5cff:fe99:c802/128
2600:3c15::2000:53ff:fe31:8c0b/128
2600:3c15::2000:9cff:fef0:8ad6/128
2602:fa59::/40
2a00:6340:2008:ec80:64cc:9116:beb2:1931/128
2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128
2a00:6340:2008:ec80:be24:11ff:fe82:2775/128
2a01:2a8:a0dd:1::1012/128
2a01:4f8:c014:7f9e::1/128
2a04:4e40:e000::/48
2a04:c300::/29
2a05:4140:3::37cd/128
2a09:bac1:76c0:460::5e:6a/128
2a09:bac5::/32
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128
2a13:adc0::2ed:89ff:fe58:19c5/128
2001:4ca0:108:42::24/128
2001:ba0:24c:a500::1/128
2400:8901::2000:62ff:fe9a:e1c2/128
2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128
2600:3000::/32
2600:3c09::2000:5cff:fe99:c802/128
2600:3c15::2000:53ff:fe31:8c0b/128
2600:3c15::2000:9cff:fef0:8ad6/128
2602:fa59::/40
2a00:6340:2008:ec80:64cc:9116:beb2:1931/128
2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128
2a00:6340:2008:ec80:be24:11ff:fe82:2775/128
2a01:2a8:a0dd:1::1012/128
2a01:4f8:c014:7f9e::1/128
2a04:4e40:e000::/48
2a04:c300::/29
2a05:4140:3::37cd/128
2a09:bac1:76c0:460::5e:6a/128
2a09:bac5::/32
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128
2a13:adc0::2ed:89ff:fe58:19c5/128
+191 -191
View File
@@ -1,191 +1,191 @@
copyparty log analysis report
generated: 2026-08-06T11:51:47
log path: P:\copyparty
log files: 42
total requests: 25295
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6581
unique denied paths: 2002
denied requests: 6581
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 110
whitelisted IPs seen: 19
block candidates: 112
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /admin.php
51 /.env
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (110) ==
never authenticated -- ban candidates
-- IPv4 (107) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-06T11:51:47
log path: P:\copyparty
log files: 42
total requests: 25295
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6581
unique denied paths: 2002
denied requests: 6581
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 110
whitelisted IPs seen: 19
block candidates: 112
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /admin.php
51 /.env
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (110) ==
never authenticated -- ban candidates
-- IPv4 (107) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+24 -24
View File
@@ -1,24 +1,24 @@
copyparty log analysis report
generated: 2026-08-06T13:03:30
log path: P:\copyparty
log files: 42
total requests: 0
unique IPs: 0 (IPv4 0 / IPv6 0)
error requests: 0
unique denied paths: 0
denied requests: 0
banned IPs: 0
authenticated users: {}
denied-only ips: 0
whitelisted IPs seen: 0
block candidates: 0
== top 30 IPs ==
ip total denied banned first last users whitelist
--------------------------------------------------------
== top 20 denied paths ==
== Denied-only IPs (0) ==
never authenticated -- ban candidates
copyparty log analysis report
generated: 2026-08-06T13:03:30
log path: P:\copyparty
log files: 42
total requests: 0
unique IPs: 0 (IPv4 0 / IPv6 0)
error requests: 0
unique denied paths: 0
denied requests: 0
banned IPs: 0
authenticated users: {}
denied-only ips: 0
whitelisted IPs seen: 0
block candidates: 0
== top 30 IPs ==
ip total denied banned first last users whitelist
--------------------------------------------------------
== top 20 denied paths ==
== Denied-only IPs (0) ==
never authenticated -- ban candidates
+191 -191
View File
@@ -1,191 +1,191 @@
copyparty log analysis report
generated: 2026-08-06T13:21:41
log path: P:\copyparty
log files: 42
total requests: 25295
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6581
unique denied paths: 2002
denied requests: 6581
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 110
whitelisted IPs seen: 19
block candidates: 112
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /admin.php
51 /.env
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (110) ==
never authenticated -- ban candidates
-- IPv4 (107) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-06T13:21:41
log path: P:\copyparty
log files: 42
total requests: 25295
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6581
unique denied paths: 2002
denied requests: 6581
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 110
whitelisted IPs seen: 19
block candidates: 112
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /admin.php
51 /.env
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (110) ==
never authenticated -- ban candidates
-- IPv4 (107) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+24 -24
View File
@@ -1,24 +1,24 @@
copyparty log analysis report
generated: 2026-08-06T14:43:58
log path: P:\copyparty
log files: 42
total requests: 0
unique IPs: 0 (IPv4 0 / IPv6 0)
error requests: 0
unique denied paths: 0
denied requests: 0
banned IPs: 0
authenticated users: {}
denied-only ips: 0
whitelisted IPs seen: 0
block candidates: 0
== top 30 IPs ==
ip total denied banned first last users whitelist
--------------------------------------------------------
== top 20 denied paths ==
== Denied-only IPs (0) ==
never authenticated -- ban candidates
copyparty log analysis report
generated: 2026-08-06T14:43:58
log path: P:\copyparty
log files: 42
total requests: 0
unique IPs: 0 (IPv4 0 / IPv6 0)
error requests: 0
unique denied paths: 0
denied requests: 0
banned IPs: 0
authenticated users: {}
denied-only ips: 0
whitelisted IPs seen: 0
block candidates: 0
== top 30 IPs ==
ip total denied banned first last users whitelist
--------------------------------------------------------
== top 20 denied paths ==
== Denied-only IPs (0) ==
never authenticated -- ban candidates
+192 -192
View File
@@ -1,192 +1,192 @@
copyparty log analysis report
generated: 2026-08-06T15:09:10
log path: P:\copyparty
log files: 42
total requests: 25297
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6582
unique denied paths: 2002
denied requests: 6582
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 111
whitelisted IPs seen: 19
block candidates: 113
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /.env
52 /admin.php
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (111) ==
never authenticated -- ban candidates
-- IPv4 (108) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-06T15:09:10
log path: P:\copyparty
log files: 42
total requests: 25297
unique IPs: 246 (IPv4 202 / IPv6 44)
error requests: 6582
unique denied paths: 2002
denied requests: 6582
banned IPs: 26
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 111
whitelisted IPs seen: 19
block candidates: 113
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
... 216 more IPs omitted
== top 20 denied paths ==
52 /.env
52 /admin.php
44 /wp-content/plugins/hellopress/wp_filemanager.php
44 /this_is_a_new_hello_world.php
35 /1.php
34 /.git/config
33 /classwithtostring.php
33 /222.php
33 /wp-content/uploads
32 /wp-content/admin.php
29 /8.php
27 /file.php
27 /mac.php
26 /wp.php
26 /edit.php
26 /aa.php
25 /images.php
25 /ops.php
24 /f35.php
24 /x.php
== Denied-only IPs (111) ==
never authenticated -- ban candidates
-- IPv4 (108) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
91.92.241.196 11 5 0 13:55:12.175 13:05:16.007 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
157.245.63.62 2 1 0 08:13:33.142 08:13:33.142 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+70 -70
View File
@@ -1,70 +1,70 @@
copyparty log analysis report
generated: 2026-08-07T19:48:03
log path: P:\copyparty
log files: 43
total requests: 1227
unique IPs: 14 (IPv4 14 / IPv6 0)
error requests: 279
unique denied paths: 182
denied requests: 279
banned IPs: 3
authenticated users: {}
denied-only ips: 9
whitelisted IPs seen: 0
block candidates: 9
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
35.196.132.85 6 0 0 14:20:00.708 16:50:00.731 *
91.92.241.196 4 2 0 15:50:20.187 15:50:21.628 *
157.245.63.62 2 1 0 13:04:56.122 13:04:56.122 *
35.227.62.178 2 0 0 15:20:01.556 15:20:01.557 *
35.237.169.55 2 0 0 13:53:04.249 13:53:04.250 *
94.154.43.229 2 1 0 12:53:30.198 12:53:30.198 *
34.85.209.183 1 0 0 15:59:40.864 15:59:40.864 *
94.154.43.178 1 0 0 16:14:12.910 16:14:12.910 *
== top 20 denied paths ==
5 /admin.php
3 /wp-content/plugins/hellopress/wp_filemanager.php
3 /this_is_a_new_hello_world.php
3 /av.php
3 /media.php
3 /images.php
3 /222.php
3 /mac.php
3 /ops.php
3 /8.php
3 /biufile.php
3 /coffexium.php
3 /1.php
3 /classwithtostring.php
3 /wp-ws68.php
3 /mgrr.php
3 /yj09.php
3 /3PJcpMFsD8B.php
3 /BDKR28WP.php
3 /shiny.php
== Denied-only IPs (9) ==
never authenticated -- ban candidates
-- IPv4 (9) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
91.92.241.196 4 2 0 15:50:20.187 15:50:21.628 *
157.245.63.62 2 1 0 13:04:56.122 13:04:56.122 *
94.154.43.229 2 1 0 12:53:30.198 12:53:30.198 *
copyparty log analysis report
generated: 2026-08-07T19:48:03
log path: P:\copyparty
log files: 43
total requests: 1227
unique IPs: 14 (IPv4 14 / IPv6 0)
error requests: 279
unique denied paths: 182
denied requests: 279
banned IPs: 3
authenticated users: {}
denied-only ips: 9
whitelisted IPs seen: 0
block candidates: 9
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
35.196.132.85 6 0 0 14:20:00.708 16:50:00.731 *
91.92.241.196 4 2 0 15:50:20.187 15:50:21.628 *
157.245.63.62 2 1 0 13:04:56.122 13:04:56.122 *
35.227.62.178 2 0 0 15:20:01.556 15:20:01.557 *
35.237.169.55 2 0 0 13:53:04.249 13:53:04.250 *
94.154.43.229 2 1 0 12:53:30.198 12:53:30.198 *
34.85.209.183 1 0 0 15:59:40.864 15:59:40.864 *
94.154.43.178 1 0 0 16:14:12.910 16:14:12.910 *
== top 20 denied paths ==
5 /admin.php
3 /wp-content/plugins/hellopress/wp_filemanager.php
3 /this_is_a_new_hello_world.php
3 /av.php
3 /media.php
3 /images.php
3 /222.php
3 /mac.php
3 /ops.php
3 /8.php
3 /biufile.php
3 /coffexium.php
3 /1.php
3 /classwithtostring.php
3 /wp-ws68.php
3 /mgrr.php
3 /yj09.php
3 /3PJcpMFsD8B.php
3 /BDKR28WP.php
3 /shiny.php
== Denied-only IPs (9) ==
never authenticated -- ban candidates
-- IPv4 (9) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
91.92.241.196 4 2 0 15:50:20.187 15:50:21.628 *
157.245.63.62 2 1 0 13:04:56.122 13:04:56.122 *
94.154.43.229 2 1 0 12:53:30.198 12:53:30.198 *
+198 -198
View File
@@ -1,198 +1,198 @@
copyparty log analysis report
generated: 2026-08-07T19:48:44
log path: P:\copyparty
log files: 43
total requests: 26522
unique IPs: 253 (IPv4 209 / IPv6 44)
error requests: 6860
unique denied paths: 2022
denied requests: 6860
banned IPs: 29
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 117
whitelisted IPs seen: 19
block candidates: 119
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
... 223 more IPs omitted
== top 20 denied paths ==
57 /admin.php
52 /.env
47 /wp-content/plugins/hellopress/wp_filemanager.php
47 /this_is_a_new_hello_world.php
38 /1.php
36 /.git/config
36 /classwithtostring.php
36 /222.php
34 /wp-content/uploads
33 /wp-content/admin.php
32 /8.php
30 /mac.php
28 /aa.php
28 /images.php
28 /ops.php
27 /wp.php
27 /file.php
27 /edit.php
26 /coffexium.php
25 /f35.php
== Denied-only IPs (117) ==
never authenticated -- ban candidates
-- IPv4 (114) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-07T19:48:44
log path: P:\copyparty
log files: 43
total requests: 26522
unique IPs: 253 (IPv4 209 / IPv6 44)
error requests: 6860
unique denied paths: 2022
denied requests: 6860
banned IPs: 29
authenticated users: {'admin': 519, 'corky': 78}
denied-only ips: 117
whitelisted IPs seen: 19
block candidates: 119
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
... 223 more IPs omitted
== top 20 denied paths ==
57 /admin.php
52 /.env
47 /wp-content/plugins/hellopress/wp_filemanager.php
47 /this_is_a_new_hello_world.php
38 /1.php
36 /.git/config
36 /classwithtostring.php
36 /222.php
34 /wp-content/uploads
33 /wp-content/admin.php
32 /8.php
30 /mac.php
28 /aa.php
28 /images.php
28 /ops.php
27 /wp.php
27 /file.php
27 /edit.php
26 /coffexium.php
25 /f35.php
== Denied-only IPs (117) ==
never authenticated -- ban candidates
-- IPv4 (114) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+201 -201
View File
@@ -1,201 +1,201 @@
copyparty log analysis report
generated: 2026-08-08T14:31:22
log path: P:\copyparty
log files: 44
total requests: 26784
unique IPs: 263 (IPv4 218 / IPv6 45)
error requests: 6976
unique denied paths: 2059
denied requests: 6976
banned IPs: 30
authenticated users: {'admin': 523, 'corky': 78}
denied-only ips: 120
whitelisted IPs seen: 21
block candidates: 122
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
... 233 more IPs omitted
== top 20 denied paths ==
58 /admin.php
53 /.env
49 /wp-content/plugins/hellopress/wp_filemanager.php
49 /this_is_a_new_hello_world.php
39 /1.php
37 /classwithtostring.php
37 /222.php
36 /.git/config
34 /wp-content/uploads
33 /8.php
33 /wp-content/admin.php
31 /mac.php
29 /aa.php
29 /images.php
29 /ops.php
28 /wp.php
28 /edit.php
27 /file.php
27 /coffexium.php
25 /f35.php
== Denied-only IPs (120) ==
never authenticated -- ban candidates
-- IPv4 (117) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
172.213.227.73 108 54 0 03:00:13.592 03:00:18.810 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-08T14:31:22
log path: P:\copyparty
log files: 44
total requests: 26784
unique IPs: 263 (IPv4 218 / IPv6 45)
error requests: 6976
unique denied paths: 2059
denied requests: 6976
banned IPs: 30
authenticated users: {'admin': 523, 'corky': 78}
denied-only ips: 120
whitelisted IPs seen: 21
block candidates: 122
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
... 233 more IPs omitted
== top 20 denied paths ==
58 /admin.php
53 /.env
49 /wp-content/plugins/hellopress/wp_filemanager.php
49 /this_is_a_new_hello_world.php
39 /1.php
37 /classwithtostring.php
37 /222.php
36 /.git/config
34 /wp-content/uploads
33 /8.php
33 /wp-content/admin.php
31 /mac.php
29 /aa.php
29 /images.php
29 /ops.php
28 /wp.php
28 /edit.php
27 /file.php
27 /coffexium.php
25 /f35.php
== Denied-only IPs (120) ==
never authenticated -- ban candidates
-- IPv4 (117) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
172.213.227.73 108 54 0 03:00:13.592 03:00:18.810 *
4.223.73.90 106 53 0 19:50:04.916 19:50:11.164 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+210 -210
View File
@@ -1,210 +1,210 @@
copyparty log analysis report
generated: 2026-08-11T11:43:46
log path: \\naspve\nas\projects\copyparty
log files: 48
total requests: 30034
unique IPs: 277 (IPv4 230 / IPv6 47)
error requests: 7738
unique denied paths: 2126
denied requests: 7738
banned IPs: 32
authenticated users: {'admin': 537, 'corky': 78}
denied-only ips: 129
whitelisted IPs seen: 23
block candidates: 131
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
192.168.88.8 1736 0 0 13:31:27.246 09:40:39.082 -
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
... 247 more IPs omitted
== top 20 denied paths ==
67 /admin.php
56 /wp-content/plugins/hellopress/wp_filemanager.php
56 /this_is_a_new_hello_world.php
54 /.env
46 /1.php
44 /classwithtostring.php
42 /222.php
38 /8.php
37 /.git/config
37 /wp-content/uploads
37 /wp-content/admin.php
35 /mac.php
34 /aa.php
34 /images.php
33 /ops.php
32 /wp.php
31 /edit.php
31 /coffexium.php
29 /file.php
29 /inputs.php
== Denied-only IPs (129) ==
never authenticated -- ban candidates
-- IPv4 (126) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
51.107.190.246 274 137 0 01:44:18.242 01:44:28.832 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
74.248.97.169 231 115 0 13:25:17.217 13:25:31.602 *
20.251.112.224 215 107 0 06:52:51.081 06:53:05.602 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
4.223.73.90 204 102 0 19:50:04.916 18:12:09.187 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.218.73.95 98 49 0 04:39:44.907 04:39:46.708 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
82.102.18.116 30 9 10 04:49:33.098 04:49:34.184 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
88.151.32.7 88 9 69 18:43:38.911 19:04:03.160 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
45.148.10.119 11 3 0 02:36:55.008 07:16:27.585 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
176.65.132.38 3 1 0 20:33:22.070 05:08:32.533 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-11T11:43:46
log path: \\naspve\nas\projects\copyparty
log files: 48
total requests: 30034
unique IPs: 277 (IPv4 230 / IPv6 47)
error requests: 7738
unique denied paths: 2126
denied requests: 7738
banned IPs: 32
authenticated users: {'admin': 537, 'corky': 78}
denied-only ips: 129
whitelisted IPs seen: 23
block candidates: 131
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
192.168.88.8 1736 0 0 13:31:27.246 09:40:39.082 -
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
... 247 more IPs omitted
== top 20 denied paths ==
67 /admin.php
56 /wp-content/plugins/hellopress/wp_filemanager.php
56 /this_is_a_new_hello_world.php
54 /.env
46 /1.php
44 /classwithtostring.php
42 /222.php
38 /8.php
37 /.git/config
37 /wp-content/uploads
37 /wp-content/admin.php
35 /mac.php
34 /aa.php
34 /images.php
33 /ops.php
32 /wp.php
31 /edit.php
31 /coffexium.php
29 /file.php
29 /inputs.php
== Denied-only IPs (129) ==
never authenticated -- ban candidates
-- IPv4 (126) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
51.107.190.246 274 137 0 01:44:18.242 01:44:28.832 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
74.248.97.169 231 115 0 13:25:17.217 13:25:31.602 *
20.251.112.224 215 107 0 06:52:51.081 06:53:05.602 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
4.223.73.90 204 102 0 19:50:04.916 18:12:09.187 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.218.73.95 98 49 0 04:39:44.907 04:39:46.708 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
82.102.18.116 30 9 10 04:49:33.098 04:49:34.184 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
88.151.32.7 88 9 69 18:43:38.911 19:04:03.160 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
45.148.10.119 11 3 0 02:36:55.008 07:16:27.585 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
176.65.132.38 3 1 0 20:33:22.070 05:08:32.533 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+210 -210
View File
@@ -1,210 +1,210 @@
copyparty log analysis report
generated: 2026-08-11T11:44:39
log path: \\naspve\nas\projects\copyparty
log files: 48
total requests: 30034
unique IPs: 277 (IPv4 230 / IPv6 47)
error requests: 7738
unique denied paths: 2126
denied requests: 7738
banned IPs: 32
authenticated users: {'admin': 537, 'corky': 78}
denied-only ips: 129
whitelisted IPs seen: 23
block candidates: 131
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
192.168.88.8 1736 0 0 13:31:27.246 09:40:39.082 -
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
... 247 more IPs omitted
== top 20 denied paths ==
67 /admin.php
56 /wp-content/plugins/hellopress/wp_filemanager.php
56 /this_is_a_new_hello_world.php
54 /.env
46 /1.php
44 /classwithtostring.php
42 /222.php
38 /8.php
37 /.git/config
37 /wp-content/uploads
37 /wp-content/admin.php
35 /mac.php
34 /aa.php
34 /images.php
33 /ops.php
32 /wp.php
31 /edit.php
31 /coffexium.php
29 /file.php
29 /inputs.php
== Denied-only IPs (129) ==
never authenticated -- ban candidates
-- IPv4 (126) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
51.107.190.246 274 137 0 01:44:18.242 01:44:28.832 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
74.248.97.169 231 115 0 13:25:17.217 13:25:31.602 *
20.251.112.224 215 107 0 06:52:51.081 06:53:05.602 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
4.223.73.90 204 102 0 19:50:04.916 18:12:09.187 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.218.73.95 98 49 0 04:39:44.907 04:39:46.708 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
82.102.18.116 30 9 10 04:49:33.098 04:49:34.184 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
88.151.32.7 88 9 69 18:43:38.911 19:04:03.160 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
45.148.10.119 11 3 0 02:36:55.008 07:16:27.585 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
176.65.132.38 3 1 0 20:33:22.070 05:08:32.533 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
copyparty log analysis report
generated: 2026-08-11T11:44:39
log path: \\naspve\nas\projects\copyparty
log files: 48
total requests: 30034
unique IPs: 277 (IPv4 230 / IPv6 47)
error requests: 7738
unique denied paths: 2126
denied requests: 7738
banned IPs: 32
authenticated users: {'admin': 537, 'corky': 78}
denied-only ips: 129
whitelisted IPs seen: 23
block candidates: 131
== top 30 IPs ==
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
192.168.88.8 1736 0 0 13:31:27.246 09:40:39.082 -
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
... 247 more IPs omitted
== top 20 denied paths ==
67 /admin.php
56 /wp-content/plugins/hellopress/wp_filemanager.php
56 /this_is_a_new_hello_world.php
54 /.env
46 /1.php
44 /classwithtostring.php
42 /222.php
38 /8.php
37 /.git/config
37 /wp-content/uploads
37 /wp-content/admin.php
35 /mac.php
34 /aa.php
34 /images.php
33 /ops.php
32 /wp.php
31 /edit.php
31 /coffexium.php
29 /file.php
29 /inputs.php
== Denied-only IPs (129) ==
never authenticated -- ban candidates
-- IPv4 (126) --
ip total denied banned first last users whitelist
------------------------------------------------------------------------------------
195.178.110.199 1258 621 0 03:02:41.078 03:02:42.924 *
45.148.10.67 1258 621 0 20:49:39.003 20:49:41.111 *
20.251.48.208 612 306 0 23:50:43.575 17:01:41.376 *
20.215.216.94 516 257 0 16:16:39.439 15:21:39.387 *
20.215.218.234 504 252 0 02:46:27.628 05:35:25.304 *
20.198.120.225 428 214 0 10:07:52.191 10:09:25.008 *
172.213.227.73 382 191 0 03:00:13.592 01:13:37.755 *
20.197.178.120 374 186 0 14:54:24.411 14:54:52.938 *
74.249.245.134 354 177 0 21:27:53.575 21:29:06.182 *
20.151.10.161 325 162 0 17:31:38.451 17:32:27.663 *
20.205.229.184 323 161 0 12:17:54.322 12:18:41.173 *
4.185.41.66 323 161 0 18:18:18.046 18:18:24.319 *
52.184.96.217 323 161 0 20:02:55.760 20:03:44.824 *
172.213.225.181 321 160 0 13:48:04.161 13:48:11.331 *
20.48.236.161 321 160 0 15:11:59.817 15:12:31.060 *
158.158.32.229 316 158 0 12:33:51.566 12:34:03.712 *
20.63.63.128 315 157 0 16:04:22.373 16:04:50.675 *
20.206.67.15 313 156 0 05:56:36.144 05:57:20.412 *
20.215.185.25 300 150 0 08:18:05.984 08:19:09.190 *
20.203.243.122 294 147 0 03:58:39.580 03:58:55.359 *
20.52.171.102 292 146 0 20:01:30.635 20:01:36.800 *
20.226.26.5 286 143 0 06:33:33.891 06:34:07.483 *
68.221.130.241 278 139 0 08:28:43.979 08:28:50.496 *
20.100.172.153 275 137 0 09:10:06.751 09:10:17.835 *
51.107.190.246 274 137 0 01:44:18.242 01:44:28.832 *
74.248.33.172 257 128 0 23:32:36.049 23:32:42.718 *
20.203.179.12 250 125 0 17:33:20.484 17:33:29.742 *
20.113.142.140 231 115 0 07:47:47.716 07:48:00.044 *
74.248.97.169 231 115 0 13:25:17.217 13:25:31.602 *
20.251.112.224 215 107 0 06:52:51.081 06:53:05.602 *
158.158.105.63 208 104 0 11:24:12.912 23:00:49.043 *
4.223.71.149 209 104 0 00:26:55.320 00:27:19.244 *
4.223.73.90 204 102 0 19:50:04.916 18:12:09.187 *
135.225.93.215 203 101 0 02:32:24.496 02:32:32.326 *
20.9.85.55 203 101 0 15:43:36.450 15:44:20.170 *
20.91.208.34 203 101 0 22:07:01.428 22:07:20.883 *
52.238.192.78 203 101 0 00:04:31.589 00:05:07.114 *
172.213.208.13 192 96 0 13:27:56.743 19:14:00.938 *
172.213.244.85 165 82 0 17:01:49.042 17:01:52.331 *
20.206.105.145 157 78 0 04:06:08.085 04:06:29.772 *
51.120.83.160 144 72 0 15:40:29.699 15:40:39.446 *
172.213.153.79 114 57 0 18:40:13.799 18:40:20.149 *
20.91.239.158 114 57 0 13:42:20.392 13:42:24.986 *
4.232.185.87 110 53 0 21:23:31.012 21:23:33.019 *
20.218.73.95 98 49 0 04:39:44.907 04:39:46.708 *
20.91.203.45 94 47 0 16:27:01.288 16:27:10.455 *
20.197.192.193 88 44 0 13:45:32.377 13:45:43.108 *
74.248.24.145 74 37 0 09:21:37.839 09:21:43.127 *
172.213.144.209 70 35 0 07:52:16.066 07:52:17.778 *
35.198.180.224 46 22 0 14:14:37.617 14:14:48.930 *
45.148.10.62 98 22 40 07:53:03.360 03:15:12.651 *
45.148.10.244 109 18 70 04:53:37.585 09:56:59.103 *
45.148.10.120 33 16 0 14:24:06.542 17:06:11.688 *
34.39.210.94 24 12 0 19:31:07.030 19:31:07.101 *
195.178.110.31 49 11 20 02:27:56.164 02:27:58.425 *
195.178.110.223 37 10 13 01:31:40.464 01:56:49.503 *
34.95.239.96 20 10 0 11:25:18.487 11:25:18.532 *
107.173.254.55 29 9 9 07:04:56.768 07:05:17.755 *
136.108.11.195 25 9 7 08:33:11.182 08:33:13.921 *
139.59.118.17 180 9 157 08:21:30.247 08:22:03.812 *
146.70.40.68 30 9 10 18:55:47.310 18:55:48.145 *
147.182.149.75 40 9 21 21:50:17.837 21:50:45.474 *
16.146.99.254 279 9 256 12:11:20.725 12:12:09.790 *
163.7.11.71 93 9 72 07:24:55.235 07:25:05.144 *
167.99.181.249 40 9 21 21:50:26.091 21:51:01.239 *
18.142.90.109 279 9 256 17:06:23.216 17:07:15.117 *
18.227.73.7 392 9 363 22:00:31.465 22:01:33.982 *
207.175.159.248 25 9 7 03:52:06.643 03:52:07.542 *
207.175.20.232 25 9 7 09:43:00.775 09:43:03.604 *
209.99.189.190 77 9 59 17:04:48.190 09:53:52.093 *
3.79.41.12 286 9 263 04:20:16.234 04:20:22.797 *
34.105.30.251 29 9 9 15:55:43.824 15:55:49.547 *
34.23.104.90 25 9 7 14:40:59.025 14:41:01.713 *
34.242.226.103 286 9 263 06:52:40.299 06:52:54.689 *
34.9.173.20 245 9 224 16:55:22.164 16:55:30.344 *
45.67.85.190 32 9 11 19:41:44.132 19:41:46.806 *
54.163.186.39 286 9 263 01:39:29.740 01:40:00.874 *
82.102.18.116 30 9 10 04:49:33.098 04:49:34.184 *
85.204.70.100 30 9 10 13:55:11.862 13:55:12.567 *
88.151.32.7 88 9 69 18:43:38.911 19:04:03.160 *
91.192.10.86 31 9 10 13:38:54.986 13:38:56.159 *
93.123.109.101 4320 9 4264 00:35:05.539 00:40:32.578 *
185.93.89.147 3762 8 0 19:07:14.620 08:52:41.657 *
195.178.110.155 57 8 0 09:10:16.072 09:10:19.329 *
45.148.10.194 58 8 0 15:46:42.822 15:46:45.473 *
45.148.10.247 57 8 0 00:58:56.398 00:58:59.599 *
72.146.20.230 14 7 0 03:01:31.244 03:01:31.427 *
91.92.241.196 15 7 0 13:55:12.175 15:50:21.628 *
209.99.189.152 13 6 0 18:03:04.845 18:03:12.906 *
34.140.123.172 434 6 411 21:34:17.485 21:35:45.084 *
162.243.79.174 11 5 0 12:20:28.790 12:20:40.350 *
51.79.208.246 10 5 0 13:50:27.669 13:50:29.418 *
94.154.43.184 10 5 0 11:23:26.214 09:31:40.319 *
195.178.110.211 8 4 0 19:35:03.504 20:22:13.338 *
45.148.10.119 11 3 0 02:36:55.008 07:16:27.585 *
157.245.63.62 4 2 0 08:13:33.142 13:04:56.122 *
163.7.13.115 5 2 0 14:06:27.842 14:06:29.745 *
45.138.16.114 5 2 0 03:09:59.971 03:10:00.217 *
45.148.10.95 4 2 0 21:05:26.356 14:40:26.566 *
91.92.41.115 8 2 0 14:44:48.975 14:44:54.158 *
94.154.43.179 5 2 0 13:27:23.753 04:38:17.921 *
107.170.9.103 2 1 0 00:19:26.062 00:19:26.062 *
129.212.237.196 2 1 0 09:23:08.470 09:23:08.471 *
134.209.162.128 2 1 0 00:43:12.731 00:43:12.731 *
158.101.144.198 2 1 0 14:30:06.125 14:30:06.125 *
165.245.185.158 2 1 0 09:20:47.477 09:20:47.477 *
176.65.132.38 3 1 0 20:33:22.070 05:08:32.533 *
195.178.110.159 2 1 0 20:41:43.691 20:41:43.691 *
2.57.122.173 2 1 0 12:10:19.177 12:10:19.177 *
23.180.120.147 4 1 0 13:53:30.303 13:53:30.473 *
31.58.51.184 4 1 0 15:07:53.176 15:07:58.514 *
34.125.42.15 2 1 0 21:39:44.709 21:39:44.709 *
34.91.243.226 2 1 0 19:51:57.606 19:51:57.606 *
35.231.100.82 2 1 0 15:36:23.715 15:36:23.715 *
35.233.191.179 2 1 0 00:16:07.188 00:16:07.199 *
35.95.56.230 3 1 0 02:29:40.010 02:29:40.562 *
43.98.201.177 2 1 0 01:01:05.988 01:01:05.988 *
45.139.104.172 2 1 0 03:14:49.950 03:14:49.950 *
64.226.123.37 2 1 0 21:33:32.148 21:33:32.148 *
8.229.130.50 2 1 0 19:23:37.001 19:23:37.002 *
93.123.109.167 2 1 0 04:39:35.474 04:39:35.474 *
94.154.43.183 3 1 0 21:50:39.582 00:01:42.127 *
94.154.43.185 3 1 0 01:40:53.903 04:02:34.085 *
94.154.43.186 3 1 0 21:07:26.439 13:43:18.923 *
94.154.43.188 5 1 0 02:45:01.636 11:09:54.264 *
94.154.43.229 4 1 0 14:35:26.801 12:53:30.198 *
-- IPv6 (3) --
ip total denied banned first last users whitelist
--------------------------------------------------------------------------------------------------------
2a04:4e40:e000:0:d09:97ab:43b1:a59a 4 2 0 14:41:30.905 14:41:30.922 *
2600:3c15::2000:53ff:fe31:8c0b 2 1 0 12:35:18.643 12:35:18.643 *
2602:fa59:10:a3a::1 2 1 0 02:10:02.531 02:10:02.532 *
+3 -3
View File
@@ -1,4 +1,4 @@
{
"admin": 537,
"corky": 78
{
"admin": 537,
"corky": 78
}
+32 -32
View File
@@ -1,32 +1,32 @@
3.79.41.12
16.146.99.254
18.142.90.109
18.227.73.7
34.9.173.20
34.23.104.90
34.105.30.251
34.140.123.172
34.242.226.103
45.67.85.190
45.148.10.62
45.148.10.244
54.163.186.39
82.102.18.116
85.204.70.100
88.151.32.7
91.192.10.86
93.123.109.101
107.173.254.55
136.108.11.195
139.59.118.17
146.70.40.68
147.182.149.75
163.7.11.71
167.99.181.249
195.178.110.31
195.178.110.104
195.178.110.135
195.178.110.223
207.175.20.232
207.175.159.248
209.99.189.190
3.79.41.12
16.146.99.254
18.142.90.109
18.227.73.7
34.9.173.20
34.23.104.90
34.105.30.251
34.140.123.172
34.242.226.103
45.67.85.190
45.148.10.62
45.148.10.244
54.163.186.39
82.102.18.116
85.204.70.100
88.151.32.7
91.192.10.86
93.123.109.101
107.173.254.55
136.108.11.195
139.59.118.17
146.70.40.68
147.182.149.75
163.7.11.71
167.99.181.249
195.178.110.31
195.178.110.104
195.178.110.135
195.178.110.223
207.175.20.232
207.175.159.248
209.99.189.190
+128 -128
View File
@@ -1,128 +1,128 @@
2.57.122.173
3.79.41.12
4.185.41.66
4.223.71.149
4.223.73.90
4.232.185.87
8.229.130.50
16.146.99.254
18.142.90.109
18.227.73.7
20.9.85.55
20.48.236.161
20.52.171.102
20.63.63.128
20.91.203.45
20.91.208.34
20.91.239.158
20.100.172.153
20.113.142.140
20.151.10.161
20.197.178.120
20.197.192.193
20.198.120.225
20.203.179.12
20.203.243.122
20.205.229.184
20.206.67.15
20.206.105.145
20.215.185.25
20.215.216.94
20.215.218.234
20.218.73.95
20.226.26.5
20.251.48.208
20.251.112.224
23.180.120.147
31.58.51.184
34.9.173.20
34.23.104.90
34.39.210.94
34.91.243.226
34.95.239.96
34.105.30.251
34.125.42.15
34.140.123.172
34.242.226.103
35.95.56.230
35.198.180.224
35.231.100.82
35.233.191.179
43.98.201.177
45.67.85.190
45.138.16.114
45.139.104.172
45.148.10.62
45.148.10.67
45.148.10.95
45.148.10.119
45.148.10.120
45.148.10.194
45.148.10.244
45.148.10.247
51.79.208.246
51.107.190.246
51.120.83.160
52.184.96.217
52.238.192.78
54.163.186.39
64.226.123.37
68.221.130.241
72.146.20.230
74.248.24.145
74.248.33.172
74.248.97.169
74.249.245.134
82.102.18.116
85.204.70.100
88.151.32.7
91.92.41.115
91.92.241.196
91.192.10.86
93.123.109.101
93.123.109.167
94.154.43.179
94.154.43.183
94.154.43.184
94.154.43.185
94.154.43.186
94.154.43.188
94.154.43.229
107.170.9.103
107.173.254.55
129.212.237.196
134.209.162.128
135.225.93.215
136.108.11.195
139.59.118.17
146.70.40.68
147.182.149.75
157.245.63.62
158.101.144.198
158.158.32.229
158.158.105.63
162.243.79.174
163.7.11.71
163.7.13.115
165.245.185.158
167.99.181.249
172.213.144.209
172.213.153.79
172.213.208.13
172.213.225.181
172.213.227.73
172.213.244.85
176.65.132.38
185.93.89.147
195.178.110.31
195.178.110.104
195.178.110.135
195.178.110.155
195.178.110.159
195.178.110.199
195.178.110.211
195.178.110.223
207.175.20.232
207.175.159.248
209.99.189.152
209.99.189.190
2.57.122.173
3.79.41.12
4.185.41.66
4.223.71.149
4.223.73.90
4.232.185.87
8.229.130.50
16.146.99.254
18.142.90.109
18.227.73.7
20.9.85.55
20.48.236.161
20.52.171.102
20.63.63.128
20.91.203.45
20.91.208.34
20.91.239.158
20.100.172.153
20.113.142.140
20.151.10.161
20.197.178.120
20.197.192.193
20.198.120.225
20.203.179.12
20.203.243.122
20.205.229.184
20.206.67.15
20.206.105.145
20.215.185.25
20.215.216.94
20.215.218.234
20.218.73.95
20.226.26.5
20.251.48.208
20.251.112.224
23.180.120.147
31.58.51.184
34.9.173.20
34.23.104.90
34.39.210.94
34.91.243.226
34.95.239.96
34.105.30.251
34.125.42.15
34.140.123.172
34.242.226.103
35.95.56.230
35.198.180.224
35.231.100.82
35.233.191.179
43.98.201.177
45.67.85.190
45.138.16.114
45.139.104.172
45.148.10.62
45.148.10.67
45.148.10.95
45.148.10.119
45.148.10.120
45.148.10.194
45.148.10.244
45.148.10.247
51.79.208.246
51.107.190.246
51.120.83.160
52.184.96.217
52.238.192.78
54.163.186.39
64.226.123.37
68.221.130.241
72.146.20.230
74.248.24.145
74.248.33.172
74.248.97.169
74.249.245.134
82.102.18.116
85.204.70.100
88.151.32.7
91.92.41.115
91.92.241.196
91.192.10.86
93.123.109.101
93.123.109.167
94.154.43.179
94.154.43.183
94.154.43.184
94.154.43.185
94.154.43.186
94.154.43.188
94.154.43.229
107.170.9.103
107.173.254.55
129.212.237.196
134.209.162.128
135.225.93.215
136.108.11.195
139.59.118.17
146.70.40.68
147.182.149.75
157.245.63.62
158.101.144.198
158.158.32.229
158.158.105.63
162.243.79.174
163.7.11.71
163.7.13.115
165.245.185.158
167.99.181.249
172.213.144.209
172.213.153.79
172.213.208.13
172.213.225.181
172.213.227.73
172.213.244.85
176.65.132.38
185.93.89.147
195.178.110.31
195.178.110.104
195.178.110.135
195.178.110.155
195.178.110.159
195.178.110.199
195.178.110.211
195.178.110.223
207.175.20.232
207.175.159.248
209.99.189.152
209.99.189.190
+3 -3
View File
@@ -1,3 +1,3 @@
2600:3c15::2000:53ff:fe31:8c0b
2602:fa59:10:a3a::1
2a04:4e40:e000:0:d09:97ab:43b1:a59a
2600:3c15::2000:53ff:fe31:8c0b
2602:fa59:10:a3a::1
2a04:4e40:e000:0:d09:97ab:43b1:a59a
+126 -126
View File
@@ -1,126 +1,126 @@
195.178.110.199 # denied=621 total=1258 first=03:02:41.078 last=03:02:42.924
45.148.10.67 # denied=621 total=1258 first=20:49:39.003 last=20:49:41.111
20.251.48.208 # denied=306 total=612 first=23:50:43.575 last=17:01:41.376
20.215.216.94 # denied=257 total=516 first=16:16:39.439 last=15:21:39.387
20.215.218.234 # denied=252 total=504 first=02:46:27.628 last=05:35:25.304
20.198.120.225 # denied=214 total=428 first=10:07:52.191 last=10:09:25.008
172.213.227.73 # denied=191 total=382 first=03:00:13.592 last=01:13:37.755
20.197.178.120 # denied=186 total=374 first=14:54:24.411 last=14:54:52.938
74.249.245.134 # denied=177 total=354 first=21:27:53.575 last=21:29:06.182
20.151.10.161 # denied=162 total=325 first=17:31:38.451 last=17:32:27.663
20.205.229.184 # denied=161 total=323 first=12:17:54.322 last=12:18:41.173
4.185.41.66 # denied=161 total=323 first=18:18:18.046 last=18:18:24.319
52.184.96.217 # denied=161 total=323 first=20:02:55.760 last=20:03:44.824
172.213.225.181 # denied=160 total=321 first=13:48:04.161 last=13:48:11.331
20.48.236.161 # denied=160 total=321 first=15:11:59.817 last=15:12:31.060
158.158.32.229 # denied=158 total=316 first=12:33:51.566 last=12:34:03.712
20.63.63.128 # denied=157 total=315 first=16:04:22.373 last=16:04:50.675
20.206.67.15 # denied=156 total=313 first=05:56:36.144 last=05:57:20.412
20.215.185.25 # denied=150 total=300 first=08:18:05.984 last=08:19:09.190
20.203.243.122 # denied=147 total=294 first=03:58:39.580 last=03:58:55.359
20.52.171.102 # denied=146 total=292 first=20:01:30.635 last=20:01:36.800
20.226.26.5 # denied=143 total=286 first=06:33:33.891 last=06:34:07.483
68.221.130.241 # denied=139 total=278 first=08:28:43.979 last=08:28:50.496
20.100.172.153 # denied=137 total=275 first=09:10:06.751 last=09:10:17.835
51.107.190.246 # denied=137 total=274 first=01:44:18.242 last=01:44:28.832
74.248.33.172 # denied=128 total=257 first=23:32:36.049 last=23:32:42.718
20.203.179.12 # denied=125 total=250 first=17:33:20.484 last=17:33:29.742
20.113.142.140 # denied=115 total=231 first=07:47:47.716 last=07:48:00.044
74.248.97.169 # denied=115 total=231 first=13:25:17.217 last=13:25:31.602
20.251.112.224 # denied=107 total=215 first=06:52:51.081 last=06:53:05.602
158.158.105.63 # denied=104 total=208 first=11:24:12.912 last=23:00:49.043
4.223.71.149 # denied=104 total=209 first=00:26:55.320 last=00:27:19.244
4.223.73.90 # denied=102 total=204 first=19:50:04.916 last=18:12:09.187
135.225.93.215 # denied=101 total=203 first=02:32:24.496 last=02:32:32.326
20.9.85.55 # denied=101 total=203 first=15:43:36.450 last=15:44:20.170
20.91.208.34 # denied=101 total=203 first=22:07:01.428 last=22:07:20.883
52.238.192.78 # denied=101 total=203 first=00:04:31.589 last=00:05:07.114
172.213.208.13 # denied=96 total=192 first=13:27:56.743 last=19:14:00.938
172.213.244.85 # denied=82 total=165 first=17:01:49.042 last=17:01:52.331
20.206.105.145 # denied=78 total=157 first=04:06:08.085 last=04:06:29.772
51.120.83.160 # denied=72 total=144 first=15:40:29.699 last=15:40:39.446
172.213.153.79 # denied=57 total=114 first=18:40:13.799 last=18:40:20.149
20.91.239.158 # denied=57 total=114 first=13:42:20.392 last=13:42:24.986
4.232.185.87 # denied=53 total=110 first=21:23:31.012 last=21:23:33.019
20.218.73.95 # denied=49 total=98 first=04:39:44.907 last=04:39:46.708
20.91.203.45 # denied=47 total=94 first=16:27:01.288 last=16:27:10.455
20.197.192.193 # denied=44 total=88 first=13:45:32.377 last=13:45:43.108
74.248.24.145 # denied=37 total=74 first=09:21:37.839 last=09:21:43.127
172.213.144.209 # denied=35 total=70 first=07:52:16.066 last=07:52:17.778
35.198.180.224 # denied=22 total=46 first=14:14:37.617 last=14:14:48.930
45.148.10.62 # denied=22 total=98 first=07:53:03.360 last=03:15:12.651
45.148.10.244 # denied=18 total=109 first=04:53:37.585 last=09:56:59.103
45.148.10.120 # denied=16 total=33 first=14:24:06.542 last=17:06:11.688
34.39.210.94 # denied=12 total=24 first=19:31:07.030 last=19:31:07.101
195.178.110.31 # denied=11 total=49 first=02:27:56.164 last=02:27:58.425
195.178.110.223 # denied=10 total=37 first=01:31:40.464 last=01:56:49.503
34.95.239.96 # denied=10 total=20 first=11:25:18.487 last=11:25:18.532
107.173.254.55 # denied=9 total=29 first=07:04:56.768 last=07:05:17.755
136.108.11.195 # denied=9 total=25 first=08:33:11.182 last=08:33:13.921
139.59.118.17 # denied=9 total=180 first=08:21:30.247 last=08:22:03.812
146.70.40.68 # denied=9 total=30 first=18:55:47.310 last=18:55:48.145
147.182.149.75 # denied=9 total=40 first=21:50:17.837 last=21:50:45.474
16.146.99.254 # denied=9 total=279 first=12:11:20.725 last=12:12:09.790
163.7.11.71 # denied=9 total=93 first=07:24:55.235 last=07:25:05.144
167.99.181.249 # denied=9 total=40 first=21:50:26.091 last=21:51:01.239
18.142.90.109 # denied=9 total=279 first=17:06:23.216 last=17:07:15.117
18.227.73.7 # denied=9 total=392 first=22:00:31.465 last=22:01:33.982
207.175.159.248 # denied=9 total=25 first=03:52:06.643 last=03:52:07.542
207.175.20.232 # denied=9 total=25 first=09:43:00.775 last=09:43:03.604
209.99.189.190 # denied=9 total=77 first=17:04:48.190 last=09:53:52.093
3.79.41.12 # denied=9 total=286 first=04:20:16.234 last=04:20:22.797
34.105.30.251 # denied=9 total=29 first=15:55:43.824 last=15:55:49.547
34.23.104.90 # denied=9 total=25 first=14:40:59.025 last=14:41:01.713
34.242.226.103 # denied=9 total=286 first=06:52:40.299 last=06:52:54.689
34.9.173.20 # denied=9 total=245 first=16:55:22.164 last=16:55:30.344
45.67.85.190 # denied=9 total=32 first=19:41:44.132 last=19:41:46.806
54.163.186.39 # denied=9 total=286 first=01:39:29.740 last=01:40:00.874
82.102.18.116 # denied=9 total=30 first=04:49:33.098 last=04:49:34.184
85.204.70.100 # denied=9 total=30 first=13:55:11.862 last=13:55:12.567
88.151.32.7 # denied=9 total=88 first=18:43:38.911 last=19:04:03.160
91.192.10.86 # denied=9 total=31 first=13:38:54.986 last=13:38:56.159
93.123.109.101 # denied=9 total=4320 first=00:35:05.539 last=00:40:32.578
185.93.89.147 # denied=8 total=3762 first=19:07:14.620 last=08:52:41.657
195.178.110.155 # denied=8 total=57 first=09:10:16.072 last=09:10:19.329
45.148.10.194 # denied=8 total=58 first=15:46:42.822 last=15:46:45.473
45.148.10.247 # denied=8 total=57 first=00:58:56.398 last=00:58:59.599
72.146.20.230 # denied=7 total=14 first=03:01:31.244 last=03:01:31.427
91.92.241.196 # denied=7 total=15 first=13:55:12.175 last=15:50:21.628
209.99.189.152 # denied=6 total=13 first=18:03:04.845 last=18:03:12.906
34.140.123.172 # denied=6 total=434 first=21:34:17.485 last=21:35:45.084
162.243.79.174 # denied=5 total=11 first=12:20:28.790 last=12:20:40.350
51.79.208.246 # denied=5 total=10 first=13:50:27.669 last=13:50:29.418
94.154.43.184 # denied=5 total=10 first=11:23:26.214 last=09:31:40.319
195.178.110.211 # denied=4 total=8 first=19:35:03.504 last=20:22:13.338
45.148.10.119 # denied=3 total=11 first=02:36:55.008 last=07:16:27.585
157.245.63.62 # denied=2 total=4 first=08:13:33.142 last=13:04:56.122
163.7.13.115 # denied=2 total=5 first=14:06:27.842 last=14:06:29.745
45.138.16.114 # denied=2 total=5 first=03:09:59.971 last=03:10:00.217
45.148.10.95 # denied=2 total=4 first=21:05:26.356 last=14:40:26.566
91.92.41.115 # denied=2 total=8 first=14:44:48.975 last=14:44:54.158
94.154.43.179 # denied=2 total=5 first=13:27:23.753 last=04:38:17.921
107.170.9.103 # denied=1 total=2 first=00:19:26.062 last=00:19:26.062
129.212.237.196 # denied=1 total=2 first=09:23:08.470 last=09:23:08.471
134.209.162.128 # denied=1 total=2 first=00:43:12.731 last=00:43:12.731
158.101.144.198 # denied=1 total=2 first=14:30:06.125 last=14:30:06.125
165.245.185.158 # denied=1 total=2 first=09:20:47.477 last=09:20:47.477
176.65.132.38 # denied=1 total=3 first=20:33:22.070 last=05:08:32.533
195.178.110.159 # denied=1 total=2 first=20:41:43.691 last=20:41:43.691
2.57.122.173 # denied=1 total=2 first=12:10:19.177 last=12:10:19.177
23.180.120.147 # denied=1 total=4 first=13:53:30.303 last=13:53:30.473
31.58.51.184 # denied=1 total=4 first=15:07:53.176 last=15:07:58.514
34.125.42.15 # denied=1 total=2 first=21:39:44.709 last=21:39:44.709
34.91.243.226 # denied=1 total=2 first=19:51:57.606 last=19:51:57.606
35.231.100.82 # denied=1 total=2 first=15:36:23.715 last=15:36:23.715
35.233.191.179 # denied=1 total=2 first=00:16:07.188 last=00:16:07.199
35.95.56.230 # denied=1 total=3 first=02:29:40.010 last=02:29:40.562
43.98.201.177 # denied=1 total=2 first=01:01:05.988 last=01:01:05.988
45.139.104.172 # denied=1 total=2 first=03:14:49.950 last=03:14:49.950
64.226.123.37 # denied=1 total=2 first=21:33:32.148 last=21:33:32.148
8.229.130.50 # denied=1 total=2 first=19:23:37.001 last=19:23:37.002
93.123.109.167 # denied=1 total=2 first=04:39:35.474 last=04:39:35.474
94.154.43.183 # denied=1 total=3 first=21:50:39.582 last=00:01:42.127
94.154.43.185 # denied=1 total=3 first=01:40:53.903 last=04:02:34.085
94.154.43.186 # denied=1 total=3 first=21:07:26.439 last=13:43:18.923
94.154.43.188 # denied=1 total=5 first=02:45:01.636 last=11:09:54.264
94.154.43.229 # denied=1 total=4 first=14:35:26.801 last=12:53:30.198
195.178.110.199 # denied=621 total=1258 first=03:02:41.078 last=03:02:42.924
45.148.10.67 # denied=621 total=1258 first=20:49:39.003 last=20:49:41.111
20.251.48.208 # denied=306 total=612 first=23:50:43.575 last=17:01:41.376
20.215.216.94 # denied=257 total=516 first=16:16:39.439 last=15:21:39.387
20.215.218.234 # denied=252 total=504 first=02:46:27.628 last=05:35:25.304
20.198.120.225 # denied=214 total=428 first=10:07:52.191 last=10:09:25.008
172.213.227.73 # denied=191 total=382 first=03:00:13.592 last=01:13:37.755
20.197.178.120 # denied=186 total=374 first=14:54:24.411 last=14:54:52.938
74.249.245.134 # denied=177 total=354 first=21:27:53.575 last=21:29:06.182
20.151.10.161 # denied=162 total=325 first=17:31:38.451 last=17:32:27.663
20.205.229.184 # denied=161 total=323 first=12:17:54.322 last=12:18:41.173
4.185.41.66 # denied=161 total=323 first=18:18:18.046 last=18:18:24.319
52.184.96.217 # denied=161 total=323 first=20:02:55.760 last=20:03:44.824
172.213.225.181 # denied=160 total=321 first=13:48:04.161 last=13:48:11.331
20.48.236.161 # denied=160 total=321 first=15:11:59.817 last=15:12:31.060
158.158.32.229 # denied=158 total=316 first=12:33:51.566 last=12:34:03.712
20.63.63.128 # denied=157 total=315 first=16:04:22.373 last=16:04:50.675
20.206.67.15 # denied=156 total=313 first=05:56:36.144 last=05:57:20.412
20.215.185.25 # denied=150 total=300 first=08:18:05.984 last=08:19:09.190
20.203.243.122 # denied=147 total=294 first=03:58:39.580 last=03:58:55.359
20.52.171.102 # denied=146 total=292 first=20:01:30.635 last=20:01:36.800
20.226.26.5 # denied=143 total=286 first=06:33:33.891 last=06:34:07.483
68.221.130.241 # denied=139 total=278 first=08:28:43.979 last=08:28:50.496
20.100.172.153 # denied=137 total=275 first=09:10:06.751 last=09:10:17.835
51.107.190.246 # denied=137 total=274 first=01:44:18.242 last=01:44:28.832
74.248.33.172 # denied=128 total=257 first=23:32:36.049 last=23:32:42.718
20.203.179.12 # denied=125 total=250 first=17:33:20.484 last=17:33:29.742
20.113.142.140 # denied=115 total=231 first=07:47:47.716 last=07:48:00.044
74.248.97.169 # denied=115 total=231 first=13:25:17.217 last=13:25:31.602
20.251.112.224 # denied=107 total=215 first=06:52:51.081 last=06:53:05.602
158.158.105.63 # denied=104 total=208 first=11:24:12.912 last=23:00:49.043
4.223.71.149 # denied=104 total=209 first=00:26:55.320 last=00:27:19.244
4.223.73.90 # denied=102 total=204 first=19:50:04.916 last=18:12:09.187
135.225.93.215 # denied=101 total=203 first=02:32:24.496 last=02:32:32.326
20.9.85.55 # denied=101 total=203 first=15:43:36.450 last=15:44:20.170
20.91.208.34 # denied=101 total=203 first=22:07:01.428 last=22:07:20.883
52.238.192.78 # denied=101 total=203 first=00:04:31.589 last=00:05:07.114
172.213.208.13 # denied=96 total=192 first=13:27:56.743 last=19:14:00.938
172.213.244.85 # denied=82 total=165 first=17:01:49.042 last=17:01:52.331
20.206.105.145 # denied=78 total=157 first=04:06:08.085 last=04:06:29.772
51.120.83.160 # denied=72 total=144 first=15:40:29.699 last=15:40:39.446
172.213.153.79 # denied=57 total=114 first=18:40:13.799 last=18:40:20.149
20.91.239.158 # denied=57 total=114 first=13:42:20.392 last=13:42:24.986
4.232.185.87 # denied=53 total=110 first=21:23:31.012 last=21:23:33.019
20.218.73.95 # denied=49 total=98 first=04:39:44.907 last=04:39:46.708
20.91.203.45 # denied=47 total=94 first=16:27:01.288 last=16:27:10.455
20.197.192.193 # denied=44 total=88 first=13:45:32.377 last=13:45:43.108
74.248.24.145 # denied=37 total=74 first=09:21:37.839 last=09:21:43.127
172.213.144.209 # denied=35 total=70 first=07:52:16.066 last=07:52:17.778
35.198.180.224 # denied=22 total=46 first=14:14:37.617 last=14:14:48.930
45.148.10.62 # denied=22 total=98 first=07:53:03.360 last=03:15:12.651
45.148.10.244 # denied=18 total=109 first=04:53:37.585 last=09:56:59.103
45.148.10.120 # denied=16 total=33 first=14:24:06.542 last=17:06:11.688
34.39.210.94 # denied=12 total=24 first=19:31:07.030 last=19:31:07.101
195.178.110.31 # denied=11 total=49 first=02:27:56.164 last=02:27:58.425
195.178.110.223 # denied=10 total=37 first=01:31:40.464 last=01:56:49.503
34.95.239.96 # denied=10 total=20 first=11:25:18.487 last=11:25:18.532
107.173.254.55 # denied=9 total=29 first=07:04:56.768 last=07:05:17.755
136.108.11.195 # denied=9 total=25 first=08:33:11.182 last=08:33:13.921
139.59.118.17 # denied=9 total=180 first=08:21:30.247 last=08:22:03.812
146.70.40.68 # denied=9 total=30 first=18:55:47.310 last=18:55:48.145
147.182.149.75 # denied=9 total=40 first=21:50:17.837 last=21:50:45.474
16.146.99.254 # denied=9 total=279 first=12:11:20.725 last=12:12:09.790
163.7.11.71 # denied=9 total=93 first=07:24:55.235 last=07:25:05.144
167.99.181.249 # denied=9 total=40 first=21:50:26.091 last=21:51:01.239
18.142.90.109 # denied=9 total=279 first=17:06:23.216 last=17:07:15.117
18.227.73.7 # denied=9 total=392 first=22:00:31.465 last=22:01:33.982
207.175.159.248 # denied=9 total=25 first=03:52:06.643 last=03:52:07.542
207.175.20.232 # denied=9 total=25 first=09:43:00.775 last=09:43:03.604
209.99.189.190 # denied=9 total=77 first=17:04:48.190 last=09:53:52.093
3.79.41.12 # denied=9 total=286 first=04:20:16.234 last=04:20:22.797
34.105.30.251 # denied=9 total=29 first=15:55:43.824 last=15:55:49.547
34.23.104.90 # denied=9 total=25 first=14:40:59.025 last=14:41:01.713
34.242.226.103 # denied=9 total=286 first=06:52:40.299 last=06:52:54.689
34.9.173.20 # denied=9 total=245 first=16:55:22.164 last=16:55:30.344
45.67.85.190 # denied=9 total=32 first=19:41:44.132 last=19:41:46.806
54.163.186.39 # denied=9 total=286 first=01:39:29.740 last=01:40:00.874
82.102.18.116 # denied=9 total=30 first=04:49:33.098 last=04:49:34.184
85.204.70.100 # denied=9 total=30 first=13:55:11.862 last=13:55:12.567
88.151.32.7 # denied=9 total=88 first=18:43:38.911 last=19:04:03.160
91.192.10.86 # denied=9 total=31 first=13:38:54.986 last=13:38:56.159
93.123.109.101 # denied=9 total=4320 first=00:35:05.539 last=00:40:32.578
185.93.89.147 # denied=8 total=3762 first=19:07:14.620 last=08:52:41.657
195.178.110.155 # denied=8 total=57 first=09:10:16.072 last=09:10:19.329
45.148.10.194 # denied=8 total=58 first=15:46:42.822 last=15:46:45.473
45.148.10.247 # denied=8 total=57 first=00:58:56.398 last=00:58:59.599
72.146.20.230 # denied=7 total=14 first=03:01:31.244 last=03:01:31.427
91.92.241.196 # denied=7 total=15 first=13:55:12.175 last=15:50:21.628
209.99.189.152 # denied=6 total=13 first=18:03:04.845 last=18:03:12.906
34.140.123.172 # denied=6 total=434 first=21:34:17.485 last=21:35:45.084
162.243.79.174 # denied=5 total=11 first=12:20:28.790 last=12:20:40.350
51.79.208.246 # denied=5 total=10 first=13:50:27.669 last=13:50:29.418
94.154.43.184 # denied=5 total=10 first=11:23:26.214 last=09:31:40.319
195.178.110.211 # denied=4 total=8 first=19:35:03.504 last=20:22:13.338
45.148.10.119 # denied=3 total=11 first=02:36:55.008 last=07:16:27.585
157.245.63.62 # denied=2 total=4 first=08:13:33.142 last=13:04:56.122
163.7.13.115 # denied=2 total=5 first=14:06:27.842 last=14:06:29.745
45.138.16.114 # denied=2 total=5 first=03:09:59.971 last=03:10:00.217
45.148.10.95 # denied=2 total=4 first=21:05:26.356 last=14:40:26.566
91.92.41.115 # denied=2 total=8 first=14:44:48.975 last=14:44:54.158
94.154.43.179 # denied=2 total=5 first=13:27:23.753 last=04:38:17.921
107.170.9.103 # denied=1 total=2 first=00:19:26.062 last=00:19:26.062
129.212.237.196 # denied=1 total=2 first=09:23:08.470 last=09:23:08.471
134.209.162.128 # denied=1 total=2 first=00:43:12.731 last=00:43:12.731
158.101.144.198 # denied=1 total=2 first=14:30:06.125 last=14:30:06.125
165.245.185.158 # denied=1 total=2 first=09:20:47.477 last=09:20:47.477
176.65.132.38 # denied=1 total=3 first=20:33:22.070 last=05:08:32.533
195.178.110.159 # denied=1 total=2 first=20:41:43.691 last=20:41:43.691
2.57.122.173 # denied=1 total=2 first=12:10:19.177 last=12:10:19.177
23.180.120.147 # denied=1 total=4 first=13:53:30.303 last=13:53:30.473
31.58.51.184 # denied=1 total=4 first=15:07:53.176 last=15:07:58.514
34.125.42.15 # denied=1 total=2 first=21:39:44.709 last=21:39:44.709
34.91.243.226 # denied=1 total=2 first=19:51:57.606 last=19:51:57.606
35.231.100.82 # denied=1 total=2 first=15:36:23.715 last=15:36:23.715
35.233.191.179 # denied=1 total=2 first=00:16:07.188 last=00:16:07.199
35.95.56.230 # denied=1 total=3 first=02:29:40.010 last=02:29:40.562
43.98.201.177 # denied=1 total=2 first=01:01:05.988 last=01:01:05.988
45.139.104.172 # denied=1 total=2 first=03:14:49.950 last=03:14:49.950
64.226.123.37 # denied=1 total=2 first=21:33:32.148 last=21:33:32.148
8.229.130.50 # denied=1 total=2 first=19:23:37.001 last=19:23:37.002
93.123.109.167 # denied=1 total=2 first=04:39:35.474 last=04:39:35.474
94.154.43.183 # denied=1 total=3 first=21:50:39.582 last=00:01:42.127
94.154.43.185 # denied=1 total=3 first=01:40:53.903 last=04:02:34.085
94.154.43.186 # denied=1 total=3 first=21:07:26.439 last=13:43:18.923
94.154.43.188 # denied=1 total=5 first=02:45:01.636 last=11:09:54.264
94.154.43.229 # denied=1 total=4 first=14:35:26.801 last=12:53:30.198
+3 -3
View File
@@ -1,3 +1,3 @@
2a04:4e40:e000:0:d09:97ab:43b1:a59a # denied=2 total=4 first=14:41:30.905 last=14:41:30.922
2600:3c15::2000:53ff:fe31:8c0b # denied=1 total=2 first=12:35:18.643 last=12:35:18.643
2602:fa59:10:a3a::1 # denied=1 total=2 first=02:10:02.531 last=02:10:02.532
2a04:4e40:e000:0:d09:97ab:43b1:a59a # denied=2 total=4 first=14:41:30.905 last=14:41:30.922
2600:3c15::2000:53ff:fe31:8c0b # denied=1 total=2 first=12:35:18.643 last=12:35:18.643
2602:fa59:10:a3a::1 # denied=1 total=2 first=02:10:02.531 last=02:10:02.532
File diff suppressed because it is too large. Load diff
+202 -202
View File
@@ -1,202 +1,202 @@
# copyparty-ids firewall export - generated 2026-08-11T11:44:39
# Openfactory IPv4 ranges (whitelisted)
/ip firewall address-list
add list=Openfactory address=5.226.144.0/21
# Cloudflare IPv4 ranges (whitelisted)
/ip firewall address-list
add list=Cloudflare address=173.245.48.0/20
add list=Cloudflare address=103.21.244.0/22
add list=Cloudflare address=103.22.200.0/22
add list=Cloudflare address=103.31.4.0/22
add list=Cloudflare address=141.101.64.0/18
add list=Cloudflare address=108.162.192.0/18
add list=Cloudflare address=190.93.240.0/20
add list=Cloudflare address=188.114.96.0/20
add list=Cloudflare address=197.234.240.0/22
add list=Cloudflare address=198.41.128.0/17
add list=Cloudflare address=162.158.0.0/15
add list=Cloudflare address=104.16.0.0/13
add list=Cloudflare address=104.24.0.0/14
add list=Cloudflare address=172.64.0.0/13
add list=Cloudflare address=131.0.72.0/22
# Cloudflare IPv6 ranges (whitelisted)
/ipv6 firewall address-list
add list=Cloudflare address=2400:cb00::/32
add list=Cloudflare address=2606:4700::/32
add list=Cloudflare address=2803:f800::/32
add list=Cloudflare address=2405:b500::/32
add list=Cloudflare address=2405:8100::/32
add list=Cloudflare address=2a06:98c0::/29
add list=Cloudflare address=2c0f:f248::/32
# PaloAlto IPv4 ranges (whitelisted)
/ip firewall address-list
add list=PaloAlto address=35.203.210.0/23
add list=PaloAlto address=144.86.173.0/24
add list=PaloAlto address=147.185.132.0/23
add list=PaloAlto address=162.216.149.0/24
add list=PaloAlto address=162.216.150.0/24
add list=PaloAlto address=172.105.147.0/24
add list=PaloAlto address=198.235.24.0/24
add list=PaloAlto address=205.210.31.0/24
add list=PaloAlto address=216.25.88.0/21
# PaloAlto IPv6 ranges (whitelisted)
/ipv6 firewall address-list
add list=PaloAlto address=2604:a940:300:5b6::/64
add list=PaloAlto address=2604:a940:301:225::/64
add list=PaloAlto address=2604:a940:302:118::/64
# Blocked IPv4 (128, non-whitelisted)
/ip firewall address-list
add list=Blocked address=2.57.122.173
add list=Blocked address=3.79.41.12
add list=Blocked address=4.185.41.66
add list=Blocked address=4.223.71.149
add list=Blocked address=4.223.73.90
add list=Blocked address=4.232.185.87
add list=Blocked address=8.229.130.50
add list=Blocked address=16.146.99.254
add list=Blocked address=18.142.90.109
add list=Blocked address=18.227.73.7
add list=Blocked address=20.9.85.55
add list=Blocked address=20.48.236.161
add list=Blocked address=20.52.171.102
add list=Blocked address=20.63.63.128
add list=Blocked address=20.91.203.45
add list=Blocked address=20.91.208.34
add list=Blocked address=20.91.239.158
add list=Blocked address=20.100.172.153
add list=Blocked address=20.113.142.140
add list=Blocked address=20.151.10.161
add list=Blocked address=20.197.178.120
add list=Blocked address=20.197.192.193
add list=Blocked address=20.198.120.225
add list=Blocked address=20.203.179.12
add list=Blocked address=20.203.243.122
add list=Blocked address=20.205.229.184
add list=Blocked address=20.206.67.15
add list=Blocked address=20.206.105.145
add list=Blocked address=20.215.185.25
add list=Blocked address=20.215.216.94
add list=Blocked address=20.215.218.234
add list=Blocked address=20.218.73.95
add list=Blocked address=20.226.26.5
add list=Blocked address=20.251.48.208
add list=Blocked address=20.251.112.224
add list=Blocked address=23.180.120.147
add list=Blocked address=31.58.51.184
add list=Blocked address=34.9.173.20
add list=Blocked address=34.23.104.90
add list=Blocked address=34.39.210.94
add list=Blocked address=34.91.243.226
add list=Blocked address=34.95.239.96
add list=Blocked address=34.105.30.251
add list=Blocked address=34.125.42.15
add list=Blocked address=34.140.123.172
add list=Blocked address=34.242.226.103
add list=Blocked address=35.95.56.230
add list=Blocked address=35.198.180.224
add list=Blocked address=35.231.100.82
add list=Blocked address=35.233.191.179
add list=Blocked address=43.98.201.177
add list=Blocked address=45.67.85.190
add list=Blocked address=45.138.16.114
add list=Blocked address=45.139.104.172
add list=Blocked address=45.148.10.62
add list=Blocked address=45.148.10.67
add list=Blocked address=45.148.10.95
add list=Blocked address=45.148.10.119
add list=Blocked address=45.148.10.120
add list=Blocked address=45.148.10.194
add list=Blocked address=45.148.10.244
add list=Blocked address=45.148.10.247
add list=Blocked address=51.79.208.246
add list=Blocked address=51.107.190.246
add list=Blocked address=51.120.83.160
add list=Blocked address=52.184.96.217
add list=Blocked address=52.238.192.78
add list=Blocked address=54.163.186.39
add list=Blocked address=64.226.123.37
add list=Blocked address=68.221.130.241
add list=Blocked address=72.146.20.230
add list=Blocked address=74.248.24.145
add list=Blocked address=74.248.33.172
add list=Blocked address=74.248.97.169
add list=Blocked address=74.249.245.134
add list=Blocked address=82.102.18.116
add list=Blocked address=85.204.70.100
add list=Blocked address=88.151.32.7
add list=Blocked address=91.92.41.115
add list=Blocked address=91.92.241.196
add list=Blocked address=91.192.10.86
add list=Blocked address=93.123.109.101
add list=Blocked address=93.123.109.167
add list=Blocked address=94.154.43.179
add list=Blocked address=94.154.43.183
add list=Blocked address=94.154.43.184
add list=Blocked address=94.154.43.185
add list=Blocked address=94.154.43.186
add list=Blocked address=94.154.43.188
add list=Blocked address=94.154.43.229
add list=Blocked address=107.170.9.103
add list=Blocked address=107.173.254.55
add list=Blocked address=129.212.237.196
add list=Blocked address=134.209.162.128
add list=Blocked address=135.225.93.215
add list=Blocked address=136.108.11.195
add list=Blocked address=139.59.118.17
add list=Blocked address=146.70.40.68
add list=Blocked address=147.182.149.75
add list=Blocked address=157.245.63.62
add list=Blocked address=158.101.144.198
add list=Blocked address=158.158.32.229
add list=Blocked address=158.158.105.63
add list=Blocked address=162.243.79.174
add list=Blocked address=163.7.11.71
add list=Blocked address=163.7.13.115
add list=Blocked address=165.245.185.158
add list=Blocked address=167.99.181.249
add list=Blocked address=172.213.144.209
add list=Blocked address=172.213.153.79
add list=Blocked address=172.213.208.13
add list=Blocked address=172.213.225.181
add list=Blocked address=172.213.227.73
add list=Blocked address=172.213.244.85
add list=Blocked address=176.65.132.38
add list=Blocked address=185.93.89.147
add list=Blocked address=195.178.110.31
add list=Blocked address=195.178.110.104
add list=Blocked address=195.178.110.135
add list=Blocked address=195.178.110.155
add list=Blocked address=195.178.110.159
add list=Blocked address=195.178.110.199
add list=Blocked address=195.178.110.211
add list=Blocked address=195.178.110.223
add list=Blocked address=207.175.20.232
add list=Blocked address=207.175.159.248
add list=Blocked address=209.99.189.152
add list=Blocked address=209.99.189.190
# Blocked IPv6 (3, non-whitelisted)
/ipv6 firewall address-list
add list=Blocked address=2600:3c15::2000:53ff:fe31:8c0b
add list=Blocked address=2602:fa59:10:a3a::1
add list=Blocked address=2a04:4e40:e000:0:d09:97ab:43b1:a59a
/ip firewall filter
add chain=input action=accept src-address-list=Openfactory comment="copyparty-ids openfactory whitelist (v4)"
add chain=input action=accept src-address-list=Cloudflare comment="copyparty-ids cloudflare whitelist (v4)"
add chain=input action=accept src-address-list=PaloAlto comment="copyparty-ids paloalto whitelist (v4)"
add chain=input action=drop src-address-list=Blocked comment="copyparty-ids blocked (v4)"
add chain=forward action=drop src-address-list=Blocked comment="copyparty-ids blocked (v4)"
/ipv6 firewall filter
add chain=input action=accept src-address-list=Openfactory comment="copyparty-ids openfactory whitelist (v6)"
add chain=input action=accept src-address-list=Cloudflare comment="copyparty-ids cloudflare whitelist (v6)"
add chain=input action=accept src-address-list=PaloAlto comment="copyparty-ids paloalto whitelist (v6)"
add chain=input action=drop src-address-list=Blocked comment="copyparty-ids blocked (v6)"
add chain=forward action=drop src-address-list=Blocked comment="copyparty-ids blocked (v6)"
# copyparty-ids firewall export - generated 2026-08-11T11:44:39
# Openfactory IPv4 ranges (whitelisted)
/ip firewall address-list
add list=Openfactory address=5.226.144.0/21
# Cloudflare IPv4 ranges (whitelisted)
/ip firewall address-list
add list=Cloudflare address=173.245.48.0/20
add list=Cloudflare address=103.21.244.0/22
add list=Cloudflare address=103.22.200.0/22
add list=Cloudflare address=103.31.4.0/22
add list=Cloudflare address=141.101.64.0/18
add list=Cloudflare address=108.162.192.0/18
add list=Cloudflare address=190.93.240.0/20
add list=Cloudflare address=188.114.96.0/20
add list=Cloudflare address=197.234.240.0/22
add list=Cloudflare address=198.41.128.0/17
add list=Cloudflare address=162.158.0.0/15
add list=Cloudflare address=104.16.0.0/13
add list=Cloudflare address=104.24.0.0/14
add list=Cloudflare address=172.64.0.0/13
add list=Cloudflare address=131.0.72.0/22
# Cloudflare IPv6 ranges (whitelisted)
/ipv6 firewall address-list
add list=Cloudflare address=2400:cb00::/32
add list=Cloudflare address=2606:4700::/32
add list=Cloudflare address=2803:f800::/32
add list=Cloudflare address=2405:b500::/32
add list=Cloudflare address=2405:8100::/32
add list=Cloudflare address=2a06:98c0::/29
add list=Cloudflare address=2c0f:f248::/32
# PaloAlto IPv4 ranges (whitelisted)
/ip firewall address-list
add list=PaloAlto address=35.203.210.0/23
add list=PaloAlto address=144.86.173.0/24
add list=PaloAlto address=147.185.132.0/23
add list=PaloAlto address=162.216.149.0/24
add list=PaloAlto address=162.216.150.0/24
add list=PaloAlto address=172.105.147.0/24
add list=PaloAlto address=198.235.24.0/24
add list=PaloAlto address=205.210.31.0/24
add list=PaloAlto address=216.25.88.0/21
# PaloAlto IPv6 ranges (whitelisted)
/ipv6 firewall address-list
add list=PaloAlto address=2604:a940:300:5b6::/64
add list=PaloAlto address=2604:a940:301:225::/64
add list=PaloAlto address=2604:a940:302:118::/64
# Blocked IPv4 (128, non-whitelisted)
/ip firewall address-list
add list=Blocked address=2.57.122.173
add list=Blocked address=3.79.41.12
add list=Blocked address=4.185.41.66
add list=Blocked address=4.223.71.149
add list=Blocked address=4.223.73.90
add list=Blocked address=4.232.185.87
add list=Blocked address=8.229.130.50
add list=Blocked address=16.146.99.254
add list=Blocked address=18.142.90.109
add list=Blocked address=18.227.73.7
add list=Blocked address=20.9.85.55
add list=Blocked address=20.48.236.161
add list=Blocked address=20.52.171.102
add list=Blocked address=20.63.63.128
add list=Blocked address=20.91.203.45
add list=Blocked address=20.91.208.34
add list=Blocked address=20.91.239.158
add list=Blocked address=20.100.172.153
add list=Blocked address=20.113.142.140
add list=Blocked address=20.151.10.161
add list=Blocked address=20.197.178.120
add list=Blocked address=20.197.192.193
add list=Blocked address=20.198.120.225
add list=Blocked address=20.203.179.12
add list=Blocked address=20.203.243.122
add list=Blocked address=20.205.229.184
add list=Blocked address=20.206.67.15
add list=Blocked address=20.206.105.145
add list=Blocked address=20.215.185.25
add list=Blocked address=20.215.216.94
add list=Blocked address=20.215.218.234
add list=Blocked address=20.218.73.95
add list=Blocked address=20.226.26.5
add list=Blocked address=20.251.48.208
add list=Blocked address=20.251.112.224
add list=Blocked address=23.180.120.147
add list=Blocked address=31.58.51.184
add list=Blocked address=34.9.173.20
add list=Blocked address=34.23.104.90
add list=Blocked address=34.39.210.94
add list=Blocked address=34.91.243.226
add list=Blocked address=34.95.239.96
add list=Blocked address=34.105.30.251
add list=Blocked address=34.125.42.15
add list=Blocked address=34.140.123.172
add list=Blocked address=34.242.226.103
add list=Blocked address=35.95.56.230
add list=Blocked address=35.198.180.224
add list=Blocked address=35.231.100.82
add list=Blocked address=35.233.191.179
add list=Blocked address=43.98.201.177
add list=Blocked address=45.67.85.190
add list=Blocked address=45.138.16.114
add list=Blocked address=45.139.104.172
add list=Blocked address=45.148.10.62
add list=Blocked address=45.148.10.67
add list=Blocked address=45.148.10.95
add list=Blocked address=45.148.10.119
add list=Blocked address=45.148.10.120
add list=Blocked address=45.148.10.194
add list=Blocked address=45.148.10.244
add list=Blocked address=45.148.10.247
add list=Blocked address=51.79.208.246
add list=Blocked address=51.107.190.246
add list=Blocked address=51.120.83.160
add list=Blocked address=52.184.96.217
add list=Blocked address=52.238.192.78
add list=Blocked address=54.163.186.39
add list=Blocked address=64.226.123.37
add list=Blocked address=68.221.130.241
add list=Blocked address=72.146.20.230
add list=Blocked address=74.248.24.145
add list=Blocked address=74.248.33.172
add list=Blocked address=74.248.97.169
add list=Blocked address=74.249.245.134
add list=Blocked address=82.102.18.116
add list=Blocked address=85.204.70.100
add list=Blocked address=88.151.32.7
add list=Blocked address=91.92.41.115
add list=Blocked address=91.92.241.196
add list=Blocked address=91.192.10.86
add list=Blocked address=93.123.109.101
add list=Blocked address=93.123.109.167
add list=Blocked address=94.154.43.179
add list=Blocked address=94.154.43.183
add list=Blocked address=94.154.43.184
add list=Blocked address=94.154.43.185
add list=Blocked address=94.154.43.186
add list=Blocked address=94.154.43.188
add list=Blocked address=94.154.43.229
add list=Blocked address=107.170.9.103
add list=Blocked address=107.173.254.55
add list=Blocked address=129.212.237.196
add list=Blocked address=134.209.162.128
add list=Blocked address=135.225.93.215
add list=Blocked address=136.108.11.195
add list=Blocked address=139.59.118.17
add list=Blocked address=146.70.40.68
add list=Blocked address=147.182.149.75
add list=Blocked address=157.245.63.62
add list=Blocked address=158.101.144.198
add list=Blocked address=158.158.32.229
add list=Blocked address=158.158.105.63
add list=Blocked address=162.243.79.174
add list=Blocked address=163.7.11.71
add list=Blocked address=163.7.13.115
add list=Blocked address=165.245.185.158
add list=Blocked address=167.99.181.249
add list=Blocked address=172.213.144.209
add list=Blocked address=172.213.153.79
add list=Blocked address=172.213.208.13
add list=Blocked address=172.213.225.181
add list=Blocked address=172.213.227.73
add list=Blocked address=172.213.244.85
add list=Blocked address=176.65.132.38
add list=Blocked address=185.93.89.147
add list=Blocked address=195.178.110.31
add list=Blocked address=195.178.110.104
add list=Blocked address=195.178.110.135
add list=Blocked address=195.178.110.155
add list=Blocked address=195.178.110.159
add list=Blocked address=195.178.110.199
add list=Blocked address=195.178.110.211
add list=Blocked address=195.178.110.223
add list=Blocked address=207.175.20.232
add list=Blocked address=207.175.159.248
add list=Blocked address=209.99.189.152
add list=Blocked address=209.99.189.190
# Blocked IPv6 (3, non-whitelisted)
/ipv6 firewall address-list
add list=Blocked address=2600:3c15::2000:53ff:fe31:8c0b
add list=Blocked address=2602:fa59:10:a3a::1
add list=Blocked address=2a04:4e40:e000:0:d09:97ab:43b1:a59a
/ip firewall filter
add chain=input action=accept src-address-list=Openfactory comment="copyparty-ids openfactory whitelist (v4)"
add chain=input action=accept src-address-list=Cloudflare comment="copyparty-ids cloudflare whitelist (v4)"
add chain=input action=accept src-address-list=PaloAlto comment="copyparty-ids paloalto whitelist (v4)"
add chain=input action=drop src-address-list=Blocked comment="copyparty-ids blocked (v4)"
add chain=forward action=drop src-address-list=Blocked comment="copyparty-ids blocked (v4)"
/ipv6 firewall filter
add chain=input action=accept src-address-list=Openfactory comment="copyparty-ids openfactory whitelist (v6)"
add chain=input action=accept src-address-list=Cloudflare comment="copyparty-ids cloudflare whitelist (v6)"
add chain=input action=accept src-address-list=PaloAlto comment="copyparty-ids paloalto whitelist (v6)"
add chain=input action=drop src-address-list=Blocked comment="copyparty-ids blocked (v6)"
add chain=forward action=drop src-address-list=Blocked comment="copyparty-ids blocked (v6)"
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+383 -383
View File
@@ -1,384 +1,384 @@
[
{
"address": "::/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::1/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "fec0::/10",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::ffff:0.0.0.0/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "100::/64",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:db8::/32",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:10::/28",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "3ffe::/16",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2a0e:8f04::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f05::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f06::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f07::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2080::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:67c:2648::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:200::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:600::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:800::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2400:cb00::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2606:4700::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2803:f800::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:b500::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:8100::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2a06:98c0::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2c0f:f248::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2604:a940:300:5b6::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:301:225::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:302:118::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2001:4ca0:108:42::24/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:62ff:fe9a:e1c2/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3000::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c09::2000:5cff:fe99:c802/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:53ff:fe31:8c0b/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59:10:a3a::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:2a8:a0dd:1::1012/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000:0:d09:97ab:43b1:a59a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:c300::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:4d/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:88/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:ba0:24c:a500::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:9cff:fef0:8ad6/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59::/40",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:64cc:9116:beb2:1931/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe82:2775/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:4f8:c014:7f9e::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:4400:0:537:cdd2:7250:95db/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a05:4140:3::37cd/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a06:a880:5:7fb3::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac1:76c0:460::5e:6a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a13:adc0::2ed:89ff:fe58:19c5/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:beff:fea3:5a44/128",
"creation-time": "2026-08-05",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-06",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2017:3810::/64",
"comment": "hosting",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:8d8:5ff:5f:82:165:82:154/128",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::/32",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:448a:a071:520:e18f:3d1f:944e:174d/128",
"creation-time": "2026-08-08",
"dynamic": "no",
"list": "Blocked"
}
[
{
"address": "::/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::1/128",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "fec0::/10",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::ffff:0.0.0.0/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "::/96",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "100::/64",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:db8::/32",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2001:10::/28",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "3ffe::/16",
"comment": "defconf:",
"creation-time": "2025-11-21",
"dynamic": "no",
"list": "bad_ipv6"
},
{
"address": "2a0e:8f04::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f05::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f06::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a0e:8f07::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2080::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:67c:2648::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:200::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:600::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2a00:6340:2044:800::/56",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2400:cb00::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2606:4700::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2803:f800::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:b500::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2405:8100::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2a06:98c0::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2c0f:f248::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Cloudflare"
},
{
"address": "2604:a940:300:5b6::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:301:225::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2604:a940:302:118::/64",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "PaloAlto"
},
{
"address": "2001:4ca0:108:42::24/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:62ff:fe9a:e1c2/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3000::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c09::2000:5cff:fe99:c802/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:53ff:fe31:8c0b/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59:10:a3a::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:2a8:a0dd:1::1012/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000:0:d09:97ab:43b1:a59a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:c300::/29",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:4d/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5:9443:3af::5e:88/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:ba0:24c:a500::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2406:da18:525:0:a23e:e8f6:3ea1:4c2c/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::2000:9cff:fef0:8ad6/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2602:fa59::/40",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:64cc:9116:beb2:1931/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe3b:4058/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2008:ec80:be24:11ff:fe82:2775/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a01:4f8:c014:7f9e::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:4400:0:537:cdd2:7250:95db/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a04:4e40:e000::/48",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a05:4140:3::37cd/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a06:a880:5:7fb3::1/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac1:76c0:460::5e:6a/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a09:bac5::/32",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a13:adc0::2ed:89ff:fe58:19c5/128",
"creation-time": "2026-08-03",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2400:8901::2000:beff:fea3:5a44/128",
"creation-time": "2026-08-05",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340::/32",
"creation-time": "2026-08-06",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2a00:6340:2017:3810::/64",
"comment": "hosting",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Openfactory"
},
{
"address": "2001:8d8:5ff:5f:82:165:82:154/128",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2600:3c15::/32",
"creation-time": "2026-08-07",
"dynamic": "no",
"list": "Blocked"
},
{
"address": "2001:448a:a071:520:e18f:3d1f:944e:174d/128",
"creation-time": "2026-08-08",
"dynamic": "no",
"list": "Blocked"
}
]
+136 -136
View File
@@ -1,137 +1,137 @@
[
{
"action": "passthrough",
"chain": "forward",
"comment": "special"
},
{
"action": "fasttrack-connection",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"hw-offload": "yes",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"log": "no",
"log-prefix": ""
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "Allow",
"connection-nat-state": "dstnat"
},
{
"action": "accept",
"chain": "forward",
"comment": "allow",
"connection-state": "new",
"dst-address": "192.168.88.25",
"dst-port": "6667",
"log": "no",
"log-prefix": "",
"protocol": "tcp"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-nat-state": "!dstnat",
"connection-state": "new",
"in-interface-list": "WAN",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"log": "no",
"log-prefix": "",
"protocol": "icmp"
},
{
"action": "accept",
"chain": "input",
"comment": "accept",
"connection-state": "established",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"dst-port": "500",
"protocol": "udp"
},
{
"action": "drop",
"chain": "input",
"comment": "Block",
"dst-port": "80,443",
"in-interface-list": "WAN",
"protocol": "tcp"
},
{
"action": "accept",
"chain": "input",
"comment": "Allow",
"dst-port": "80,443",
"in-interface-list": "LAN",
"protocol": "tcp",
"src-address": "192.168.88.0/24"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "input",
"comment": "drop",
"in-interface": "pppoe-out1",
"log": "no",
"log-prefix": ""
}
[
{
"action": "passthrough",
"chain": "forward",
"comment": "special"
},
{
"action": "fasttrack-connection",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"hw-offload": "yes",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related",
"log": "no",
"log-prefix": ""
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "forward",
"comment": "Allow",
"connection-nat-state": "dstnat"
},
{
"action": "accept",
"chain": "forward",
"comment": "allow",
"connection-state": "new",
"dst-address": "192.168.88.25",
"dst-port": "6667",
"log": "no",
"log-prefix": "",
"protocol": "tcp"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-nat-state": "!dstnat",
"connection-state": "new",
"in-interface-list": "WAN",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"log": "no",
"log-prefix": "",
"protocol": "icmp"
},
{
"action": "accept",
"chain": "input",
"comment": "accept",
"connection-state": "established",
"log": "no",
"log-prefix": ""
},
{
"action": "accept",
"chain": "input",
"comment": "allow",
"dst-port": "500",
"protocol": "udp"
},
{
"action": "drop",
"chain": "input",
"comment": "Block",
"dst-port": "80,443",
"in-interface-list": "WAN",
"protocol": "tcp"
},
{
"action": "accept",
"chain": "input",
"comment": "Allow",
"dst-port": "80,443",
"in-interface-list": "LAN",
"protocol": "tcp",
"src-address": "192.168.88.0/24"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "drop",
"chain": "input",
"comment": "drop",
"in-interface": "pppoe-out1",
"log": "no",
"log-prefix": ""
}
]
+185 -185
View File
@@ -1,186 +1,186 @@
[
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"port": "33434-33534",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "546",
"protocol": "udp",
"src-address": "fe80::/10"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"src-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"dst-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"hop-limit": "equal:1",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "ids",
"log": "no",
"log-prefix": "",
"src-address-list": "Openfactory"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"log": "no",
"log-prefix": "",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "139"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
}
[
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"port": "33434-33534",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "546",
"protocol": "udp",
"src-address": "fe80::/10"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "input",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"connection-state": "established,related,untracked"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"connection-state": "invalid"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"src-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"dst-address-list": "bad_ipv6"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"hop-limit": "equal:1",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "ids",
"log": "no",
"log-prefix": "",
"src-address-list": "Openfactory"
},
{
"action": "drop",
"chain": "forward",
"comment": "ids",
"src-address-list": "Blocked"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "input",
"comment": "defconf:",
"log": "no",
"log-prefix": "",
"protocol": "icmpv6"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "139"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"dst-port": "500,4500",
"protocol": "udp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-ah"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"protocol": "ipsec-esp"
},
{
"action": "accept",
"chain": "forward",
"comment": "defconf:",
"ipsec-policy": "in,ipsec"
},
{
"action": "drop",
"chain": "forward",
"comment": "defconf:",
"in-interface-list": "!LAN"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Openfactory"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "Cloudflare"
},
{
"action": "accept",
"chain": "input",
"comment": "ids",
"src-address-list": "PaloAlto"
},
{
"action": "drop",
"chain": "input",
"comment": "ids",
"src-address-list": "Blocked"
}
]
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+41 -41
View File
@@ -1,41 +1,41 @@
2001:ba0:24c:a500::1
2001:4ca0:108:42::24
2400:8901::2000:62ff:fe9a:e1c2
2406:da18:525:0:a23e:e8f6:3ea1:4c2c
2600:3000:1305:4212::81
2600:3000:1305:4212::82
2600:3000:1305:4212::83
2600:3000:1305:4212::84
2600:3000:1305:4212::85
2600:3000:2710:200::81
2600:3000:2710:200::82
2600:3000:2710:200::83
2600:3000:2710:200::84
2600:3000:2710:200::85
2600:3000:2710:200::86
2600:3c09::2000:5cff:fe99:c802
2600:3c15::2000:53ff:fe31:8c0b
2600:3c15::2000:9cff:fef0:8ad6
2602:fa59:10:4c9::1
2602:fa59:10:a3a::1
2602:fa59:10:e70::1
2a00:6340:2008:ec80:64cc:9116:beb2:1931
2a00:6340:2008:ec80:be24:11ff:fe3b:4058
2a00:6340:2008:ec80:be24:11ff:fe82:2775
2a01:2a8:a0dd:1::1012
2a01:4f8:c014:7f9e::1
2a04:4e40:e000:0:33c:a689:be95:5a4
2a04:4e40:e000:0:566:f8d7:adbe:f536
2a04:4e40:e000:0:954:9789:20b1:d5fc
2a04:4e40:e000:0:bfc:4b0:174b:d52d
2a04:c300::3ce
2a04:c300:400::58
2a04:c300:400::5d
2a04:c300:400::99
2a05:4140:3::37cd
2a09:bac1:76c0:460::5e:6a
2a09:bac5:55fb:18c8::278:a7
2a09:bac5:9443:3af::5e:4d
2a09:bac5:9443:3af::5e:88
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9
2a13:adc0::2ed:89ff:fe58:19c5
2001:ba0:24c:a500::1
2001:4ca0:108:42::24
2400:8901::2000:62ff:fe9a:e1c2
2406:da18:525:0:a23e:e8f6:3ea1:4c2c
2600:3000:1305:4212::81
2600:3000:1305:4212::82
2600:3000:1305:4212::83
2600:3000:1305:4212::84
2600:3000:1305:4212::85
2600:3000:2710:200::81
2600:3000:2710:200::82
2600:3000:2710:200::83
2600:3000:2710:200::84
2600:3000:2710:200::85
2600:3000:2710:200::86
2600:3c09::2000:5cff:fe99:c802
2600:3c15::2000:53ff:fe31:8c0b
2600:3c15::2000:9cff:fef0:8ad6
2602:fa59:10:4c9::1
2602:fa59:10:a3a::1
2602:fa59:10:e70::1
2a00:6340:2008:ec80:64cc:9116:beb2:1931
2a00:6340:2008:ec80:be24:11ff:fe3b:4058
2a00:6340:2008:ec80:be24:11ff:fe82:2775
2a01:2a8:a0dd:1::1012
2a01:4f8:c014:7f9e::1
2a04:4e40:e000:0:33c:a689:be95:5a4
2a04:4e40:e000:0:566:f8d7:adbe:f536
2a04:4e40:e000:0:954:9789:20b1:d5fc
2a04:4e40:e000:0:bfc:4b0:174b:d52d
2a04:c300::3ce
2a04:c300:400::58
2a04:c300:400::5d
2a04:c300:400::99
2a05:4140:3::37cd
2a09:bac1:76c0:460::5e:6a
2a09:bac5:55fb:18c8::278:a7
2a09:bac5:9443:3af::5e:4d
2a09:bac5:9443:3af::5e:88
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9
2a13:adc0::2ed:89ff:fe58:19c5
File diff suppressed because it is too large. Load diff
+23 -23
View File
@@ -1,23 +1,23 @@
host,count
pbs.allucanget.biz,43743
s.allucanget.biz,42014
coolify.allucanget.biz,41829
wagnerloibner.com,37046
git.allucanget.biz,25376
openmicodyssey.com,25325
copyparty.allucanget.biz,18117
openwebui.allucanget.biz,14539
contact.allucanget.biz,10770
ai.allucanget.biz,9799
contact.wagnerloibner.com,9592
admin.openmicodyssey.com,8974
www.openmicodyssey.com,8386
api.openmicodyssey.com,4598
tcv.allucanget.biz,2557
cam.openmicodyssey.com,2468
linearvoid.tv,1951
lounge.allucanget.biz,1745
code.allucanget.biz,788
www.wagnerloibner.com,326
m.allucanget.biz,242
postiz.allucanget.biz,78
host,count
pbs.allucanget.biz,43743
s.allucanget.biz,42014
coolify.allucanget.biz,41829
wagnerloibner.com,37046
git.allucanget.biz,25376
openmicodyssey.com,25325
copyparty.allucanget.biz,18117
openwebui.allucanget.biz,14539
contact.allucanget.biz,10770
ai.allucanget.biz,9799
contact.wagnerloibner.com,9592
admin.openmicodyssey.com,8974
www.openmicodyssey.com,8386
api.openmicodyssey.com,4598
tcv.allucanget.biz,2557
cam.openmicodyssey.com,2468
linearvoid.tv,1951
lounge.allucanget.biz,1745
code.allucanget.biz,788
www.wagnerloibner.com,326
m.allucanget.biz,242
postiz.allucanget.biz,78
1 host count
2 pbs.allucanget.biz 43743
3 s.allucanget.biz 42014
4 coolify.allucanget.biz 41829
5 wagnerloibner.com 37046
6 git.allucanget.biz 25376
7 openmicodyssey.com 25325
8 copyparty.allucanget.biz 18117
9 openwebui.allucanget.biz 14539
10 contact.allucanget.biz 10770
11 ai.allucanget.biz 9799
12 contact.wagnerloibner.com 9592
13 admin.openmicodyssey.com 8974
14 www.openmicodyssey.com 8386
15 api.openmicodyssey.com 4598
16 tcv.allucanget.biz 2557
17 cam.openmicodyssey.com 2468
18 linearvoid.tv 1951
19 lounge.allucanget.biz 1745
20 code.allucanget.biz 788
21 www.wagnerloibner.com 326
22 m.allucanget.biz 242
23 postiz.allucanget.biz 78
+311264 -311264
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+310264 -310264
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+26 -26
View File
@@ -1,26 +1,26 @@
2a01:2a8:a0dd:1::1012 # errors=9517 total=9517 ratio=1.0 first=09/Aug/2026:19:01:21 +0200 last=18/Jul/2026:23:59:49 +0200
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9 # errors=150 total=150 ratio=1.0 first=27/Jul/2026:14:49:23 +0200 last=27/Jul/2026:14:49:53 +0200
2a00:6340:2008:ec80:be24:11ff:fe3b:4058 # errors=105 total=120 ratio=0.875 first=31/Jul/2026:18:53:29 +0200 last=17/Jul/2026:17:28:19 +0200
2a06:98c0:3600::103 # errors=63 total=74 ratio=0.851 first=29/Jul/2026:05:34:01 +0200 last=27/Jul/2026:18:39:05 +0200
2600:3000:1305:4212::83 # errors=44 total=78 ratio=0.564 first=10/Aug/2026:04:04:22 +0200 last=02/Aug/2026:08:41:15 +0200
2a09:bac5:9443:3af::5e:4d # errors=40 total=40 ratio=1.0 first=25/Jul/2026:05:55:27 +0200 last=25/Jul/2026:05:55:39 +0200
2600:3000:2710:200::85 # errors=37 total=68 ratio=0.544 first=10/Aug/2026:17:56:13 +0200 last=29/Jul/2026:02:00:14 +0200
2600:3000:2710:200::86 # errors=29 total=49 ratio=0.592 first=10/Aug/2026:17:56:04 +0200 last=17/Jul/2026:17:26:06 +0200
2600:3000:1305:4212::85 # errors=28 total=48 ratio=0.583 first=10/Aug/2026:02:00:13 +0200 last=10/Aug/2026:21:57:52 +0200
2600:3000:2710:200::82 # errors=28 total=51 ratio=0.549 first=10/Aug/2026:04:01:19 +0200 last=17/Jul/2026:17:14:39 +0200
2600:3000:2710:200::83 # errors=28 total=48 ratio=0.583 first=02/Aug/2026:08:43:47 +0200 last=17/Jul/2026:17:27:06 +0200
2600:3000:1305:4212::81 # errors=24 total=46 ratio=0.522 first=02/Aug/2026:08:41:14 +0200 last=30/Jul/2026:02:00:11 +0200
2600:3000:2710:200::81 # errors=23 total=38 ratio=0.605 first=25/Jul/2026:02:00:09 +0200 last=15/Jul/2026:18:29:14 +0200
2600:3000:2710:200::84 # errors=23 total=44 ratio=0.523 first=10/Aug/2026:10:30:53 +0200 last=17/Jul/2026:17:22:50 +0200
2600:3000:1305:4212::82 # errors=19 total=31 ratio=0.613 first=10/Aug/2026:10:30:34 +0200 last=02/Aug/2026:08:43:51 +0200
2600:3000:1305:4212::84 # errors=19 total=35 ratio=0.543 first=29/Jul/2026:16:26:16 +0200 last=10/Aug/2026:19:53:10 +0200
2a04:c300:400::99 # errors=15 total=15 ratio=1.0 first=25/Jul/2026:16:45:35 +0200 last=25/Jul/2026:16:45:40 +0200
2a00:6340:2008:ec80:be24:11ff:fe82:2775 # errors=14 total=16 ratio=0.875 first=31/Jul/2026:19:10:46 +0200 last=31/Jul/2026:19:11:42 +0200
2400:8901::2000:62ff:fe9a:e1c2 # errors=9 total=9 ratio=1.0 first=18/Jul/2026:21:57:41 +0200 last=18/Jul/2026:21:57:44 +0200
2a09:bac5:9443:3af::5e:88 # errors=8 total=8 ratio=1.0 first=16/Jul/2026:10:53:36 +0200 last=16/Jul/2026:10:53:36 +0200
2001:4ca0:108:42::24 # errors=7 total=8 ratio=0.875 first=09/Aug/2026:19:50:32 +0200 last=19/Jul/2026:09:41:27 +0200
2a04:c300:400::58 # errors=7 total=8 ratio=0.875 first=20/Jul/2026:23:55:45 +0200 last=29/Jul/2026:17:55:40 +0200
2a04:c300:400::5d # errors=7 total=13 ratio=0.538 first=23/Jul/2026:15:28:34 +0200 last=23/Jul/2026:15:28:38 +0200
2600:3c09::2000:5cff:fe99:c802 # errors=5 total=5 ratio=1.0 first=28/Jul/2026:22:51:11 +0200 last=28/Jul/2026:22:51:14 +0200
2600:3c15::2000:53ff:fe31:8c0b # errors=5 total=8 ratio=0.625 first=23/Jul/2026:14:35:18 +0200 last=23/Jul/2026:14:34:55 +0200
2602:fa59:10:a3a::1 # errors=5 total=7 ratio=0.714 first=28/Jul/2026:04:10:02 +0200 last=28/Jul/2026:05:36:59 +0200
2a01:2a8:a0dd:1::1012 # errors=9517 total=9517 ratio=1.0 first=09/Aug/2026:19:01:21 +0200 last=18/Jul/2026:23:59:49 +0200
2a0a:4cc0:2000:8528:c4e8:3ff:febb:3ee9 # errors=150 total=150 ratio=1.0 first=27/Jul/2026:14:49:23 +0200 last=27/Jul/2026:14:49:53 +0200
2a00:6340:2008:ec80:be24:11ff:fe3b:4058 # errors=105 total=120 ratio=0.875 first=31/Jul/2026:18:53:29 +0200 last=17/Jul/2026:17:28:19 +0200
2a06:98c0:3600::103 # errors=63 total=74 ratio=0.851 first=29/Jul/2026:05:34:01 +0200 last=27/Jul/2026:18:39:05 +0200
2600:3000:1305:4212::83 # errors=44 total=78 ratio=0.564 first=10/Aug/2026:04:04:22 +0200 last=02/Aug/2026:08:41:15 +0200
2a09:bac5:9443:3af::5e:4d # errors=40 total=40 ratio=1.0 first=25/Jul/2026:05:55:27 +0200 last=25/Jul/2026:05:55:39 +0200
2600:3000:2710:200::85 # errors=37 total=68 ratio=0.544 first=10/Aug/2026:17:56:13 +0200 last=29/Jul/2026:02:00:14 +0200
2600:3000:2710:200::86 # errors=29 total=49 ratio=0.592 first=10/Aug/2026:17:56:04 +0200 last=17/Jul/2026:17:26:06 +0200
2600:3000:1305:4212::85 # errors=28 total=48 ratio=0.583 first=10/Aug/2026:02:00:13 +0200 last=10/Aug/2026:21:57:52 +0200
2600:3000:2710:200::82 # errors=28 total=51 ratio=0.549 first=10/Aug/2026:04:01:19 +0200 last=17/Jul/2026:17:14:39 +0200
2600:3000:2710:200::83 # errors=28 total=48 ratio=0.583 first=02/Aug/2026:08:43:47 +0200 last=17/Jul/2026:17:27:06 +0200
2600:3000:1305:4212::81 # errors=24 total=46 ratio=0.522 first=02/Aug/2026:08:41:14 +0200 last=30/Jul/2026:02:00:11 +0200
2600:3000:2710:200::81 # errors=23 total=38 ratio=0.605 first=25/Jul/2026:02:00:09 +0200 last=15/Jul/2026:18:29:14 +0200
2600:3000:2710:200::84 # errors=23 total=44 ratio=0.523 first=10/Aug/2026:10:30:53 +0200 last=17/Jul/2026:17:22:50 +0200
2600:3000:1305:4212::82 # errors=19 total=31 ratio=0.613 first=10/Aug/2026:10:30:34 +0200 last=02/Aug/2026:08:43:51 +0200
2600:3000:1305:4212::84 # errors=19 total=35 ratio=0.543 first=29/Jul/2026:16:26:16 +0200 last=10/Aug/2026:19:53:10 +0200
2a04:c300:400::99 # errors=15 total=15 ratio=1.0 first=25/Jul/2026:16:45:35 +0200 last=25/Jul/2026:16:45:40 +0200
2a00:6340:2008:ec80:be24:11ff:fe82:2775 # errors=14 total=16 ratio=0.875 first=31/Jul/2026:19:10:46 +0200 last=31/Jul/2026:19:11:42 +0200
2400:8901::2000:62ff:fe9a:e1c2 # errors=9 total=9 ratio=1.0 first=18/Jul/2026:21:57:41 +0200 last=18/Jul/2026:21:57:44 +0200
2a09:bac5:9443:3af::5e:88 # errors=8 total=8 ratio=1.0 first=16/Jul/2026:10:53:36 +0200 last=16/Jul/2026:10:53:36 +0200
2001:4ca0:108:42::24 # errors=7 total=8 ratio=0.875 first=09/Aug/2026:19:50:32 +0200 last=19/Jul/2026:09:41:27 +0200
2a04:c300:400::58 # errors=7 total=8 ratio=0.875 first=20/Jul/2026:23:55:45 +0200 last=29/Jul/2026:17:55:40 +0200
2a04:c300:400::5d # errors=7 total=13 ratio=0.538 first=23/Jul/2026:15:28:34 +0200 last=23/Jul/2026:15:28:38 +0200
2600:3c09::2000:5cff:fe99:c802 # errors=5 total=5 ratio=1.0 first=28/Jul/2026:22:51:11 +0200 last=28/Jul/2026:22:51:14 +0200
2600:3c15::2000:53ff:fe31:8c0b # errors=5 total=8 ratio=0.625 first=23/Jul/2026:14:35:18 +0200 last=23/Jul/2026:14:34:55 +0200
2602:fa59:10:a3a::1 # errors=5 total=7 ratio=0.714 first=28/Jul/2026:04:10:02 +0200 last=28/Jul/2026:05:36:59 +0200
File diff suppressed because it is too large. Load diff
+322 -322
View File
@@ -1,322 +1,322 @@
#!/usr/bin/env python3
"""Consolidated intrusion detection log scanner.
Runs both copyparty and Nginx Proxy Manager (NPM) log analyzers,
and outputs a single consolidated MikroTik RouterOS blocklist.
"""
from __future__ import annotations
import argparse
import os
from dataclasses import dataclass, field
from ..utils.blocklist_history import (
committed_lines,
cumulative_blocklist,
current_file_lines,
write_blocklist_report,
)
from ..utils.constants import (
COPYPARTY_LOG_PATH,
COPYPARTY_REPORT_DIR,
DEFAULT_ERROR_RATIO,
DEFAULT_MIN_DENIED,
DEFAULT_MIN_ERRORS,
DEFAULT_TOP,
NPM_LOG_PATH,
NPM_REPORT_DIR,
REPORT_DIR,
REPORT_RETENTION_DAYS,
REPORT_RETENTION_MAX_FILES,
SUBNET_THRESHOLD,
)
from ..firewall import MikrotikFirewall, write_blocklist_files
from ..utils.retention import prune_report_dirs
from ..copyparty import CopypartyAnalyzer
from ..npm import NpmAnalyzer
from ..utils.ip_utils import is_whitelisted
from ..mikrotik import split_cidr_versions
from ..utils.whois import consolidate_by_subnet
@dataclass
class ScanParams:
"""Configuration for a consolidated scan.
Shared by the CLI entry point and the web interface so both run the
exact same pipeline.
"""
copyparty_log_path: str = COPYPARTY_LOG_PATH
copyparty_report_dir: str = COPYPARTY_REPORT_DIR
min_denied: int = DEFAULT_MIN_DENIED
npm_log_path: str = NPM_LOG_PATH
npm_report_dir: str = NPM_REPORT_DIR
min_errors: int = DEFAULT_MIN_ERRORS
error_ratio: float = DEFAULT_ERROR_RATIO
report_dir: str = REPORT_DIR
top: int = DEFAULT_TOP
quiet: bool = False
full: bool = False
update_firewall: bool = False
dry_run: bool = False
@dataclass
class ScanResult:
"""Structured outcome of a consolidated scan."""
ok: bool
cp_exists: bool = False
npm_exists: bool = False
cp_candidates: int = 0
npm_candidates: int = 0
blocked_ips: int = 0
blocked_targets: int = 0
blocked_ipv4: list[str] = field(default_factory=list)
blocked_ipv6: list[str] = field(default_factory=list)
blocklist_v4_path: str | None = None
blocklist_v6_path: str | None = None
firewall_connected: bool = False
firewall_changes: dict | None = None
blocklist_report_path: str | None = None
errors: list[str] = field(default_factory=list)
def run_scan(params: ScanParams) -> ScanResult:
"""Run the full consolidated scan pipeline and return structured results.
Steps: connect to MikroTik (optional) -> snapshot state -> run copyparty
+ NPM analyzers -> consolidate candidates -> write blocklists -> compare
and apply firewall changes (optional).
"""
errors: list[str] = []
# --- Step 1-3: connect to MikroTik RouterOS and capture current state ---
# If the router is unreachable we fall back to scan-only mode: still
# generate reports and blocklists, but skip the firewall sync.
firewall: MikrotikFirewall | None = None
if params.update_firewall:
firewall = MikrotikFirewall()
try:
firewall.connect()
# Read current firewall rules + address lists and snapshot them to
# reports/mikrotik/data/ and the git-diffable data/mikrotik/.
firewall.save_state_report(params.report_dir)
except Exception as e:
message = f"could not read MikroTik router ({firewall.router_ip}): {e}"
errors.append(message)
print(f"\nWARNING: {message}")
firewall.disconnect()
firewall = None
# --- Step 4: run copyparty + NPM analyzers -> blocklist candidates ------
cp_analyzer = CopypartyAnalyzer(
log_path=params.copyparty_log_path,
report_dir=params.copyparty_report_dir,
top=params.top,
quiet=params.quiet,
full=params.full,
min_denied=params.min_denied,
)
npm_analyzer = NpmAnalyzer(
log_path=params.npm_log_path,
report_dir=params.npm_report_dir,
top=params.top,
quiet=params.quiet,
full=params.full,
min_errors=params.min_errors,
error_ratio=params.error_ratio,
)
print("=== Running copyparty scan ===")
cp_exists = True
try:
cp_analyzer.run()
except Exception as e:
errors.append(f"copyparty scan failed: {e}")
print(f"Error running copyparty scan: {e}")
cp_exists = False
print("\n=== Running NPM scan ===")
npm_exists = True
try:
npm_analyzer.run()
except Exception as e:
errors.append(f"NPM scan failed: {e}")
print(f"Error running NPM scan: {e}")
npm_exists = False
if not cp_exists and not npm_exists:
message = "Both scans failed. Unable to generate consolidated blocklist."
errors.append(message)
print(f"\n{message}")
if firewall is not None:
firewall.disconnect()
return ScanResult(ok=False, errors=errors)
# Consolidate block candidates
consolidated_candidates: set[str] = set()
if cp_exists:
consolidated_candidates.update(cp_analyzer.block_candidates())
if npm_exists:
consolidated_candidates.update(npm_analyzer.block_candidates())
# Exclude whitelisted IPs
final_blocked_ips = {
ip for ip in consolidated_candidates if not is_whitelisted(ip)}
# Group into subnets via WHOIS if multiple malicious IPs in same subnet
print("\nGrouping blocked IPs into subnets using WHOIS...")
final_blocked_targets = consolidate_by_subnet(
final_blocked_ips, threshold=SUBNET_THRESHOLD)
blocked_ipv4, blocked_ipv6 = split_cidr_versions(final_blocked_targets)
cp_candidates = len(cp_analyzer.block_candidates()) if cp_exists else 0
npm_candidates = len(npm_analyzer.block_candidates()) if npm_exists else 0
print("\n=== Consolidated Summary ===")
print(f"copyparty block candidates: {cp_candidates}")
print(f"NPM block candidates: {npm_candidates}")
print(f"Total unified blocked IPs: {len(final_blocked_ips)}")
print(f"Total target blocks/subnets: {len(final_blocked_targets)}")
# --- Step 6: write consolidated blocklists to reports/app/data ----------
# Capture the previous blocklist state BEFORE the files are overwritten so
# the change report can compute the complete-set delta.
app_data_dir = os.path.join(params.report_dir, "app", "data")
blocklist_v4_path = os.path.join(app_data_dir, "blocklist_ipv4.txt")
blocklist_v6_path = os.path.join(app_data_dir, "blocklist_ipv6.txt")
prev_v4 = current_file_lines(blocklist_v4_path)
prev_v6 = current_file_lines(blocklist_v6_path)
history_v4 = committed_lines(blocklist_v4_path)
history_v6 = committed_lines(blocklist_v6_path)
write_blocklist_files(blocked_ipv4, blocked_ipv6, params.report_dir)
print(f"blocklist files:\n {blocklist_v4_path}\n {blocklist_v6_path}")
# --- Steps 5+7: compare current state with candidates and apply ---------
firewall_changes: dict | None = None
blocklist_report_path: str | None = None
if firewall is not None:
try:
firewall_changes = firewall.sync_blocklist(
blocked_ipv4, blocked_ipv6, dry_run=params.dry_run,
report_dir=params.report_dir)
finally:
firewall.disconnect()
action = "Would" if params.dry_run else ""
print(f"{action} add {len(firewall_changes['added_ipv4'])} IPv4 and "
f"{len(firewall_changes['added_ipv6'])} IPv6 addresses; "
f"remove {len(firewall_changes['removed_ipv4'])} IPv4 and "
f"{len(firewall_changes['removed_ipv6'])} IPv6 addresses.")
# Timestamped change report — only when the router was reachable.
complete_v4, complete_v6 = cumulative_blocklist(
blocklist_v4_path, blocklist_v6_path,
blocked_ipv4, blocked_ipv6)
blocklist_report_path = write_blocklist_report(
params.report_dir,
history_v4=history_v4, history_v6=history_v6,
prev_v4=prev_v4, prev_v6=prev_v6,
complete_v4=complete_v4, complete_v6=complete_v6,
firewall_changes=firewall_changes,
dry_run=params.dry_run,
errors=errors)
print(f"blocklist report: {blocklist_report_path}")
# --- Step 8: prune old reports (retention) ------------------------------
# Each report subdirectory keeps at most REPORT_RETENTION_MAX_FILES files,
# all newer than REPORT_RETENTION_DAYS days. The blocklist files in
# ``app/data`` are always protected. ``--dry-run`` only previews.
pruned = prune_report_dirs(
params.report_dir, params.copyparty_report_dir, params.npm_report_dir,
dry_run=params.dry_run)
total_pruned = sum(len(paths) for paths in pruned.values())
action = "Would prune" if params.dry_run else "Pruned"
print(f"{action} {total_pruned} report file(s) "
f"(keep {REPORT_RETENTION_DAYS}d / "
f"max {REPORT_RETENTION_MAX_FILES} per dir)")
return ScanResult(
ok=True,
cp_exists=cp_exists,
npm_exists=npm_exists,
cp_candidates=cp_candidates,
npm_candidates=npm_candidates,
blocked_ips=len(final_blocked_ips),
blocked_targets=len(final_blocked_targets),
blocked_ipv4=blocked_ipv4,
blocked_ipv6=blocked_ipv6,
blocklist_v4_path=blocklist_v4_path,
blocklist_v6_path=blocklist_v6_path,
firewall_connected=firewall is not None,
firewall_changes=firewall_changes,
blocklist_report_path=blocklist_report_path,
errors=errors,
)
def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Consolidated IDS Scanner: run copyparty + NPM analyzers and generate unified blocklist."
)
# copyparty arguments
parser.add_argument("--copyparty-log-path", default=COPYPARTY_LOG_PATH,
help=f"copyparty log directory (default: {COPYPARTY_LOG_PATH})")
parser.add_argument("--copyparty-report-dir", default=COPYPARTY_REPORT_DIR,
help=f"copyparty report directory (default: {COPYPARTY_REPORT_DIR})")
parser.add_argument("--min-denied", type=int, default=DEFAULT_MIN_DENIED,
help=f"minimum copyparty denied hits before flagging (default: {DEFAULT_MIN_DENIED})")
# NPM arguments
parser.add_argument("--npm-log-path", default=NPM_LOG_PATH,
help=f"NPM log directory (default: {NPM_LOG_PATH})")
parser.add_argument("--npm-report-dir", default=NPM_REPORT_DIR,
help=f"NPM report directory (default: {NPM_REPORT_DIR})")
parser.add_argument("--min-errors", type=int, default=DEFAULT_MIN_ERRORS,
help=f"minimum NPM error responses to flag (default: {DEFAULT_MIN_ERRORS})")
parser.add_argument("--error-ratio", type=float, default=DEFAULT_ERROR_RATIO,
help=f"minimum NPM error ratio to flag (default: {DEFAULT_ERROR_RATIO})")
# Shared arguments
parser.add_argument("--report-dir", default=REPORT_DIR,
help=f"consolidated reports directory (default: {REPORT_DIR})")
parser.add_argument("--top", type=int, default=DEFAULT_TOP,
help=f"rows in the top-IP tables (default: {DEFAULT_TOP})")
parser.add_argument("--quiet", action="store_true",
help="write files, suppress console reports")
parser.add_argument("--full", action="store_true",
help="rescan all log files from the start (ignore incremental state)")
parser.add_argument("--update-firewall", action="store_true",
help="synchronize the MikroTik Blocked list after scanning")
parser.add_argument("--dry-run", action="store_true",
help="preview firewall changes without applying them")
return parser
def main(argv: list[str] | None = None) -> None:
args = _build_parser().parse_args(argv)
params = ScanParams(
copyparty_log_path=args.copyparty_log_path,
copyparty_report_dir=args.copyparty_report_dir,
min_denied=args.min_denied,
npm_log_path=args.npm_log_path,
npm_report_dir=args.npm_report_dir,
min_errors=args.min_errors,
error_ratio=args.error_ratio,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
update_firewall=args.update_firewall,
dry_run=args.dry_run,
)
run_scan(params)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Consolidated intrusion detection log scanner.
Runs both copyparty and Nginx Proxy Manager (NPM) log analyzers,
and outputs a single consolidated MikroTik RouterOS blocklist.
"""
from __future__ import annotations
import argparse
import os
from dataclasses import dataclass, field
from ..utils.blocklist_history import (
committed_lines,
cumulative_blocklist,
current_file_lines,
write_blocklist_report,
)
from ..utils.constants import (
COPYPARTY_LOG_PATH,
COPYPARTY_REPORT_DIR,
DEFAULT_ERROR_RATIO,
DEFAULT_MIN_DENIED,
DEFAULT_MIN_ERRORS,
DEFAULT_TOP,
NPM_LOG_PATH,
NPM_REPORT_DIR,
REPORT_DIR,
REPORT_RETENTION_DAYS,
REPORT_RETENTION_MAX_FILES,
SUBNET_THRESHOLD,
)
from ..firewall import MikrotikFirewall, write_blocklist_files
from ..utils.retention import prune_report_dirs
from ..copyparty import CopypartyAnalyzer
from ..npm import NpmAnalyzer
from ..utils.ip_utils import is_whitelisted
from ..mikrotik import split_cidr_versions
from ..utils.whois import consolidate_by_subnet
@dataclass
class ScanParams:
"""Configuration for a consolidated scan.
Shared by the CLI entry point and the web interface so both run the
exact same pipeline.
"""
copyparty_log_path: str = COPYPARTY_LOG_PATH
copyparty_report_dir: str = COPYPARTY_REPORT_DIR
min_denied: int = DEFAULT_MIN_DENIED
npm_log_path: str = NPM_LOG_PATH
npm_report_dir: str = NPM_REPORT_DIR
min_errors: int = DEFAULT_MIN_ERRORS
error_ratio: float = DEFAULT_ERROR_RATIO
report_dir: str = REPORT_DIR
top: int = DEFAULT_TOP
quiet: bool = False
full: bool = False
update_firewall: bool = False
dry_run: bool = False
@dataclass
class ScanResult:
"""Structured outcome of a consolidated scan."""
ok: bool
cp_exists: bool = False
npm_exists: bool = False
cp_candidates: int = 0
npm_candidates: int = 0
blocked_ips: int = 0
blocked_targets: int = 0
blocked_ipv4: list[str] = field(default_factory=list)
blocked_ipv6: list[str] = field(default_factory=list)
blocklist_v4_path: str | None = None
blocklist_v6_path: str | None = None
firewall_connected: bool = False
firewall_changes: dict | None = None
blocklist_report_path: str | None = None
errors: list[str] = field(default_factory=list)
def run_scan(params: ScanParams) -> ScanResult:
"""Run the full consolidated scan pipeline and return structured results.
Steps: connect to MikroTik (optional) -> snapshot state -> run copyparty
+ NPM analyzers -> consolidate candidates -> write blocklists -> compare
and apply firewall changes (optional).
"""
errors: list[str] = []
# --- Step 1-3: connect to MikroTik RouterOS and capture current state ---
# If the router is unreachable we fall back to scan-only mode: still
# generate reports and blocklists, but skip the firewall sync.
firewall: MikrotikFirewall | None = None
if params.update_firewall:
firewall = MikrotikFirewall()
try:
firewall.connect()
# Read current firewall rules + address lists and snapshot them to
# reports/mikrotik/data/ and the git-diffable data/mikrotik/.
firewall.save_state_report(params.report_dir)
except Exception as e:
message = f"could not read MikroTik router ({firewall.router_ip}): {e}"
errors.append(message)
print(f"\nWARNING: {message}")
firewall.disconnect()
firewall = None
# --- Step 4: run copyparty + NPM analyzers -> blocklist candidates ------
cp_analyzer = CopypartyAnalyzer(
log_path=params.copyparty_log_path,
report_dir=params.copyparty_report_dir,
top=params.top,
quiet=params.quiet,
full=params.full,
min_denied=params.min_denied,
)
npm_analyzer = NpmAnalyzer(
log_path=params.npm_log_path,
report_dir=params.npm_report_dir,
top=params.top,
quiet=params.quiet,
full=params.full,
min_errors=params.min_errors,
error_ratio=params.error_ratio,
)
print("=== Running copyparty scan ===")
cp_exists = True
try:
cp_analyzer.run()
except Exception as e:
errors.append(f"copyparty scan failed: {e}")
print(f"Error running copyparty scan: {e}")
cp_exists = False
print("\n=== Running NPM scan ===")
npm_exists = True
try:
npm_analyzer.run()
except Exception as e:
errors.append(f"NPM scan failed: {e}")
print(f"Error running NPM scan: {e}")
npm_exists = False
if not cp_exists and not npm_exists:
message = "Both scans failed. Unable to generate consolidated blocklist."
errors.append(message)
print(f"\n{message}")
if firewall is not None:
firewall.disconnect()
return ScanResult(ok=False, errors=errors)
# Consolidate block candidates
consolidated_candidates: set[str] = set()
if cp_exists:
consolidated_candidates.update(cp_analyzer.block_candidates())
if npm_exists:
consolidated_candidates.update(npm_analyzer.block_candidates())
# Exclude whitelisted IPs
final_blocked_ips = {
ip for ip in consolidated_candidates if not is_whitelisted(ip)}
# Group into subnets via WHOIS if multiple malicious IPs in same subnet
print("\nGrouping blocked IPs into subnets using WHOIS...")
final_blocked_targets = consolidate_by_subnet(
final_blocked_ips, threshold=SUBNET_THRESHOLD)
blocked_ipv4, blocked_ipv6 = split_cidr_versions(final_blocked_targets)
cp_candidates = len(cp_analyzer.block_candidates()) if cp_exists else 0
npm_candidates = len(npm_analyzer.block_candidates()) if npm_exists else 0
print("\n=== Consolidated Summary ===")
print(f"copyparty block candidates: {cp_candidates}")
print(f"NPM block candidates: {npm_candidates}")
print(f"Total unified blocked IPs: {len(final_blocked_ips)}")
print(f"Total target blocks/subnets: {len(final_blocked_targets)}")
# --- Step 6: write consolidated blocklists to reports/app/data ----------
# Capture the previous blocklist state BEFORE the files are overwritten so
# the change report can compute the complete-set delta.
app_data_dir = os.path.join(params.report_dir, "app", "data")
blocklist_v4_path = os.path.join(app_data_dir, "blocklist_ipv4.txt")
blocklist_v6_path = os.path.join(app_data_dir, "blocklist_ipv6.txt")
prev_v4 = current_file_lines(blocklist_v4_path)
prev_v6 = current_file_lines(blocklist_v6_path)
history_v4 = committed_lines(blocklist_v4_path)
history_v6 = committed_lines(blocklist_v6_path)
write_blocklist_files(blocked_ipv4, blocked_ipv6, params.report_dir)
print(f"blocklist files:\n {blocklist_v4_path}\n {blocklist_v6_path}")
# --- Steps 5+7: compare current state with candidates and apply ---------
firewall_changes: dict | None = None
blocklist_report_path: str | None = None
if firewall is not None:
try:
firewall_changes = firewall.sync_blocklist(
blocked_ipv4, blocked_ipv6, dry_run=params.dry_run,
report_dir=params.report_dir)
finally:
firewall.disconnect()
action = "Would" if params.dry_run else ""
print(f"{action} add {len(firewall_changes['added_ipv4'])} IPv4 and "
f"{len(firewall_changes['added_ipv6'])} IPv6 addresses; "
f"remove {len(firewall_changes['removed_ipv4'])} IPv4 and "
f"{len(firewall_changes['removed_ipv6'])} IPv6 addresses.")
# Timestamped change report — only when the router was reachable.
complete_v4, complete_v6 = cumulative_blocklist(
blocklist_v4_path, blocklist_v6_path,
blocked_ipv4, blocked_ipv6)
blocklist_report_path = write_blocklist_report(
params.report_dir,
history_v4=history_v4, history_v6=history_v6,
prev_v4=prev_v4, prev_v6=prev_v6,
complete_v4=complete_v4, complete_v6=complete_v6,
firewall_changes=firewall_changes,
dry_run=params.dry_run,
errors=errors)
print(f"blocklist report: {blocklist_report_path}")
# --- Step 8: prune old reports (retention) ------------------------------
# Each report subdirectory keeps at most REPORT_RETENTION_MAX_FILES files,
# all newer than REPORT_RETENTION_DAYS days. The blocklist files in
# ``app/data`` are always protected. ``--dry-run`` only previews.
pruned = prune_report_dirs(
params.report_dir, params.copyparty_report_dir, params.npm_report_dir,
dry_run=params.dry_run)
total_pruned = sum(len(paths) for paths in pruned.values())
action = "Would prune" if params.dry_run else "Pruned"
print(f"{action} {total_pruned} report file(s) "
f"(keep {REPORT_RETENTION_DAYS}d / "
f"max {REPORT_RETENTION_MAX_FILES} per dir)")
return ScanResult(
ok=True,
cp_exists=cp_exists,
npm_exists=npm_exists,
cp_candidates=cp_candidates,
npm_candidates=npm_candidates,
blocked_ips=len(final_blocked_ips),
blocked_targets=len(final_blocked_targets),
blocked_ipv4=blocked_ipv4,
blocked_ipv6=blocked_ipv6,
blocklist_v4_path=blocklist_v4_path,
blocklist_v6_path=blocklist_v6_path,
firewall_connected=firewall is not None,
firewall_changes=firewall_changes,
blocklist_report_path=blocklist_report_path,
errors=errors,
)
def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Consolidated IDS Scanner: run copyparty + NPM analyzers and generate unified blocklist."
)
# copyparty arguments
parser.add_argument("--copyparty-log-path", default=COPYPARTY_LOG_PATH,
help=f"copyparty log directory (default: {COPYPARTY_LOG_PATH})")
parser.add_argument("--copyparty-report-dir", default=COPYPARTY_REPORT_DIR,
help=f"copyparty report directory (default: {COPYPARTY_REPORT_DIR})")
parser.add_argument("--min-denied", type=int, default=DEFAULT_MIN_DENIED,
help=f"minimum copyparty denied hits before flagging (default: {DEFAULT_MIN_DENIED})")
# NPM arguments
parser.add_argument("--npm-log-path", default=NPM_LOG_PATH,
help=f"NPM log directory (default: {NPM_LOG_PATH})")
parser.add_argument("--npm-report-dir", default=NPM_REPORT_DIR,
help=f"NPM report directory (default: {NPM_REPORT_DIR})")
parser.add_argument("--min-errors", type=int, default=DEFAULT_MIN_ERRORS,
help=f"minimum NPM error responses to flag (default: {DEFAULT_MIN_ERRORS})")
parser.add_argument("--error-ratio", type=float, default=DEFAULT_ERROR_RATIO,
help=f"minimum NPM error ratio to flag (default: {DEFAULT_ERROR_RATIO})")
# Shared arguments
parser.add_argument("--report-dir", default=REPORT_DIR,
help=f"consolidated reports directory (default: {REPORT_DIR})")
parser.add_argument("--top", type=int, default=DEFAULT_TOP,
help=f"rows in the top-IP tables (default: {DEFAULT_TOP})")
parser.add_argument("--quiet", action="store_true",
help="write files, suppress console reports")
parser.add_argument("--full", action="store_true",
help="rescan all log files from the start (ignore incremental state)")
parser.add_argument("--update-firewall", action="store_true",
help="synchronize the MikroTik Blocked list after scanning")
parser.add_argument("--dry-run", action="store_true",
help="preview firewall changes without applying them")
return parser
def main(argv: list[str] | None = None) -> None:
args = _build_parser().parse_args(argv)
params = ScanParams(
copyparty_log_path=args.copyparty_log_path,
copyparty_report_dir=args.copyparty_report_dir,
min_denied=args.min_denied,
npm_log_path=args.npm_log_path,
npm_report_dir=args.npm_report_dir,
min_errors=args.min_errors,
error_ratio=args.error_ratio,
report_dir=args.report_dir,
top=args.top,
quiet=args.quiet,
full=args.full,
update_firewall=args.update_firewall,
dry_run=args.dry_run,
)
run_scan(params)
if __name__ == "__main__":
main()
+33 -33
View File
@@ -1,33 +1,33 @@
#!/usr/bin/env python3
"""Persistent state for incremental log scanning.
Tracks the last processed byte offset per absolute log file path so a scan
only reads new entries instead of re-reading the whole file. The state file
is written atomically (temp file + rename) to avoid corruption.
"""
from __future__ import annotations
import json
import os
from ..utils.constants import SCAN_STATE_PATH
def load_state() -> dict[str, int]:
"""Return ``{absolute log path: byte offset}`` from the scan-state file."""
try:
with open(SCAN_STATE_PATH, "r", encoding="utf-8") as f:
data = json.load(f)
return {k: int(v) for k, v in data.items()}
except (OSError, ValueError, TypeError):
return {}
def save_state(state: dict[str, int]) -> None:
"""Write the scan-state file atomically (temp file + rename)."""
os.makedirs(os.path.dirname(SCAN_STATE_PATH), exist_ok=True)
tmp = SCAN_STATE_PATH + ".tmp"
with open(tmp, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2, sort_keys=True)
os.replace(tmp, SCAN_STATE_PATH)
#!/usr/bin/env python3
"""Persistent state for incremental log scanning.
Tracks the last processed byte offset per absolute log file path so a scan
only reads new entries instead of re-reading the whole file. The state file
is written atomically (temp file + rename) to avoid corruption.
"""
from __future__ import annotations
import json
import os
from ..utils.constants import SCAN_STATE_PATH
def load_state() -> dict[str, int]:
"""Return ``{absolute log path: byte offset}`` from the scan-state file."""
try:
with open(SCAN_STATE_PATH, "r", encoding="utf-8") as f:
data = json.load(f)
return {k: int(v) for k, v in data.items()}
except (OSError, ValueError, TypeError):
return {}
def save_state(state: dict[str, int]) -> None:
"""Write the scan-state file atomically (temp file + rename)."""
os.makedirs(os.path.dirname(SCAN_STATE_PATH), exist_ok=True)
tmp = SCAN_STATE_PATH + ".tmp"
with open(tmp, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2, sort_keys=True)
os.replace(tmp, SCAN_STATE_PATH)
+83 -83
View File
@@ -1,83 +1,83 @@
// Shared helpers for the Intrusion Detection web UI.
async function api(path, options = {}) {
const opts = { headers: {}, ...options };
if (opts.body && typeof opts.body !== "string") {
opts.headers["Content-Type"] = "application/json";
opts.body = JSON.stringify(opts.body);
}
const res = await fetch(path, opts);
let data = null;
try {
data = await res.json();
} catch (e) {
/* non-JSON */
}
if (!res.ok) {
const msg = (data && (data.error || data.message)) || `HTTP ${res.status}`;
throw new Error(msg);
}
return data;
}
function escapeHtml(s) {
return String(s ?? "").replace(
/[&<>"']/g,
(c) =>
({
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
})[c],
);
}
function toast(message, type = "info") {
const box = document.getElementById("toasts");
if (!box) return;
const node = document.createElement("div");
node.className = `toast toast-${type}`;
node.textContent = message;
box.appendChild(node);
setTimeout(() => node.remove(), 4000);
}
function fmtTime(s) {
if (!s) return "—";
const d = new Date(s);
return isNaN(d) ? s : d.toLocaleString();
}
function badge(state) {
const node = document.createElement("span");
node.className = `badge ${state}`;
node.textContent = state;
return node;
}
function el(tag, attrs = {}, ...children) {
const node = document.createElement(tag);
// Allow el("tr", child1, child2, ...): if the 2nd argument is a node or an
// array, treat it as the first child instead of an attributes object.
if (attrs && (attrs.nodeType === 1 || Array.isArray(attrs))) {
children.unshift(attrs);
attrs = {};
}
for (const [k, v] of Object.entries(attrs || {})) {
if (k === "class") node.className = v;
else if (k === "text") node.textContent = v;
else if (k === "html") node.innerHTML = v;
else if (k.startsWith("on")) node.addEventListener(k.slice(2), v);
else node.setAttribute(k, v);
}
for (const c of children) {
node.append(c == null ? "" : c);
}
return node;
}
async function startScan(kind, params) {
return api(`/api/scan/${kind}`, { method: "POST", body: params });
}
// Shared helpers for the Intrusion Detection web UI.
async function api(path, options = {}) {
const opts = { headers: {}, ...options };
if (opts.body && typeof opts.body !== "string") {
opts.headers["Content-Type"] = "application/json";
opts.body = JSON.stringify(opts.body);
}
const res = await fetch(path, opts);
let data = null;
try {
data = await res.json();
} catch (e) {
/* non-JSON */
}
if (!res.ok) {
const msg = (data && (data.error || data.message)) || `HTTP ${res.status}`;
throw new Error(msg);
}
return data;
}
function escapeHtml(s) {
return String(s ?? "").replace(
/[&<>"']/g,
(c) =>
({
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
})[c],
);
}
function toast(message, type = "info") {
const box = document.getElementById("toasts");
if (!box) return;
const node = document.createElement("div");
node.className = `toast toast-${type}`;
node.textContent = message;
box.appendChild(node);
setTimeout(() => node.remove(), 4000);
}
function fmtTime(s) {
if (!s) return "—";
const d = new Date(s);
return isNaN(d) ? s : d.toLocaleString();
}
function badge(state) {
const node = document.createElement("span");
node.className = `badge ${state}`;
node.textContent = state;
return node;
}
function el(tag, attrs = {}, ...children) {
const node = document.createElement(tag);
// Allow el("tr", child1, child2, ...): if the 2nd argument is a node or an
// array, treat it as the first child instead of an attributes object.
if (attrs && (attrs.nodeType === 1 || Array.isArray(attrs))) {
children.unshift(attrs);
attrs = {};
}
for (const [k, v] of Object.entries(attrs || {})) {
if (k === "class") node.className = v;
else if (k === "text") node.textContent = v;
else if (k === "html") node.innerHTML = v;
else if (k.startsWith("on")) node.addEventListener(k.slice(2), v);
else node.setAttribute(k, v);
}
for (const c of children) {
node.append(c == null ? "" : c);
}
return node;
}
async function startScan(kind, params) {
return api(`/api/scan/${kind}`, { method: "POST", body: params });
}
+499 -499
View File
@@ -1,499 +1,499 @@
:root {
--bg: #0f172a;
--surface: #1e293b;
--surface-2: #263449;
--border: #334155;
--text: #e2e8f0;
--muted: #94a3b8;
--accent: #22d3ee;
--ok: #34d399;
--warn: #fbbf24;
--danger: #f87171;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.5;
}
.topbar {
display: flex;
align-items: center;
gap: 1.5rem;
padding: 0.75rem 1.5rem;
background: var(--surface);
border-bottom: 1px solid var(--border);
position: sticky;
top: 0;
z-index: 10;
}
.brand {
font-weight: 700;
letter-spacing: 0.02em;
white-space: nowrap;
}
.topbar nav {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.topbar nav a {
color: var(--muted);
text-decoration: none;
padding: 0.4rem 0.75rem;
border-radius: 8px;
font-size: 0.9rem;
}
.topbar nav a:hover {
color: var(--text);
background: var(--surface-2);
}
.topbar nav a.active {
color: var(--accent);
background: var(--surface-2);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 1.5rem;
}
h1 {
font-size: 1.4rem;
margin: 0 0 0.25rem;
}
h2 {
font-size: 1.05rem;
margin: 0;
}
.muted {
color: var(--muted);
}
.mono {
font-family: var(--mono);
font-size: 0.85rem;
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.25rem;
margin: 1rem 0;
}
.panel-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.25rem;
}
.card-label {
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
.card-value {
font-size: 1.5rem;
font-weight: 700;
margin-top: 0.25rem;
}
.card-value.ok {
color: var(--ok);
}
.card-value.warn {
color: var(--warn);
}
.card-value.danger {
color: var(--danger);
}
.card-value.muted {
color: var(--muted);
}
.table {
width: 100%;
border-collapse: collapse;
font-size: 0.88rem;
}
.table th {
text-align: left;
color: var(--muted);
font-weight: 600;
border-bottom: 1px solid var(--border);
padding: 0.5rem 0.6rem;
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.table td {
padding: 0.5rem 0.6rem;
border-bottom: 1px solid var(--border);
}
.table tr:last-child td {
border-bottom: none;
}
.table .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.badge {
display: inline-block;
padding: 0.1rem 0.5rem;
border-radius: 999px;
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.03em;
background: var(--surface-2);
color: var(--muted);
}
.badge.ok,
.badge.done {
background: rgba(52, 211, 153, 0.15);
color: var(--ok);
}
.badge.warn,
.badge.running,
.badge.queued {
background: rgba(251, 191, 36, 0.15);
color: var(--warn);
}
.badge.danger,
.badge.error {
background: rgba(248, 113, 113, 0.15);
color: var(--danger);
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
border: 1px solid var(--border);
background: var(--surface-2);
color: var(--text);
padding: 0.45rem 0.9rem;
border-radius: 8px;
font-size: 0.88rem;
cursor: pointer;
text-decoration: none;
}
.btn:hover {
border-color: var(--accent);
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #062a35;
font-weight: 600;
}
.btn.primary:hover {
filter: brightness(1.08);
}
.btn.danger {
border-color: rgba(248, 113, 113, 0.5);
color: var(--danger);
}
.btn.danger:hover {
background: rgba(248, 113, 113, 0.12);
}
.btn.ghost {
background: transparent;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.panel-actions {
display: flex;
align-items: center;
gap: 1rem;
margin-top: 1rem;
flex-wrap: wrap;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
}
label {
display: flex;
flex-direction: column;
gap: 0.3rem;
font-size: 0.82rem;
color: var(--muted);
}
label.check {
flex-direction: row;
align-items: center;
gap: 0.5rem;
font-size: 0.88rem;
color: var(--text);
margin-top: 1.4rem;
}
input,
select {
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
border-radius: 8px;
padding: 0.45rem 0.6rem;
font-size: 0.88rem;
}
input:focus,
select:focus {
outline: none;
border-color: var(--accent);
}
.job-status {
margin-top: 1rem;
font-family: var(--mono);
font-size: 0.85rem;
}
#toasts {
position: fixed;
bottom: 1rem;
right: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
z-index: 100;
}
.toast {
padding: 0.6rem 1rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
font-size: 0.88rem;
max-width: 360px;
}
.toast-error {
border-color: var(--danger);
color: var(--danger);
}
.toast-ok {
border-color: var(--ok);
color: var(--ok);
}
.toast-warn {
border-color: var(--warn);
color: var(--warn);
}
pre.content {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 1rem;
overflow: auto;
max-height: 480px;
font-family: var(--mono);
font-size: 0.8rem;
white-space: pre-wrap;
}
.list {
display: flex;
flex-direction: column;
gap: 0.25rem;
max-height: 300px;
overflow: auto;
padding: 0.25rem;
}
.list a {
color: var(--accent);
text-decoration: none;
font-family: var(--mono);
font-size: 0.85rem;
padding: 0.2rem 0.4rem;
border-radius: 6px;
}
.list a:hover {
background: var(--surface-2);
}
/* Blocklist display */
.table tbody[id="v4"] td {
padding: 0;
}
.table tbody[id="v4"] td .btn {
border-radius: 0;
border: none;
padding: 0.25rem 0.5rem;
}
/* IPv4 graph page */
.graph-controls {
display: flex;
align-items: center;
gap: 1.25rem;
flex-wrap: wrap;
}
.legend {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.82rem;
color: var(--muted);
}
.sw {
display: inline-block;
width: 0.8rem;
height: 0.8rem;
border-radius: 3px;
border: 1px solid var(--border);
}
.sw.red {
background: #e53935;
}
.sw.green {
background: #43a047;
}
.sw.plain {
background: #fff;
}
.graph-wrap {
position: relative;
width: 100%;
max-width: 920px;
margin: 0 auto;
}
#graph-canvas {
display: block;
width: 100%;
height: auto;
aspect-ratio: 1 / 1;
background: #fff;
border: 1px solid var(--border);
border-radius: 8px;
image-rendering: pixelated;
cursor: crosshair;
}
.graph-overlay {
position: absolute;
inset: 0;
pointer-events: none;
}
.g-line {
position: absolute;
background: rgba(148, 163, 184, 0.55);
}
.g-v {
top: 0;
bottom: 0;
width: 1px;
}
.g-h {
left: 0;
right: 0;
height: 1px;
}
.g-label {
position: absolute;
transform: translate(6px, 4px);
font-size: 0.55rem;
line-height: 1;
color: #475569;
white-space: nowrap;
user-select: none;
text-shadow: 0 0 2px #fff, 0 0 2px #fff;
}
.graph-tooltip {
position: absolute;
z-index: 5;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.5rem 0.65rem;
pointer-events: none;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
max-width: 260px;
}
.graph-tooltip.hidden {
display: none;
}
.tt-head {
font-weight: 600;
margin-bottom: 0.2rem;
}
.tt-status {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.04em;
font-weight: 600;
}
.tt-status.blocked {
color: #e53935;
}
.tt-status.whitelisted {
color: #43a047;
}
.tt-status.unlisted {
color: var(--muted);
}
.tt-list {
margin-top: 0.35rem;
font-size: 0.72rem;
white-space: pre-line;
color: var(--text);
}
:root {
--bg: #0f172a;
--surface: #1e293b;
--surface-2: #263449;
--border: #334155;
--text: #e2e8f0;
--muted: #94a3b8;
--accent: #22d3ee;
--ok: #34d399;
--warn: #fbbf24;
--danger: #f87171;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.5;
}
.topbar {
display: flex;
align-items: center;
gap: 1.5rem;
padding: 0.75rem 1.5rem;
background: var(--surface);
border-bottom: 1px solid var(--border);
position: sticky;
top: 0;
z-index: 10;
}
.brand {
font-weight: 700;
letter-spacing: 0.02em;
white-space: nowrap;
}
.topbar nav {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.topbar nav a {
color: var(--muted);
text-decoration: none;
padding: 0.4rem 0.75rem;
border-radius: 8px;
font-size: 0.9rem;
}
.topbar nav a:hover {
color: var(--text);
background: var(--surface-2);
}
.topbar nav a.active {
color: var(--accent);
background: var(--surface-2);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 1.5rem;
}
h1 {
font-size: 1.4rem;
margin: 0 0 0.25rem;
}
h2 {
font-size: 1.05rem;
margin: 0;
}
.muted {
color: var(--muted);
}
.mono {
font-family: var(--mono);
font-size: 0.85rem;
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.25rem;
margin: 1rem 0;
}
.panel-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.25rem;
}
.card-label {
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
.card-value {
font-size: 1.5rem;
font-weight: 700;
margin-top: 0.25rem;
}
.card-value.ok {
color: var(--ok);
}
.card-value.warn {
color: var(--warn);
}
.card-value.danger {
color: var(--danger);
}
.card-value.muted {
color: var(--muted);
}
.table {
width: 100%;
border-collapse: collapse;
font-size: 0.88rem;
}
.table th {
text-align: left;
color: var(--muted);
font-weight: 600;
border-bottom: 1px solid var(--border);
padding: 0.5rem 0.6rem;
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.table td {
padding: 0.5rem 0.6rem;
border-bottom: 1px solid var(--border);
}
.table tr:last-child td {
border-bottom: none;
}
.table .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.badge {
display: inline-block;
padding: 0.1rem 0.5rem;
border-radius: 999px;
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.03em;
background: var(--surface-2);
color: var(--muted);
}
.badge.ok,
.badge.done {
background: rgba(52, 211, 153, 0.15);
color: var(--ok);
}
.badge.warn,
.badge.running,
.badge.queued {
background: rgba(251, 191, 36, 0.15);
color: var(--warn);
}
.badge.danger,
.badge.error {
background: rgba(248, 113, 113, 0.15);
color: var(--danger);
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
border: 1px solid var(--border);
background: var(--surface-2);
color: var(--text);
padding: 0.45rem 0.9rem;
border-radius: 8px;
font-size: 0.88rem;
cursor: pointer;
text-decoration: none;
}
.btn:hover {
border-color: var(--accent);
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #062a35;
font-weight: 600;
}
.btn.primary:hover {
filter: brightness(1.08);
}
.btn.danger {
border-color: rgba(248, 113, 113, 0.5);
color: var(--danger);
}
.btn.danger:hover {
background: rgba(248, 113, 113, 0.12);
}
.btn.ghost {
background: transparent;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.panel-actions {
display: flex;
align-items: center;
gap: 1rem;
margin-top: 1rem;
flex-wrap: wrap;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
}
label {
display: flex;
flex-direction: column;
gap: 0.3rem;
font-size: 0.82rem;
color: var(--muted);
}
label.check {
flex-direction: row;
align-items: center;
gap: 0.5rem;
font-size: 0.88rem;
color: var(--text);
margin-top: 1.4rem;
}
input,
select {
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
border-radius: 8px;
padding: 0.45rem 0.6rem;
font-size: 0.88rem;
}
input:focus,
select:focus {
outline: none;
border-color: var(--accent);
}
.job-status {
margin-top: 1rem;
font-family: var(--mono);
font-size: 0.85rem;
}
#toasts {
position: fixed;
bottom: 1rem;
right: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
z-index: 100;
}
.toast {
padding: 0.6rem 1rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
font-size: 0.88rem;
max-width: 360px;
}
.toast-error {
border-color: var(--danger);
color: var(--danger);
}
.toast-ok {
border-color: var(--ok);
color: var(--ok);
}
.toast-warn {
border-color: var(--warn);
color: var(--warn);
}
pre.content {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 1rem;
overflow: auto;
max-height: 480px;
font-family: var(--mono);
font-size: 0.8rem;
white-space: pre-wrap;
}
.list {
display: flex;
flex-direction: column;
gap: 0.25rem;
max-height: 300px;
overflow: auto;
padding: 0.25rem;
}
.list a {
color: var(--accent);
text-decoration: none;
font-family: var(--mono);
font-size: 0.85rem;
padding: 0.2rem 0.4rem;
border-radius: 6px;
}
.list a:hover {
background: var(--surface-2);
}
/* Blocklist display */
.table tbody[id="v4"] td {
padding: 0;
}
.table tbody[id="v4"] td .btn {
border-radius: 0;
border: none;
padding: 0.25rem 0.5rem;
}
/* IPv4 graph page */
.graph-controls {
display: flex;
align-items: center;
gap: 1.25rem;
flex-wrap: wrap;
}
.legend {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.82rem;
color: var(--muted);
}
.sw {
display: inline-block;
width: 0.8rem;
height: 0.8rem;
border-radius: 3px;
border: 1px solid var(--border);
}
.sw.red {
background: #e53935;
}
.sw.green {
background: #43a047;
}
.sw.plain {
background: #fff;
}
.graph-wrap {
position: relative;
width: 100%;
max-width: 920px;
margin: 0 auto;
}
#graph-canvas {
display: block;
width: 100%;
height: auto;
aspect-ratio: 1 / 1;
background: #fff;
border: 1px solid var(--border);
border-radius: 8px;
image-rendering: pixelated;
cursor: crosshair;
}
.graph-overlay {
position: absolute;
inset: 0;
pointer-events: none;
}
.g-line {
position: absolute;
background: rgba(148, 163, 184, 0.55);
}
.g-v {
top: 0;
bottom: 0;
width: 1px;
}
.g-h {
left: 0;
right: 0;
height: 1px;
}
.g-label {
position: absolute;
transform: translate(6px, 4px);
font-size: 0.55rem;
line-height: 1;
color: #475569;
white-space: nowrap;
user-select: none;
text-shadow: 0 0 2px #fff, 0 0 2px #fff;
}
.graph-tooltip {
position: absolute;
z-index: 5;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.5rem 0.65rem;
pointer-events: none;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
max-width: 260px;
}
.graph-tooltip.hidden {
display: none;
}
.tt-head {
font-weight: 600;
margin-bottom: 0.2rem;
}
.tt-status {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.04em;
font-weight: 600;
}
.tt-status.blocked {
color: #e53935;
}
.tt-status.whitelisted {
color: #43a047;
}
.tt-status.unlisted {
color: var(--muted);
}
.tt-list {
margin-top: 0.35rem;
font-size: 0.72rem;
white-space: pre-line;
color: var(--text);
}
+50 -50
View File
@@ -1,50 +1,50 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block title %}Intrusion Detection{% endblock %}</title>
<link
rel="stylesheet"
href="{{ url_for('static', filename='style.css') }}"
/>
</head>
<body>
<header class="topbar">
<div class="brand">🛡 Intrusion Detection</div>
<nav>
<a href="/" class="{{ 'active' if request.path == '/' }}">Dashboard</a>
<a href="/scan" class="{{ 'active' if request.path == '/scan' }}"
>Scan</a
>
<a href="/reports" class="{{ 'active' if request.path == '/reports' }}"
>Reports</a
>
<a
href="/blocklist"
class="{{ 'active' if request.path == '/blocklist' }}"
>Blocklist</a
>
<a
href="/firewall"
class="{{ 'active' if request.path == '/firewall' }}"
>Firewall</a
>
<a
href="/whitelist"
class="{{ 'active' if request.path == '/whitelist' }}"
>Whitelist</a
>
<a
href="/graph"
class="{{ 'active' if request.path == '/graph' }}"
>Graph</a
>
</nav>
</header>
<main class="container">{% block content %}{% endblock %}</main>
<div id="toasts"></div>
<script src="{{ url_for('static', filename='app.js') }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block title %}Intrusion Detection{% endblock %}</title>
<link
rel="stylesheet"
href="{{ url_for('static', filename='style.css') }}"
/>
</head>
<body>
<header class="topbar">
<div class="brand">🛡 Intrusion Detection</div>
<nav>
<a href="/" class="{{ 'active' if request.path == '/' }}">Dashboard</a>
<a href="/scan" class="{{ 'active' if request.path == '/scan' }}"
>Scan</a
>
<a href="/reports" class="{{ 'active' if request.path == '/reports' }}"
>Reports</a
>
<a
href="/blocklist"
class="{{ 'active' if request.path == '/blocklist' }}"
>Blocklist</a
>
<a
href="/firewall"
class="{{ 'active' if request.path == '/firewall' }}"
>Firewall</a
>
<a
href="/whitelist"
class="{{ 'active' if request.path == '/whitelist' }}"
>Whitelist</a
>
<a
href="/graph"
class="{{ 'active' if request.path == '/graph' }}"
>Graph</a
>
</nav>
</header>
<main class="container">{% block content %}{% endblock %}</main>
<div id="toasts"></div>
<script src="{{ url_for('static', filename='app.js') }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>
+134 -134
View File
@@ -1,134 +1,134 @@
{% extends "base.html" %} {% block title %}Blocklist — Intrusion Detection{%
endblock %} {% block content %}
<h1>Blocklist</h1>
<p class="muted">
Current consolidated blocklist (from the latest scan). Adding/removing touches
the MikroTik router.
</p>
<div class="panel">
<div class="panel-head"><h2>Add / remove entry</h2></div>
<div class="panel-actions" style="margin-top: 0">
<input
id="ip"
placeholder="IP or CIDR, e.g. 1.2.3.4 or 1.2.0.0/16"
style="min-width: 260px"
/>
<button class="btn primary" id="add-btn">Add to Blocked</button>
<button class="btn danger" id="remove-btn">Remove from Blocked</button>
</div>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv4 <span id="v4-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v4"></tbody>
</table>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv6 <span id="v6-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v6"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadBlocklist() {
try {
const data = await api("/api/blocklist");
render("v4", data.ipv4 || [], "v4-count");
render("v6", data.ipv6 || [], "v6-count");
} catch (e) {
toast(e.message, "error");
}
}
function render(tbodyId, entries, countId) {
const body = document.getElementById(tbodyId);
body.innerHTML = "";
document.getElementById(countId).textContent = `(${entries.length})`;
if (!entries.length) {
body.innerHTML =
'<tr><td colspan="2" class="muted">No entries.</td></tr>';
return;
}
for (const ip of entries) {
body.append(
el(
"tr",
el("td", { class: "mono", text: ip }),
el(
"td",
{ style: "text-align:right" },
el("button", {
class: "btn danger",
text: "Remove",
onclick: () => remove(ip),
}),
),
),
);
}
}
async function act(action) {
const ip = document.getElementById("ip").value.trim();
if (!ip) {
toast("Enter an IP or CIDR", "warn");
return;
}
try {
const data = await api(`/api/blocklist/${action}`, {
method: "POST",
body: { ip },
});
toast(
`Removed ${ip}`.replace(
"Removed",
action === "add" ? "Added" : "Removed",
),
"ok",
);
document.getElementById("ip").value = "";
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
async function remove(ip) {
try {
await api("/api/blocklist/remove", { method: "POST", body: { ip } });
toast(`Removed ${ip}`, "ok");
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
document
.getElementById("add-btn")
.addEventListener("click", () => act("add"));
document
.getElementById("remove-btn")
.addEventListener("click", () => act("remove"));
loadBlocklist();
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Blocklist — Intrusion Detection{%
endblock %} {% block content %}
<h1>Blocklist</h1>
<p class="muted">
Current consolidated blocklist (from the latest scan). Adding/removing touches
the MikroTik router.
</p>
<div class="panel">
<div class="panel-head"><h2>Add / remove entry</h2></div>
<div class="panel-actions" style="margin-top: 0">
<input
id="ip"
placeholder="IP or CIDR, e.g. 1.2.3.4 or 1.2.0.0/16"
style="min-width: 260px"
/>
<button class="btn primary" id="add-btn">Add to Blocked</button>
<button class="btn danger" id="remove-btn">Remove from Blocked</button>
</div>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv4 <span id="v4-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v4"></tbody>
</table>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv6 <span id="v6-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v6"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadBlocklist() {
try {
const data = await api("/api/blocklist");
render("v4", data.ipv4 || [], "v4-count");
render("v6", data.ipv6 || [], "v6-count");
} catch (e) {
toast(e.message, "error");
}
}
function render(tbodyId, entries, countId) {
const body = document.getElementById(tbodyId);
body.innerHTML = "";
document.getElementById(countId).textContent = `(${entries.length})`;
if (!entries.length) {
body.innerHTML =
'<tr><td colspan="2" class="muted">No entries.</td></tr>';
return;
}
for (const ip of entries) {
body.append(
el(
"tr",
el("td", { class: "mono", text: ip }),
el(
"td",
{ style: "text-align:right" },
el("button", {
class: "btn danger",
text: "Remove",
onclick: () => remove(ip),
}),
),
),
);
}
}
async function act(action) {
const ip = document.getElementById("ip").value.trim();
if (!ip) {
toast("Enter an IP or CIDR", "warn");
return;
}
try {
const data = await api(`/api/blocklist/${action}`, {
method: "POST",
body: { ip },
});
toast(
`Removed ${ip}`.replace(
"Removed",
action === "add" ? "Added" : "Removed",
),
"ok",
);
document.getElementById("ip").value = "";
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
async function remove(ip) {
try {
await api("/api/blocklist/remove", { method: "POST", body: { ip } });
toast(`Removed ${ip}`, "ok");
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
document
.getElementById("add-btn")
.addEventListener("click", () => act("add"));
document
.getElementById("remove-btn")
.addEventListener("click", () => act("remove"));
loadBlocklist();
</script>
{% endblock %}
+102 -102
View File
@@ -1,102 +1,102 @@
{% extends "base.html" %} {% block title %}Dashboard — Intrusion Detection{%
endblock %} {% block content %}
<h1>Dashboard</h1>
<p class="muted">
Localhost-only control panel for the intrusion detection scanner.
</p>
<div class="cards" id="status-cards"></div>
<div class="panel">
<div class="panel-head">
<h2>Latest scans</h2>
<a class="btn ghost" href="/scan">Run a scan →</a>
</div>
<table class="table">
<thead>
<tr>
<th>Job</th>
<th>Kind</th>
<th>State</th>
<th>Started</th>
<th>Finished</th>
<th class="num">Blocked</th>
</tr>
</thead>
<tbody id="latest-scans"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadDashboard() {
try {
const s = await api("/api/status");
renderCards(s);
renderScans(s.latest_scans || []);
} catch (e) {
toast(e.message, "error");
}
}
function renderCards(s) {
const cards = [
{
label: "Scan running",
value: s.scan_running ? "Yes" : "No",
tone: s.scan_running ? "warn" : "ok",
},
{ label: "Blocklist IPv4", value: s.blocklist_ipv4_count ?? "—" },
{ label: "Blocklist IPv6", value: s.blocklist_ipv6_count ?? "—" },
{
label: "Firewall snapshot",
value:
s.firewall_snapshot && s.firewall_snapshot.exists
? "Present"
: "None",
tone:
s.firewall_snapshot && s.firewall_snapshot.exists ? "ok" : "muted",
},
];
const box = document.getElementById("status-cards");
box.innerHTML = "";
for (const c of cards) {
box.append(
el(
"div",
{ class: "card" },
el("div", { class: "card-label", text: c.label }),
el("div", { class: `card-value ${c.tone || ""}`, text: c.value }),
),
);
}
}
function renderScans(scans) {
const body = document.getElementById("latest-scans");
body.innerHTML = "";
if (!scans.length) {
body.innerHTML =
'<tr><td colspan="6" class="muted">No scans yet — run one from the Scan page.</td></tr>';
return;
}
for (const j of scans) {
const r = j.result || {};
body.append(
el(
"tr",
el("td", { class: "mono", text: j.job_id }),
el("td", { text: j.kind }),
el("td", {}, badge(j.state)),
el("td", { text: fmtTime(j.started) }),
el("td", { text: fmtTime(j.finished) }),
el("td", { class: "num", text: r.blocked_targets ?? "—" }),
),
);
}
}
loadDashboard();
// Keep the latest-scans table fresh without hammering /api/scan/status.
setInterval(loadDashboard, 15000);
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Dashboard — Intrusion Detection{%
endblock %} {% block content %}
<h1>Dashboard</h1>
<p class="muted">
Localhost-only control panel for the intrusion detection scanner.
</p>
<div class="cards" id="status-cards"></div>
<div class="panel">
<div class="panel-head">
<h2>Latest scans</h2>
<a class="btn ghost" href="/scan">Run a scan →</a>
</div>
<table class="table">
<thead>
<tr>
<th>Job</th>
<th>Kind</th>
<th>State</th>
<th>Started</th>
<th>Finished</th>
<th class="num">Blocked</th>
</tr>
</thead>
<tbody id="latest-scans"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadDashboard() {
try {
const s = await api("/api/status");
renderCards(s);
renderScans(s.latest_scans || []);
} catch (e) {
toast(e.message, "error");
}
}
function renderCards(s) {
const cards = [
{
label: "Scan running",
value: s.scan_running ? "Yes" : "No",
tone: s.scan_running ? "warn" : "ok",
},
{ label: "Blocklist IPv4", value: s.blocklist_ipv4_count ?? "—" },
{ label: "Blocklist IPv6", value: s.blocklist_ipv6_count ?? "—" },
{
label: "Firewall snapshot",
value:
s.firewall_snapshot && s.firewall_snapshot.exists
? "Present"
: "None",
tone:
s.firewall_snapshot && s.firewall_snapshot.exists ? "ok" : "muted",
},
];
const box = document.getElementById("status-cards");
box.innerHTML = "";
for (const c of cards) {
box.append(
el(
"div",
{ class: "card" },
el("div", { class: "card-label", text: c.label }),
el("div", { class: `card-value ${c.tone || ""}`, text: c.value }),
),
);
}
}
function renderScans(scans) {
const body = document.getElementById("latest-scans");
body.innerHTML = "";
if (!scans.length) {
body.innerHTML =
'<tr><td colspan="6" class="muted">No scans yet — run one from the Scan page.</td></tr>';
return;
}
for (const j of scans) {
const r = j.result || {};
body.append(
el(
"tr",
el("td", { class: "mono", text: j.job_id }),
el("td", { text: j.kind }),
el("td", {}, badge(j.state)),
el("td", { text: fmtTime(j.started) }),
el("td", { text: fmtTime(j.finished) }),
el("td", { class: "num", text: r.blocked_targets ?? "—" }),
),
);
}
}
loadDashboard();
// Keep the latest-scans table fresh without hammering /api/scan/status.
setInterval(loadDashboard, 15000);
</script>
{% endblock %}
+176 -176
View File
@@ -1,176 +1,176 @@
{% extends "base.html" %} {% block title %}Firewall — Intrusion Detection{%
endblock %} {% block content %}
<h1>Firewall</h1>
<p class="muted">
Current MikroTik state (from the latest <code>data/mikrotik</code> snapshot).
Sync previews or applies the blocklist diff.
</p>
<div class="panel">
<div class="panel-actions" style="margin-top: 0">
<button class="btn" id="preview-btn">Preview sync (dry-run)</button>
<button class="btn danger" id="apply-btn">Apply sync</button>
<span class="muted" id="fw-result"></span>
</div>
</div>
<div class="panel">
<div class="panel-head"><h2>Address lists</h2></div>
<div id="address-lists"></div>
</div>
<div class="panel">
<div class="panel-head"><h2>Firewall rules</h2></div>
<div id="firewall-rules"></div>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadState() {
try {
const s = await api("/api/firewall/state");
renderAddressLists(s.address_lists || {});
renderRules("firewall-rules", s.firewall_rules || {});
} catch (e) {
toast(e.message, "error");
}
}
function renderAddressLists(addr) {
const box = document.getElementById("address-lists");
box.innerHTML = "";
const byList = {};
for (const version of ["ipv4", "ipv6"]) {
for (const e of addr[version] || []) {
const name = e.list || "?";
(byList[name] = byList[name] || { ipv4: [], ipv6: [] })[version].push(
e.address,
);
}
}
const names = Object.keys(byList);
if (!names.length) {
box.innerHTML =
'<p class="muted">No address-list snapshot available. Run <code>app.py --update-firewall</code> first.</p>';
return;
}
for (const name of names) {
const rows = [];
for (const version of ["ipv4", "ipv6"]) {
const entries = (byList[name][version] || []).sort();
rows.push(
el(
"tr",
el("td", { text: version }),
el("td", { class: "mono", text: entries.join(", ") || "—" }),
),
);
}
box.append(
el(
"div",
{ style: "margin-bottom:1rem" },
el("div", {
style: "font-weight:600;margin-bottom:.4rem",
text: name,
}),
el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Version" }),
el("th", { text: "Addresses" }),
),
),
el("tbody", {}, ...rows),
),
),
);
}
}
function renderRules(boxId, rules) {
const box = document.getElementById(boxId);
box.innerHTML = "";
for (const version of ["ipv4", "ipv6"]) {
const list = rules[version] || [];
const rows = list.map((r) =>
el(
"tr",
el("td", {
class: "mono",
text: r.address ? r.address : r["src-address-list"] || "",
}),
el("td", { text: r.chain || "—" }),
el("td", { text: r.action || "—" }),
el("td", { text: r.comment || "" }),
),
);
box.append(
el(
"div",
{ style: "margin-bottom:1rem" },
el("div", {
style: "font-weight:600;margin-bottom:.4rem",
text: `IPv${version} (${list.length})`,
}),
rows.length
? el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Address / List" }),
el("th", { text: "Chain" }),
el("th", { text: "Action" }),
el("th", { text: "Comment" }),
),
),
el("tbody", {}, ...rows),
)
: el("p", { class: "muted", text: "No rules in snapshot." }),
),
);
}
}
async function sync(dryRun) {
const out = document.getElementById("fw-result");
out.textContent = "Working…";
try {
const changes = await api(`/api/firewall/${dryRun ? "sync" : "apply"}`, {
method: "POST",
body: {},
});
const verb = dryRun ? "Would" : "";
out.textContent =
`${verb} add ${(changes.added_ipv4 || []).length} IPv4 + ${(changes.added_ipv6 || []).length} IPv6; ` +
`remove ${(changes.removed_ipv4 || []).length} IPv4 + ${(changes.removed_ipv6 || []).length} IPv6.`;
toast(
(dryRun ? "Preview" : "Applied") + " firewall sync",
dryRun ? "warn" : "ok",
);
if (!dryRun) loadState();
} catch (e) {
out.textContent = "";
toast(e.message, "error");
}
}
document
.getElementById("preview-btn")
.addEventListener("click", () => sync(true));
document
.getElementById("apply-btn")
.addEventListener("click", () => sync(false));
loadState();
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Firewall — Intrusion Detection{%
endblock %} {% block content %}
<h1>Firewall</h1>
<p class="muted">
Current MikroTik state (from the latest <code>data/mikrotik</code> snapshot).
Sync previews or applies the blocklist diff.
</p>
<div class="panel">
<div class="panel-actions" style="margin-top: 0">
<button class="btn" id="preview-btn">Preview sync (dry-run)</button>
<button class="btn danger" id="apply-btn">Apply sync</button>
<span class="muted" id="fw-result"></span>
</div>
</div>
<div class="panel">
<div class="panel-head"><h2>Address lists</h2></div>
<div id="address-lists"></div>
</div>
<div class="panel">
<div class="panel-head"><h2>Firewall rules</h2></div>
<div id="firewall-rules"></div>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadState() {
try {
const s = await api("/api/firewall/state");
renderAddressLists(s.address_lists || {});
renderRules("firewall-rules", s.firewall_rules || {});
} catch (e) {
toast(e.message, "error");
}
}
function renderAddressLists(addr) {
const box = document.getElementById("address-lists");
box.innerHTML = "";
const byList = {};
for (const version of ["ipv4", "ipv6"]) {
for (const e of addr[version] || []) {
const name = e.list || "?";
(byList[name] = byList[name] || { ipv4: [], ipv6: [] })[version].push(
e.address,
);
}
}
const names = Object.keys(byList);
if (!names.length) {
box.innerHTML =
'<p class="muted">No address-list snapshot available. Run <code>app.py --update-firewall</code> first.</p>';
return;
}
for (const name of names) {
const rows = [];
for (const version of ["ipv4", "ipv6"]) {
const entries = (byList[name][version] || []).sort();
rows.push(
el(
"tr",
el("td", { text: version }),
el("td", { class: "mono", text: entries.join(", ") || "—" }),
),
);
}
box.append(
el(
"div",
{ style: "margin-bottom:1rem" },
el("div", {
style: "font-weight:600;margin-bottom:.4rem",
text: name,
}),
el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Version" }),
el("th", { text: "Addresses" }),
),
),
el("tbody", {}, ...rows),
),
),
);
}
}
function renderRules(boxId, rules) {
const box = document.getElementById(boxId);
box.innerHTML = "";
for (const version of ["ipv4", "ipv6"]) {
const list = rules[version] || [];
const rows = list.map((r) =>
el(
"tr",
el("td", {
class: "mono",
text: r.address ? r.address : r["src-address-list"] || "",
}),
el("td", { text: r.chain || "—" }),
el("td", { text: r.action || "—" }),
el("td", { text: r.comment || "" }),
),
);
box.append(
el(
"div",
{ style: "margin-bottom:1rem" },
el("div", {
style: "font-weight:600;margin-bottom:.4rem",
text: `IPv${version} (${list.length})`,
}),
rows.length
? el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Address / List" }),
el("th", { text: "Chain" }),
el("th", { text: "Action" }),
el("th", { text: "Comment" }),
),
),
el("tbody", {}, ...rows),
)
: el("p", { class: "muted", text: "No rules in snapshot." }),
),
);
}
}
async function sync(dryRun) {
const out = document.getElementById("fw-result");
out.textContent = "Working…";
try {
const changes = await api(`/api/firewall/${dryRun ? "sync" : "apply"}`, {
method: "POST",
body: {},
});
const verb = dryRun ? "Would" : "";
out.textContent =
`${verb} add ${(changes.added_ipv4 || []).length} IPv4 + ${(changes.added_ipv6 || []).length} IPv6; ` +
`remove ${(changes.removed_ipv4 || []).length} IPv4 + ${(changes.removed_ipv6 || []).length} IPv6.`;
toast(
(dryRun ? "Preview" : "Applied") + " firewall sync",
dryRun ? "warn" : "ok",
);
if (!dryRun) loadState();
} catch (e) {
out.textContent = "";
toast(e.message, "error");
}
}
document
.getElementById("preview-btn")
.addEventListener("click", () => sync(true));
document
.getElementById("apply-btn")
.addEventListener("click", () => sync(false));
loadState();
</script>
{% endblock %}
+227 -227
View File
@@ -1,227 +1,227 @@
{% extends "base.html" %} {% block title %}Graph — Intrusion Detection{%
endblock %} {% block content %}
<h1>IPv4 address space map</h1>
<p class="muted">
One pixel per /24 network, arranged as 16×16 tiles of /8 (first octet).
Blocked targets are red, whitelisted ranges are green.
</p>
<div class="panel">
<div class="panel-head">
<div class="graph-controls">
<label class="check" style="margin-top: 0">
<input type="checkbox" id="show-whitelisted" checked />
Show whitelisted
</label>
<span class="legend">
<span class="sw red"></span> Blocked
<span class="sw green"></span> Whitelisted
<span class="sw plain"></span> Unlisted
</span>
</div>
<button class="btn ghost" id="graph-refresh">↻ Refresh</button>
</div>
<div class="graph-wrap" id="graph-wrap">
<canvas id="graph-canvas" width="4096" height="4096"></canvas>
<div class="graph-overlay" id="graph-overlay"></div>
<div class="graph-tooltip hidden" id="graph-tooltip"></div>
</div>
<p class="muted mono" id="graph-stats">Loading…</p>
</div>
{% endblock %} {% block scripts %}
<script>
// Layout mirrors plot.py: 16x16 grid of /8 tiles, each 256x256 px (one pixel
// per /24). Blocked ranges override whitelisted ranges.
const TILE = 16;
const SIZE = 256;
const TOTAL = TILE * SIZE; // 4096
const V_UNLISTED = 0;
const V_WHITELISTED = 1;
const V_BLOCKED = 2;
const COLOR_WHITELISTED = "#43a047";
const COLOR_BLOCKED = "#e53935";
const canvas = document.getElementById("graph-canvas");
const ctx = canvas.getContext("2d");
const overlay = document.getElementById("graph-overlay");
const tooltip = document.getElementById("graph-tooltip");
const stats = document.getElementById("graph-stats");
// /24 index (0..2^24-1) -> value (whitelisted/blocked)
const marked = new Map();
function parseCIDR(s) {
const m = String(s)
.trim()
.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,2}))?$/);
if (!m) return null;
const o = [m[1], m[2], m[3], m[4]].map(Number);
if (o.some((n) => n > 255)) return null;
const prefix = m[5] === undefined ? 32 : Number(m[5]);
if (prefix < 0 || prefix > 32) return null;
const ip = ((o[0] << 24) | (o[1] << 16) | (o[2] << 8) | o[3]) >>> 0;
const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
const network = (ip & mask) >>> 0;
const broadcast = (ip | (~mask >>> 0)) >>> 0;
return {
first24: network >>> 8,
last24: broadcast >>> 8,
label: `${o[0]}.${o[1]}.${o[2]}.${o[3]}/${prefix}`,
};
}
function idxToPos(idx) {
const a = (idx >>> 16) & 0xff;
const b = (idx >>> 8) & 0xff;
const c = idx & 0xff;
return {
x: (a % TILE) * SIZE + b,
y: Math.floor(a / TILE) * SIZE + c,
};
}
function markRange(range, value) {
for (let idx = range.first24; idx <= range.last24; idx++) {
const prev = marked.get(idx);
if (prev === undefined || value > prev) marked.set(idx, value);
}
}
function drawOverlay() {
overlay.innerHTML = "";
// /8 tile borders
for (let i = 0; i <= TILE; i++) {
const pct = (i / TILE) * 100;
const v = el("div", { class: "g-line g-v", style: `left:${pct}%` });
const h = el("div", { class: "g-line g-h", style: `top:${pct}%` });
overlay.append(v, h);
}
// first-octet labels, one per /8 tile
for (let a = 0; a < 256; a++) {
const col = a % TILE;
const row = Math.floor(a / TILE);
overlay.append(
el("div", {
class: "g-label",
style: `left:${(col / TILE) * 100}%;top:${(row / TILE) * 100}%`,
text: `${a}.0.0.0/8`,
}),
);
}
}
function render() {
const showWl = document.getElementById("show-whitelisted").checked;
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, TOTAL, TOTAL);
for (const [idx, value] of marked) {
if (!showWl && value === V_WHITELISTED) continue;
const p = idxToPos(idx);
ctx.fillStyle = value === V_BLOCKED ? COLOR_BLOCKED : COLOR_WHITELISTED;
ctx.fillRect(p.x, p.y, 1, 1);
}
}
// --- hover tooltip ------------------------------------------------------
function matchesIn(ranges, idx) {
const out = [];
for (const r of ranges) {
if (idx >= r.first24 && idx <= r.last24) out.push(r.label);
if (out.length >= 12) break;
}
return out;
}
function showTooltip(e, x, y) {
const tileCol = Math.floor(x / SIZE);
const tileRow = Math.floor(y / SIZE);
const a = tileRow * TILE + tileCol;
const b = x % SIZE;
const c = y % SIZE;
const idx = (a << 16) | (b << 8) | c;
const value = marked.get(idx) ?? V_UNLISTED;
const status =
value === V_BLOCKED
? "blocked"
: value === V_WHITELISTED
? "whitelisted"
: "unlisted";
const entries = matchesIn(blockedRanges, idx).concat(
matchesIn(whitelistedRanges, idx),
);
tooltip.innerHTML = "";
tooltip.append(
el("div", { class: "tt-head mono", text: `${a}.${b}.${c}.0/24` }),
el("div", { class: `tt-status ${status}`, text: status }),
);
if (entries.length) {
tooltip.append(
el("div", { class: "tt-list mono", text: entries.join("\n") }),
);
} else {
tooltip.append(
el("div", { class: "tt-list muted", text: "no matching entry" }),
);
}
tooltip.classList.remove("hidden");
const rect = canvas.getBoundingClientRect();
let left = e.clientX - rect.left + 14;
let top = e.clientY - rect.top + 14;
if (left + tooltip.offsetWidth > rect.width)
left = e.clientX - rect.left - tooltip.offsetWidth - 14;
if (top + tooltip.offsetHeight > rect.height)
top = e.clientY - rect.top - tooltip.offsetHeight - 14;
tooltip.style.left = `${Math.max(0, left)}px`;
tooltip.style.top = `${Math.max(0, top)}px`;
}
canvas.addEventListener("mousemove", (e) => {
const rect = canvas.getBoundingClientRect();
const lx = ((e.clientX - rect.left) * TOTAL) / rect.width;
const ly = ((e.clientY - rect.top) * TOTAL) / rect.height;
const x = Math.floor(lx);
const y = Math.floor(ly);
if (x < 0 || x >= TOTAL || y < 0 || y >= TOTAL) {
tooltip.classList.add("hidden");
return;
}
showTooltip(e, x, y);
});
canvas.addEventListener("mouseleave", () => {
tooltip.classList.add("hidden");
});
// --- load ---------------------------------------------------------------
let blockedRanges = [];
let whitelistedRanges = [];
async function loadGraph() {
try {
const d = await api("/api/graph/ipv4");
blockedRanges = (d.blocked || []).map(parseCIDR).filter(Boolean);
whitelistedRanges = (d.whitelisted || []).map(parseCIDR).filter(Boolean);
marked.clear();
for (const r of whitelistedRanges) markRange(r, V_WHITELISTED);
for (const r of blockedRanges) markRange(r, V_BLOCKED);
render();
drawOverlay();
const c = d.counts || {};
stats.textContent = `blocked targets: ${c.blocked ?? blockedRanges.length} · whitelisted ranges: ${c.whitelisted ?? whitelistedRanges.length} · marked /24 pixels: ${marked.size}`;
} catch (err) {
stats.textContent = `failed to load graph data: ${err.message}`;
toast(err.message, "error");
}
}
document
.getElementById("show-whitelisted")
.addEventListener("change", render);
document.getElementById("graph-refresh").addEventListener("click", loadGraph);
loadGraph();
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Graph — Intrusion Detection{%
endblock %} {% block content %}
<h1>IPv4 address space map</h1>
<p class="muted">
One pixel per /24 network, arranged as 16×16 tiles of /8 (first octet).
Blocked targets are red, whitelisted ranges are green.
</p>
<div class="panel">
<div class="panel-head">
<div class="graph-controls">
<label class="check" style="margin-top: 0">
<input type="checkbox" id="show-whitelisted" checked />
Show whitelisted
</label>
<span class="legend">
<span class="sw red"></span> Blocked
<span class="sw green"></span> Whitelisted
<span class="sw plain"></span> Unlisted
</span>
</div>
<button class="btn ghost" id="graph-refresh">↻ Refresh</button>
</div>
<div class="graph-wrap" id="graph-wrap">
<canvas id="graph-canvas" width="4096" height="4096"></canvas>
<div class="graph-overlay" id="graph-overlay"></div>
<div class="graph-tooltip hidden" id="graph-tooltip"></div>
</div>
<p class="muted mono" id="graph-stats">Loading…</p>
</div>
{% endblock %} {% block scripts %}
<script>
// Layout mirrors plot.py: 16x16 grid of /8 tiles, each 256x256 px (one pixel
// per /24). Blocked ranges override whitelisted ranges.
const TILE = 16;
const SIZE = 256;
const TOTAL = TILE * SIZE; // 4096
const V_UNLISTED = 0;
const V_WHITELISTED = 1;
const V_BLOCKED = 2;
const COLOR_WHITELISTED = "#43a047";
const COLOR_BLOCKED = "#e53935";
const canvas = document.getElementById("graph-canvas");
const ctx = canvas.getContext("2d");
const overlay = document.getElementById("graph-overlay");
const tooltip = document.getElementById("graph-tooltip");
const stats = document.getElementById("graph-stats");
// /24 index (0..2^24-1) -> value (whitelisted/blocked)
const marked = new Map();
function parseCIDR(s) {
const m = String(s)
.trim()
.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,2}))?$/);
if (!m) return null;
const o = [m[1], m[2], m[3], m[4]].map(Number);
if (o.some((n) => n > 255)) return null;
const prefix = m[5] === undefined ? 32 : Number(m[5]);
if (prefix < 0 || prefix > 32) return null;
const ip = ((o[0] << 24) | (o[1] << 16) | (o[2] << 8) | o[3]) >>> 0;
const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
const network = (ip & mask) >>> 0;
const broadcast = (ip | (~mask >>> 0)) >>> 0;
return {
first24: network >>> 8,
last24: broadcast >>> 8,
label: `${o[0]}.${o[1]}.${o[2]}.${o[3]}/${prefix}`,
};
}
function idxToPos(idx) {
const a = (idx >>> 16) & 0xff;
const b = (idx >>> 8) & 0xff;
const c = idx & 0xff;
return {
x: (a % TILE) * SIZE + b,
y: Math.floor(a / TILE) * SIZE + c,
};
}
function markRange(range, value) {
for (let idx = range.first24; idx <= range.last24; idx++) {
const prev = marked.get(idx);
if (prev === undefined || value > prev) marked.set(idx, value);
}
}
function drawOverlay() {
overlay.innerHTML = "";
// /8 tile borders
for (let i = 0; i <= TILE; i++) {
const pct = (i / TILE) * 100;
const v = el("div", { class: "g-line g-v", style: `left:${pct}%` });
const h = el("div", { class: "g-line g-h", style: `top:${pct}%` });
overlay.append(v, h);
}
// first-octet labels, one per /8 tile
for (let a = 0; a < 256; a++) {
const col = a % TILE;
const row = Math.floor(a / TILE);
overlay.append(
el("div", {
class: "g-label",
style: `left:${(col / TILE) * 100}%;top:${(row / TILE) * 100}%`,
text: `${a}.0.0.0/8`,
}),
);
}
}
function render() {
const showWl = document.getElementById("show-whitelisted").checked;
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, TOTAL, TOTAL);
for (const [idx, value] of marked) {
if (!showWl && value === V_WHITELISTED) continue;
const p = idxToPos(idx);
ctx.fillStyle = value === V_BLOCKED ? COLOR_BLOCKED : COLOR_WHITELISTED;
ctx.fillRect(p.x, p.y, 1, 1);
}
}
// --- hover tooltip ------------------------------------------------------
function matchesIn(ranges, idx) {
const out = [];
for (const r of ranges) {
if (idx >= r.first24 && idx <= r.last24) out.push(r.label);
if (out.length >= 12) break;
}
return out;
}
function showTooltip(e, x, y) {
const tileCol = Math.floor(x / SIZE);
const tileRow = Math.floor(y / SIZE);
const a = tileRow * TILE + tileCol;
const b = x % SIZE;
const c = y % SIZE;
const idx = (a << 16) | (b << 8) | c;
const value = marked.get(idx) ?? V_UNLISTED;
const status =
value === V_BLOCKED
? "blocked"
: value === V_WHITELISTED
? "whitelisted"
: "unlisted";
const entries = matchesIn(blockedRanges, idx).concat(
matchesIn(whitelistedRanges, idx),
);
tooltip.innerHTML = "";
tooltip.append(
el("div", { class: "tt-head mono", text: `${a}.${b}.${c}.0/24` }),
el("div", { class: `tt-status ${status}`, text: status }),
);
if (entries.length) {
tooltip.append(
el("div", { class: "tt-list mono", text: entries.join("\n") }),
);
} else {
tooltip.append(
el("div", { class: "tt-list muted", text: "no matching entry" }),
);
}
tooltip.classList.remove("hidden");
const rect = canvas.getBoundingClientRect();
let left = e.clientX - rect.left + 14;
let top = e.clientY - rect.top + 14;
if (left + tooltip.offsetWidth > rect.width)
left = e.clientX - rect.left - tooltip.offsetWidth - 14;
if (top + tooltip.offsetHeight > rect.height)
top = e.clientY - rect.top - tooltip.offsetHeight - 14;
tooltip.style.left = `${Math.max(0, left)}px`;
tooltip.style.top = `${Math.max(0, top)}px`;
}
canvas.addEventListener("mousemove", (e) => {
const rect = canvas.getBoundingClientRect();
const lx = ((e.clientX - rect.left) * TOTAL) / rect.width;
const ly = ((e.clientY - rect.top) * TOTAL) / rect.height;
const x = Math.floor(lx);
const y = Math.floor(ly);
if (x < 0 || x >= TOTAL || y < 0 || y >= TOTAL) {
tooltip.classList.add("hidden");
return;
}
showTooltip(e, x, y);
});
canvas.addEventListener("mouseleave", () => {
tooltip.classList.add("hidden");
});
// --- load ---------------------------------------------------------------
let blockedRanges = [];
let whitelistedRanges = [];
async function loadGraph() {
try {
const d = await api("/api/graph/ipv4");
blockedRanges = (d.blocked || []).map(parseCIDR).filter(Boolean);
whitelistedRanges = (d.whitelisted || []).map(parseCIDR).filter(Boolean);
marked.clear();
for (const r of whitelistedRanges) markRange(r, V_WHITELISTED);
for (const r of blockedRanges) markRange(r, V_BLOCKED);
render();
drawOverlay();
const c = d.counts || {};
stats.textContent = `blocked targets: ${c.blocked ?? blockedRanges.length} · whitelisted ranges: ${c.whitelisted ?? whitelistedRanges.length} · marked /24 pixels: ${marked.size}`;
} catch (err) {
stats.textContent = `failed to load graph data: ${err.message}`;
toast(err.message, "error");
}
}
document
.getElementById("show-whitelisted")
.addEventListener("change", render);
document.getElementById("graph-refresh").addEventListener("click", loadGraph);
loadGraph();
</script>
{% endblock %}
+76 -76
View File
@@ -1,76 +1,76 @@
{% extends "base.html" %} {% block title %}Reports — Intrusion Detection{%
endblock %} {% block content %}
<h1>Reports</h1>
<p class="muted">Browse the timestamped reports written by each scanner.</p>
<div class="panel">
<div class="panel-actions" style="margin-top: 0">
<label style="flex-direction: row; align-items: center; gap: 0.5rem"
>Source
<select id="source">
<option value="copyparty">copyparty</option>
<option value="npm">npm</option>
<option value="app">app</option>
<option value="mikrotik">mikrotik</option>
</select>
</label>
<button class="btn" id="refresh-btn">Refresh</button>
</div>
<div class="list" id="files"></div>
</div>
<div class="panel">
<div class="panel-head"><h2 id="content-title">Report content</h2></div>
<pre class="content" id="content">
Select a report on the left to view it.</pre
>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadFiles() {
const source = document.getElementById("source").value;
const list = document.getElementById("files");
list.innerHTML = '<div class="muted">Loading…</div>';
try {
const data = await api(`/api/reports/${source}`);
list.innerHTML = "";
const files = data.files || [];
if (!files.length) {
list.innerHTML = '<div class="muted">No reports in this source.</div>';
return;
}
for (const name of files) {
list.append(
el("a", {
href: "#",
text: name,
onclick: (ev) => {
ev.preventDefault();
openReport(name);
},
}),
);
}
} catch (e) {
list.innerHTML = `<div class="muted">${escapeHtml(e.message)}</div>`;
}
}
async function openReport(name) {
const source = document.getElementById("source").value;
document.getElementById("content-title").textContent = name;
const pre = document.getElementById("content");
pre.textContent = "Loading…";
try {
const data = await api(`/api/reports/${source}/${name}`);
pre.textContent = data.content;
} catch (e) {
pre.textContent = `Error: ${e.message}`;
}
}
document.getElementById("refresh-btn").addEventListener("click", loadFiles);
document.getElementById("source").addEventListener("change", loadFiles);
loadFiles();
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Reports — Intrusion Detection{%
endblock %} {% block content %}
<h1>Reports</h1>
<p class="muted">Browse the timestamped reports written by each scanner.</p>
<div class="panel">
<div class="panel-actions" style="margin-top: 0">
<label style="flex-direction: row; align-items: center; gap: 0.5rem"
>Source
<select id="source">
<option value="copyparty">copyparty</option>
<option value="npm">npm</option>
<option value="app">app</option>
<option value="mikrotik">mikrotik</option>
</select>
</label>
<button class="btn" id="refresh-btn">Refresh</button>
</div>
<div class="list" id="files"></div>
</div>
<div class="panel">
<div class="panel-head"><h2 id="content-title">Report content</h2></div>
<pre class="content" id="content">
Select a report on the left to view it.</pre
>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadFiles() {
const source = document.getElementById("source").value;
const list = document.getElementById("files");
list.innerHTML = '<div class="muted">Loading…</div>';
try {
const data = await api(`/api/reports/${source}`);
list.innerHTML = "";
const files = data.files || [];
if (!files.length) {
list.innerHTML = '<div class="muted">No reports in this source.</div>';
return;
}
for (const name of files) {
list.append(
el("a", {
href: "#",
text: name,
onclick: (ev) => {
ev.preventDefault();
openReport(name);
},
}),
);
}
} catch (e) {
list.innerHTML = `<div class="muted">${escapeHtml(e.message)}</div>`;
}
}
async function openReport(name) {
const source = document.getElementById("source").value;
document.getElementById("content-title").textContent = name;
const pre = document.getElementById("content");
pre.textContent = "Loading…";
try {
const data = await api(`/api/reports/${source}/${name}`);
pre.textContent = data.content;
} catch (e) {
pre.textContent = `Error: ${e.message}`;
}
}
document.getElementById("refresh-btn").addEventListener("click", loadFiles);
document.getElementById("source").addEventListener("change", loadFiles);
loadFiles();
</script>
{% endblock %}
+185 -185
View File
@@ -1,185 +1,185 @@
{% extends "base.html" %} {% block title %}Scan — Intrusion Detection{% endblock
%} {% block content %}
<h1>Run a scan</h1>
<p class="muted">
Scans run in the background; only one at a time. You can leave this page and
come back.
</p>
<div class="panel">
<form id="scan-form" class="form-grid">
<label
>Type
<select id="kind">
<option value="consolidated">Consolidated (copyparty + npm)</option>
<option value="copyparty">copyparty only</option>
<option value="npm">npm only</option>
</select>
</label>
<label>Top IPs <input id="top" type="number" value="30" min="1" /></label>
<label
>Min denied (copyparty)
<input id="min_denied" type="number" value="1" min="0"
/></label>
<label
>Min errors (npm) <input id="min_errors" type="number" value="5" min="0"
/></label>
<label
>Error ratio (npm)
<input
id="error_ratio"
type="number"
step="0.05"
value="0.5"
min="0"
max="1"
/></label>
<label class="check"
><input id="update_firewall" type="checkbox" /> Update firewall after
scan</label
>
<label class="check"
><input id="dry_run" type="checkbox" /> Dry-run (preview, no
changes)</label
>
<label class="check"
><input id="full" type="checkbox" /> Full scan (ignore incremental
state)</label
>
</form>
<div class="panel-actions">
<button class="btn primary" id="run-btn">Run scan</button>
<span class="muted" id="busy-hint"></span>
</div>
<div id="job-status" class="job-status"></div>
</div>
<div class="panel">
<div class="panel-head"><h2>Recent jobs</h2></div>
<table class="table">
<thead>
<tr>
<th>Job</th>
<th>Kind</th>
<th>State</th>
<th>Started</th>
<th>Finished</th>
<th class="num">Blocked</th>
</tr>
</thead>
<tbody id="jobs"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
let pollTimer = null;
const form = document.getElementById("scan-form");
const runBtn = document.getElementById("run-btn");
const hint = document.getElementById("busy-hint");
async function runScan() {
const kind = document.getElementById("kind").value;
const params = {
top: parseInt(document.getElementById("top").value, 10) || 30,
min_denied:
parseInt(document.getElementById("min_denied").value, 10) || 1,
min_errors:
parseInt(document.getElementById("min_errors").value, 10) || 5,
error_ratio:
parseFloat(document.getElementById("error_ratio").value) || 0.5,
update_firewall: document.getElementById("update_firewall").checked,
dry_run: document.getElementById("dry_run").checked,
full: document.getElementById("full").checked,
quiet: true,
};
runBtn.disabled = true;
try {
const job = await startScan(kind, params);
setStatus(`Job ${job.job_id} started (${job.state}).`, "ok");
poll(job.job_id);
} catch (e) {
setStatus(e.message, "error");
runBtn.disabled = false;
}
}
function setStatus(msg, type) {
const box = document.getElementById("job-status");
box.textContent = msg;
box.style.color =
type === "error"
? "var(--danger)"
: type === "ok"
? "var(--ok)"
: "inherit";
}
async function poll(jobId) {
clearTimeout(pollTimer);
let job;
try {
job = await api(`/api/scan/${jobId}`);
} catch (e) {
setStatus(e.message, "error");
runBtn.disabled = false;
return;
}
const r = job.result || {};
setStatus(
`[${job.state}] ${job.kind} — started ${fmtTime(job.started)}` +
(job.finished ? `, finished ${fmtTime(job.finished)}` : "") +
(r.blocked_targets != null
? `, blocked targets: ${r.blocked_targets}`
: "") +
(job.error ? `, error: ${job.error}` : ""),
job.state === "error" ? "error" : job.state === "done" ? "ok" : "",
);
if (job.state === "running" || job.state === "queued") {
pollTimer = setTimeout(() => poll(jobId), 2000);
} else {
runBtn.disabled = false;
refreshJobs();
const running = (await api("/api/scan/status")).running;
hint.textContent = running ? "" : "";
}
}
async function refreshJobs() {
try {
const s = await api("/api/scan/status");
hint.textContent = s.running ? "A scan is currently running…" : "";
const body = document.getElementById("jobs");
body.innerHTML = "";
const jobs = s.latest_scans || [];
if (!jobs.length) {
body.innerHTML =
'<tr><td colspan="6" class="muted">No jobs yet.</td></tr>';
return;
}
for (const j of jobs) {
const r = j.result || {};
body.append(
el(
"tr",
el("td", { class: "mono", text: j.job_id }),
el("td", { text: j.kind }),
el("td", {}, badge(j.state)),
el("td", { text: fmtTime(j.started) }),
el("td", { text: fmtTime(j.finished) }),
el("td", { class: "num", text: r.blocked_targets ?? "—" }),
),
);
}
} catch (e) {
toast(e.message, "error");
}
}
runBtn.addEventListener("click", runScan);
refreshJobs();
// /api/scan/status is only polled every 15 s; the active job's own
// 2 s poll keeps live progress without hammering the status endpoint.
setInterval(refreshJobs, 15000);
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Scan — Intrusion Detection{% endblock
%} {% block content %}
<h1>Run a scan</h1>
<p class="muted">
Scans run in the background; only one at a time. You can leave this page and
come back.
</p>
<div class="panel">
<form id="scan-form" class="form-grid">
<label
>Type
<select id="kind">
<option value="consolidated">Consolidated (copyparty + npm)</option>
<option value="copyparty">copyparty only</option>
<option value="npm">npm only</option>
</select>
</label>
<label>Top IPs <input id="top" type="number" value="30" min="1" /></label>
<label
>Min denied (copyparty)
<input id="min_denied" type="number" value="1" min="0"
/></label>
<label
>Min errors (npm) <input id="min_errors" type="number" value="5" min="0"
/></label>
<label
>Error ratio (npm)
<input
id="error_ratio"
type="number"
step="0.05"
value="0.5"
min="0"
max="1"
/></label>
<label class="check"
><input id="update_firewall" type="checkbox" /> Update firewall after
scan</label
>
<label class="check"
><input id="dry_run" type="checkbox" /> Dry-run (preview, no
changes)</label
>
<label class="check"
><input id="full" type="checkbox" /> Full scan (ignore incremental
state)</label
>
</form>
<div class="panel-actions">
<button class="btn primary" id="run-btn">Run scan</button>
<span class="muted" id="busy-hint"></span>
</div>
<div id="job-status" class="job-status"></div>
</div>
<div class="panel">
<div class="panel-head"><h2>Recent jobs</h2></div>
<table class="table">
<thead>
<tr>
<th>Job</th>
<th>Kind</th>
<th>State</th>
<th>Started</th>
<th>Finished</th>
<th class="num">Blocked</th>
</tr>
</thead>
<tbody id="jobs"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
let pollTimer = null;
const form = document.getElementById("scan-form");
const runBtn = document.getElementById("run-btn");
const hint = document.getElementById("busy-hint");
async function runScan() {
const kind = document.getElementById("kind").value;
const params = {
top: parseInt(document.getElementById("top").value, 10) || 30,
min_denied:
parseInt(document.getElementById("min_denied").value, 10) || 1,
min_errors:
parseInt(document.getElementById("min_errors").value, 10) || 5,
error_ratio:
parseFloat(document.getElementById("error_ratio").value) || 0.5,
update_firewall: document.getElementById("update_firewall").checked,
dry_run: document.getElementById("dry_run").checked,
full: document.getElementById("full").checked,
quiet: true,
};
runBtn.disabled = true;
try {
const job = await startScan(kind, params);
setStatus(`Job ${job.job_id} started (${job.state}).`, "ok");
poll(job.job_id);
} catch (e) {
setStatus(e.message, "error");
runBtn.disabled = false;
}
}
function setStatus(msg, type) {
const box = document.getElementById("job-status");
box.textContent = msg;
box.style.color =
type === "error"
? "var(--danger)"
: type === "ok"
? "var(--ok)"
: "inherit";
}
async function poll(jobId) {
clearTimeout(pollTimer);
let job;
try {
job = await api(`/api/scan/${jobId}`);
} catch (e) {
setStatus(e.message, "error");
runBtn.disabled = false;
return;
}
const r = job.result || {};
setStatus(
`[${job.state}] ${job.kind} — started ${fmtTime(job.started)}` +
(job.finished ? `, finished ${fmtTime(job.finished)}` : "") +
(r.blocked_targets != null
? `, blocked targets: ${r.blocked_targets}`
: "") +
(job.error ? `, error: ${job.error}` : ""),
job.state === "error" ? "error" : job.state === "done" ? "ok" : "",
);
if (job.state === "running" || job.state === "queued") {
pollTimer = setTimeout(() => poll(jobId), 2000);
} else {
runBtn.disabled = false;
refreshJobs();
const running = (await api("/api/scan/status")).running;
hint.textContent = running ? "" : "";
}
}
async function refreshJobs() {
try {
const s = await api("/api/scan/status");
hint.textContent = s.running ? "A scan is currently running…" : "";
const body = document.getElementById("jobs");
body.innerHTML = "";
const jobs = s.latest_scans || [];
if (!jobs.length) {
body.innerHTML =
'<tr><td colspan="6" class="muted">No jobs yet.</td></tr>';
return;
}
for (const j of jobs) {
const r = j.result || {};
body.append(
el(
"tr",
el("td", { class: "mono", text: j.job_id }),
el("td", { text: j.kind }),
el("td", {}, badge(j.state)),
el("td", { text: fmtTime(j.started) }),
el("td", { text: fmtTime(j.finished) }),
el("td", { class: "num", text: r.blocked_targets ?? "—" }),
),
);
}
} catch (e) {
toast(e.message, "error");
}
}
runBtn.addEventListener("click", runScan);
refreshJobs();
// /api/scan/status is only polled every 15 s; the active job's own
// 2 s poll keeps live progress without hammering the status endpoint.
setInterval(refreshJobs, 15000);
</script>
{% endblock %}
+110 -110
View File
@@ -1,110 +1,110 @@
{% extends "base.html" %} {% block title %}Whitelist — Intrusion Detection{%
endblock %} {% block content %}
<h1>Whitelist</h1>
<p class="muted">
Provider whitelists (from the router snapshot). Never add a whole cloud
provider to the blocklist.
</p>
<div class="panel">
<div class="panel-head"><h2>Add / remove CIDR</h2></div>
<div class="panel-actions" style="margin-top: 0">
<select id="wl-name">
{% for name in whitelist_names %}
<option value="{{ name }}">{{ name }}</option>
{% endfor %}
</select>
<input
id="wl-address"
placeholder="CIDR, e.g. 1.2.3.0/24"
style="min-width: 220px"
/>
<button class="btn primary" id="wl-add-btn">Add</button>
<button class="btn danger" id="wl-remove-btn">Remove</button>
</div>
</div>
<div id="whitelists"></div>
{% endblock %} {% block scripts %}
<script>
async function loadWhitelists() {
try {
const data = await api("/api/whitelist");
const box = document.getElementById("whitelists");
box.innerHTML = "";
for (const name of data.names || []) {
const w = data.whitelists[name] || {};
const rows = [];
for (const version of ["ipv4", "ipv6"]) {
const entries = (w[version] || []).sort();
rows.push(
el(
"tr",
el("td", { text: version }),
el("td", { class: "mono", text: entries.join(", ") || "—" }),
),
);
}
box.append(
el(
"div",
{ class: "panel" },
el(
"div",
{ class: "panel-head" },
el("h2", {
text: `${name} (${(w.ipv4 || []).length + (w.ipv6 || []).length})`,
}),
),
el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Version" }),
el("th", { text: "Addresses" }),
),
),
el("tbody", {}, ...rows),
),
),
);
}
} catch (e) {
toast(e.message, "error");
}
}
async function act(action) {
const name = document.getElementById("wl-name").value;
const address = document.getElementById("wl-address").value.trim();
if (!address) {
toast("Enter a CIDR", "warn");
return;
}
try {
await api("/api/whitelist/update", {
method: "POST",
body: { name, address, action },
});
toast(`${action} ${address} on ${name}`, "ok");
document.getElementById("wl-address").value = "";
loadWhitelists();
} catch (e) {
toast(e.message, "error");
}
}
document
.getElementById("wl-add-btn")
.addEventListener("click", () => act("add"));
document
.getElementById("wl-remove-btn")
.addEventListener("click", () => act("remove"));
loadWhitelists();
</script>
{% endblock %}
{% extends "base.html" %} {% block title %}Whitelist — Intrusion Detection{%
endblock %} {% block content %}
<h1>Whitelist</h1>
<p class="muted">
Provider whitelists (from the router snapshot). Never add a whole cloud
provider to the blocklist.
</p>
<div class="panel">
<div class="panel-head"><h2>Add / remove CIDR</h2></div>
<div class="panel-actions" style="margin-top: 0">
<select id="wl-name">
{% for name in whitelist_names %}
<option value="{{ name }}">{{ name }}</option>
{% endfor %}
</select>
<input
id="wl-address"
placeholder="CIDR, e.g. 1.2.3.0/24"
style="min-width: 220px"
/>
<button class="btn primary" id="wl-add-btn">Add</button>
<button class="btn danger" id="wl-remove-btn">Remove</button>
</div>
</div>
<div id="whitelists"></div>
{% endblock %} {% block scripts %}
<script>
async function loadWhitelists() {
try {
const data = await api("/api/whitelist");
const box = document.getElementById("whitelists");
box.innerHTML = "";
for (const name of data.names || []) {
const w = data.whitelists[name] || {};
const rows = [];
for (const version of ["ipv4", "ipv6"]) {
const entries = (w[version] || []).sort();
rows.push(
el(
"tr",
el("td", { text: version }),
el("td", { class: "mono", text: entries.join(", ") || "—" }),
),
);
}
box.append(
el(
"div",
{ class: "panel" },
el(
"div",
{ class: "panel-head" },
el("h2", {
text: `${name} (${(w.ipv4 || []).length + (w.ipv6 || []).length})`,
}),
),
el(
"table",
{ class: "table" },
el(
"thead",
{},
el(
"tr",
{},
el("th", { text: "Version" }),
el("th", { text: "Addresses" }),
),
),
el("tbody", {}, ...rows),
),
),
);
}
} catch (e) {
toast(e.message, "error");
}
}
async function act(action) {
const name = document.getElementById("wl-name").value;
const address = document.getElementById("wl-address").value.trim();
if (!address) {
toast("Enter a CIDR", "warn");
return;
}
try {
await api("/api/whitelist/update", {
method: "POST",
body: { name, address, action },
});
toast(`${action} ${address} on ${name}`, "ok");
document.getElementById("wl-address").value = "";
loadWhitelists();
} catch (e) {
toast(e.message, "error");
}
}
document
.getElementById("wl-add-btn")
.addEventListener("click", () => act("add"));
document
.getElementById("wl-remove-btn")
.addEventListener("click", () => act("remove"));
loadWhitelists();
</script>
{% endblock %}
+13 -13
View File
@@ -1,13 +1,13 @@
# Intrusion Detection System — shared utilities
#
# Modules:
# constants.py central configuration, paths, env vars
# files.py filesystem & I/O helpers
# ip_utils.py IP address parsing, validation, whitelist lookup
# models.py data models (Request, IPStats) + aggregate()
# reporting.py text rendering, table formatting
# utils.py shared CLI arg parser
# whitelists.py whitelist CIDR download, caching, validation
# whois.py WHOIS subnet queries, IP consolidation
# blocklist_history.py git-backed cumulative blocklist reconstruction
# retention.py report file retention & pruning
# Intrusion Detection System — shared utilities
#
# Modules:
# constants.py central configuration, paths, env vars
# files.py filesystem & I/O helpers
# ip_utils.py IP address parsing, validation, whitelist lookup
# models.py data models (Request, IPStats) + aggregate()
# reporting.py text rendering, table formatting
# utils.py shared CLI arg parser
# whitelists.py whitelist CIDR download, caching, validation
# whois.py WHOIS subnet queries, IP consolidation
# blocklist_history.py git-backed cumulative blocklist reconstruction
# retention.py report file retention & pruning
+186 -186
View File
@@ -1,186 +1,186 @@
#!/usr/bin/env python3
"""Git-backed cumulative blocklist history.
The consolidated blocklist lives in git-tracked files
(``reports/app/data/blocklist_ipv4.txt`` / ``blocklist_ipv6.txt``). To make the
MikroTik blocklist grow-only, the "complete set of all blocked IPs" is
reconstructed from **every git revision** of those files (the union of all
lines ever present), plus the current working files and the latest scan
targets.
This keeps IPs blocked even after they leave the NPM ~30-day log window, and
only ever removes router entries that were never blocked by the system.
"""
from __future__ import annotations
import ipaddress
import os
import re
import subprocess
from datetime import datetime
from typing import Any, Iterable
from .files import write_json
from .reporting import timestamp_name
#: A ``+ 1.2.3.4/32`` added line in a git patch; ``+++ b/...`` is the file
#: header and is excluded by the negative lookahead.
_ADDED_LINE_RE = re.compile(r"^\+(?!\+)(.*)$")
def _run_git(*args: str) -> subprocess.CompletedProcess[str] | None:
"""Run a git command, returning None on any failure (never raises)."""
try:
return subprocess.run(
["git", *args], capture_output=True, text=True, check=False)
except (OSError, subprocess.SubprocessError):
return None
def _valid_line(line: str) -> str | None:
"""Normalize a blocklist line to a canonical CIDR string, or None."""
line = line.strip()
if not line:
return None
try:
return str(ipaddress.ip_network(line, strict=False))
except ValueError:
return None
def committed_lines(path: str) -> set[str]:
"""Return the union of all lines ever present in ``path`` across git.
Uses a single ``git log --all -p -- <path>`` and collects the ``+`` added
lines (excluding the ``+++`` file header). A line present in any revision
appears as an added line in some commit's diff, so the union equals "all
lines ever present".
Returns an empty set when git is unavailable, the path is untracked, or the
repository has no history — callers then fall back to the working file.
"""
proc = _run_git("log", "--all", "-p", "--", path)
if proc is None or proc.returncode != 0:
return set()
lines: set[str] = set()
for raw in proc.stdout.splitlines():
m = _ADDED_LINE_RE.match(raw)
if not m:
continue
clean = _valid_line(m.group(1))
if clean is not None:
lines.add(clean)
return lines
def current_file_lines(path: str) -> set[str]:
"""Return the validated lines currently in ``path`` (missing file -> {})."""
try:
with open(path, "r", encoding="utf-8") as f:
return {clean for clean in (_valid_line(x) for x in f)
if clean is not None}
except OSError:
return set()
def cumulative_blocklist(v4_path: str, v6_path: str,
desired_v4: Iterable[str],
desired_v6: Iterable[str],
) -> tuple[set[str], set[str]]:
"""Complete set of all blocked targets (history | working file | desired).
Returns ``(complete_v4, complete_v6)`` of canonical CIDR strings.
"""
complete_v4 = (
committed_lines(v4_path)
| current_file_lines(v4_path)
| {c for c in (_valid_line(x) for x in desired_v4) if c is not None})
complete_v6 = (
committed_lines(v6_path)
| current_file_lines(v6_path)
| {c for c in (_valid_line(x) for x in desired_v6) if c is not None})
return complete_v4, complete_v6
def compute_changes(current_v4: set[str], current_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
whitelisted_v4: set[str], whitelisted_v6: set[str],
) -> dict[str, Any]:
"""Compute the add/remove diff for a cumulative (grow-only) blocklist.
Entries are added when present in the complete set but not yet on the
router and not whitelisted. Entries are removed only when they sit on the
router but are absent from the complete set — i.e. they were never blocked
by the system (manual/rogue entries). Callers may attach extra keys (e.g.
``dry_run``).
"""
return {
"added_ipv4": sorted(complete_v4 - current_v4 - whitelisted_v4),
"added_ipv6": sorted(complete_v6 - current_v6 - whitelisted_v6),
"removed_ipv4": sorted(current_v4 - complete_v4),
"removed_ipv6": sorted(current_v6 - complete_v6),
}
def blocklist_delta(history_v4: set[str], history_v6: set[str],
prev_v4: set[str], prev_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
) -> dict[str, list[str]]:
"""Complete-set delta between the previous and current blocklist state.
``added`` are entries newly part of the blocklist (this run's targets not
blocked before); ``removed`` are entries no longer part of it — normally
empty in the cumulative model.
"""
before_v4 = history_v4 | prev_v4
before_v6 = history_v6 | prev_v6
return {
"added_ipv4": sorted(complete_v4 - before_v4),
"added_ipv6": sorted(complete_v6 - before_v6),
"removed_ipv4": sorted(before_v4 - complete_v4),
"removed_ipv6": sorted(before_v6 - complete_v6),
}
def write_blocklist_report(report_dir: str,
*,
history_v4: set[str], history_v6: set[str],
prev_v4: set[str], prev_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
firewall_changes: dict | None = None,
dry_run: bool = False,
errors: Iterable[str] = (),
) -> str:
"""Write the timestamped blocklist report to ``<report_dir>/app/``.
Records the complete-set delta (added/removed) plus the full cumulative
blocked list (git history | working files | scan targets), and — when
supplied — the router sync changes. Returns the written file path.
"""
delta = blocklist_delta(
history_v4, history_v6, prev_v4, prev_v6, complete_v4, complete_v6)
payload = {
"generated_at": datetime.now().astimezone().isoformat(
timespec="seconds"),
"report_dir": report_dir,
"dry_run": dry_run,
"summary": {
"added": len(delta["added_ipv4"]) + len(delta["added_ipv6"]),
"removed": len(delta["removed_ipv4"]) + len(delta["removed_ipv6"]),
"total_blocked": len(complete_v4) + len(complete_v6),
},
"added_ipv4": delta["added_ipv4"],
"added_ipv6": delta["added_ipv6"],
"removed_ipv4": delta["removed_ipv4"],
"removed_ipv6": delta["removed_ipv6"],
"blocked_ipv4": sorted(complete_v4),
"blocked_ipv6": sorted(complete_v6),
"firewall_changes": firewall_changes,
"errors": list(errors),
}
app_dir = os.path.join(report_dir, "app")
os.makedirs(app_dir, exist_ok=True)
path = os.path.join(app_dir, f"{timestamp_name()}.json")
write_json(path, payload)
return path
#!/usr/bin/env python3
"""Git-backed cumulative blocklist history.
The consolidated blocklist lives in git-tracked files
(``reports/app/data/blocklist_ipv4.txt`` / ``blocklist_ipv6.txt``). To make the
MikroTik blocklist grow-only, the "complete set of all blocked IPs" is
reconstructed from **every git revision** of those files (the union of all
lines ever present), plus the current working files and the latest scan
targets.
This keeps IPs blocked even after they leave the NPM ~30-day log window, and
only ever removes router entries that were never blocked by the system.
"""
from __future__ import annotations
import ipaddress
import os
import re
import subprocess
from datetime import datetime
from typing import Any, Iterable
from .files import write_json
from .reporting import timestamp_name
#: A ``+ 1.2.3.4/32`` added line in a git patch; ``+++ b/...`` is the file
#: header and is excluded by the negative lookahead.
_ADDED_LINE_RE = re.compile(r"^\+(?!\+)(.*)$")
def _run_git(*args: str) -> subprocess.CompletedProcess[str] | None:
"""Run a git command, returning None on any failure (never raises)."""
try:
return subprocess.run(
["git", *args], capture_output=True, text=True, check=False)
except (OSError, subprocess.SubprocessError):
return None
def _valid_line(line: str) -> str | None:
"""Normalize a blocklist line to a canonical CIDR string, or None."""
line = line.strip()
if not line:
return None
try:
return str(ipaddress.ip_network(line, strict=False))
except ValueError:
return None
def committed_lines(path: str) -> set[str]:
"""Return the union of all lines ever present in ``path`` across git.
Uses a single ``git log --all -p -- <path>`` and collects the ``+`` added
lines (excluding the ``+++`` file header). A line present in any revision
appears as an added line in some commit's diff, so the union equals "all
lines ever present".
Returns an empty set when git is unavailable, the path is untracked, or the
repository has no history — callers then fall back to the working file.
"""
proc = _run_git("log", "--all", "-p", "--", path)
if proc is None or proc.returncode != 0:
return set()
lines: set[str] = set()
for raw in proc.stdout.splitlines():
m = _ADDED_LINE_RE.match(raw)
if not m:
continue
clean = _valid_line(m.group(1))
if clean is not None:
lines.add(clean)
return lines
def current_file_lines(path: str) -> set[str]:
"""Return the validated lines currently in ``path`` (missing file -> {})."""
try:
with open(path, "r", encoding="utf-8") as f:
return {clean for clean in (_valid_line(x) for x in f)
if clean is not None}
except OSError:
return set()
def cumulative_blocklist(v4_path: str, v6_path: str,
desired_v4: Iterable[str],
desired_v6: Iterable[str],
) -> tuple[set[str], set[str]]:
"""Complete set of all blocked targets (history | working file | desired).
Returns ``(complete_v4, complete_v6)`` of canonical CIDR strings.
"""
complete_v4 = (
committed_lines(v4_path)
| current_file_lines(v4_path)
| {c for c in (_valid_line(x) for x in desired_v4) if c is not None})
complete_v6 = (
committed_lines(v6_path)
| current_file_lines(v6_path)
| {c for c in (_valid_line(x) for x in desired_v6) if c is not None})
return complete_v4, complete_v6
def compute_changes(current_v4: set[str], current_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
whitelisted_v4: set[str], whitelisted_v6: set[str],
) -> dict[str, Any]:
"""Compute the add/remove diff for a cumulative (grow-only) blocklist.
Entries are added when present in the complete set but not yet on the
router and not whitelisted. Entries are removed only when they sit on the
router but are absent from the complete set — i.e. they were never blocked
by the system (manual/rogue entries). Callers may attach extra keys (e.g.
``dry_run``).
"""
return {
"added_ipv4": sorted(complete_v4 - current_v4 - whitelisted_v4),
"added_ipv6": sorted(complete_v6 - current_v6 - whitelisted_v6),
"removed_ipv4": sorted(current_v4 - complete_v4),
"removed_ipv6": sorted(current_v6 - complete_v6),
}
def blocklist_delta(history_v4: set[str], history_v6: set[str],
prev_v4: set[str], prev_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
) -> dict[str, list[str]]:
"""Complete-set delta between the previous and current blocklist state.
``added`` are entries newly part of the blocklist (this run's targets not
blocked before); ``removed`` are entries no longer part of it — normally
empty in the cumulative model.
"""
before_v4 = history_v4 | prev_v4
before_v6 = history_v6 | prev_v6
return {
"added_ipv4": sorted(complete_v4 - before_v4),
"added_ipv6": sorted(complete_v6 - before_v6),
"removed_ipv4": sorted(before_v4 - complete_v4),
"removed_ipv6": sorted(before_v6 - complete_v6),
}
def write_blocklist_report(report_dir: str,
*,
history_v4: set[str], history_v6: set[str],
prev_v4: set[str], prev_v6: set[str],
complete_v4: set[str], complete_v6: set[str],
firewall_changes: dict | None = None,
dry_run: bool = False,
errors: Iterable[str] = (),
) -> str:
"""Write the timestamped blocklist report to ``<report_dir>/app/``.
Records the complete-set delta (added/removed) plus the full cumulative
blocked list (git history | working files | scan targets), and — when
supplied — the router sync changes. Returns the written file path.
"""
delta = blocklist_delta(
history_v4, history_v6, prev_v4, prev_v6, complete_v4, complete_v6)
payload = {
"generated_at": datetime.now().astimezone().isoformat(
timespec="seconds"),
"report_dir": report_dir,
"dry_run": dry_run,
"summary": {
"added": len(delta["added_ipv4"]) + len(delta["added_ipv6"]),
"removed": len(delta["removed_ipv4"]) + len(delta["removed_ipv6"]),
"total_blocked": len(complete_v4) + len(complete_v6),
},
"added_ipv4": delta["added_ipv4"],
"added_ipv6": delta["added_ipv6"],
"removed_ipv4": delta["removed_ipv4"],
"removed_ipv6": delta["removed_ipv6"],
"blocked_ipv4": sorted(complete_v4),
"blocked_ipv6": sorted(complete_v6),
"firewall_changes": firewall_changes,
"errors": list(errors),
}
app_dir = os.path.join(report_dir, "app")
os.makedirs(app_dir, exist_ok=True)
path = os.path.join(app_dir, f"{timestamp_name()}.json")
write_json(path, payload)
return path
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff. Show more