Restructure sources into app package with unified entry point and update documentation
This commit is contained in:
1 parent
540154d426
commit
f78faf8f8a
18 files changed
+166
-128
No files matched your search
@@ -2,53 +2,59 @@
|
|||||||
|
|
||||||
Local-development intrusion detection / log analysis for two log sources:
|
Local-development intrusion detection / log analysis for two log sources:
|
||||||
|
|
||||||
| Script | Source | Detection rule |
|
| Script | Source | Detection rule |
|
||||||
| ----------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
| --------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||||
| `scan.py` | both sources | consolidated scan + unified MikroTik export |
|
| `app.py` | unified entry point | runs both analyzers + optional firewall sync |
|
||||||
| `copyparty.py` | [copyparty](https://github.com/9001/copyparty) server logs | denied-only IPs + copyparty auto-bans |
|
| `app/scan.py` | consolidated scanner | runs both analyzers, merges blocklists, syncs firewall |
|
||||||
| `npm.py` | [Nginx Proxy Manager](https://nginxproxymanager.com) proxy logs | high error-rate IPs (scanners) |
|
| `app/copyparty.py` | [copyparty](https://github.com/9001/copyparty) server logs | denied-only IPs + copyparty auto-bans |
|
||||||
| `utils.py` | re-export layer | thin barrel — imports from sub-modules below |
|
| `app/npm.py` | [Nginx Proxy Manager](https://nginxproxymanager.com) proxy logs | high error-rate IPs (scanners) |
|
||||||
| `models.py` | data model | `Request`, `IPStats`, `aggregate()` |
|
| `app/utils.py` | re-export layer | thin barrel — imports from sub-modules below |
|
||||||
| `ip_utils.py` | IP helpers | `parse_ip`, `whitelist_of`, `is_whitelisted`, `sort_ips`, `split_versions` |
|
| `app/models.py` | data model | `Request`, `IPStats`, `aggregate()` |
|
||||||
| `flags.py` | detection rules | `flag_scanners`, `flag_denied_only`, `flag_malicious_patterns`, `by_total` |
|
| `app/ip_utils.py` | IP helpers | `parse_ip`, `whitelist_of`, `is_whitelisted`, `sort_ips`, `split_versions` |
|
||||||
| `analyzer.py` | pipeline | `Analyzer` — discover → load → analyze → report → write |
|
| `app/flags.py` | detection rules | `flag_scanners`, `flag_denied_only`, `flag_malicious_patterns`, `by_total` |
|
||||||
| `whitelists.py` | whitelist module | provider CIDR constants, local/remote load, CIDR extraction |
|
| `app/analyzer.py` | pipeline | `Analyzer` — discover → load → analyze → report → write |
|
||||||
| `bad_patterns.py` | pattern detection | malicious URL/file regex classification |
|
| `app/whitelists.py` | whitelist module | provider CIDR constants, local/remote load, CIDR extraction |
|
||||||
| `whois.py` | WHOIS query | `query_whois_subnet`, `consolidate_by_subnet` |
|
| `app/bad_patterns.py` | pattern detection | malicious URL/file regex classification |
|
||||||
| `mikrotik.py` | RouterOS export | `mikrotik_script`, `write_mikrotik`, `split_cidr_versions` |
|
| `app/whois.py` | WHOIS query | `query_whois_subnet`, `consolidate_by_subnet` |
|
||||||
| `files.py` | I/O helpers | `read_lines`, `find_logs`, `write_csv`, `write_json`, etc. |
|
| `app/mikrotik.py` | RouterOS export | `mikrotik_script`, `write_mikrotik`, `split_cidr_versions` |
|
||||||
| `reporting.py` | text rendering | `Column`, `render_table`, `render_kv`, `timestamp_name` |
|
| `app/firewall.py` | RouterOS SSH client | `MikrotikFirewall` — connect, sync blocklist, audit state |
|
||||||
|
| `app/files.py` | I/O helpers | `read_lines`, `find_logs`, `write_csv`, `write_json`, etc. |
|
||||||
|
| `app/reporting.py` | text rendering | `Column`, `render_table`, `render_kv`, `timestamp_name` |
|
||||||
|
|
||||||
Both per-source scripts parse logs, aggregate per-IP behaviour, split
|
Both per-source scripts parse logs, aggregate per-IP behaviour, split
|
||||||
IPv4/IPv6, skip whitelisted provider ranges, detect malicious path patterns,
|
IPv4/IPv6, skip whitelisted provider ranges, detect malicious path patterns,
|
||||||
group flagged IPs into WHOIS subnets, and emit a ready-to-import MikroTik
|
group flagged IPs into WHOIS subnets, and emit a ready-to-import MikroTik
|
||||||
RouterOS firewall script.
|
RouterOS firewall script.
|
||||||
|
|
||||||
`scan.py` runs both analyzers, merges their blocklists, and writes a single
|
`app.py` runs both analyzers, merges their blocklists, and optionally
|
||||||
consolidated `.rsc`.
|
synchronizes the MikroTik RouterOS firewall via SSH.
|
||||||
|
|
||||||
> Status: **local dev**. Runs offline against log files on disk. It does not
|
> Status: **local dev**. Runs offline against log files on disk. Use
|
||||||
> talk to the router, does not run as a service, and blocks nothing by itself.
|
> `--update-firewall` to push changes to the router, or `--dry-run` to
|
||||||
> You review the generated `.rsc` and import it manually.
|
> preview without applying.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```text
|
```text
|
||||||
intrusion-detection/
|
intrusion-detection/
|
||||||
├── scan.py consolidated scanner entry point
|
├── app.py unified entry point
|
||||||
├── copyparty.py copyparty log adapter (~150 lines)
|
├── app/ application package
|
||||||
├── npm.py NPM proxy log adapter (~150 lines)
|
│ ├── __init__.py
|
||||||
├── utils.py thin re-export barrel (~90 lines)
|
│ ├── scan.py consolidated scanner
|
||||||
├── models.py Request, IPStats, aggregate()
|
│ ├── copyparty.py copyparty log adapter (~150 lines)
|
||||||
├── ip_utils.py IP parsing, whitelist lookups, sorting
|
│ ├── npm.py NPM proxy log adapter (~150 lines)
|
||||||
├── flags.py flag_scanners, flag_denied_only, flag_malicious_patterns
|
│ ├── firewall.py MikroTik RouterOS SSH client
|
||||||
├── analyzer.py Analyzer pipeline base class
|
│ ├── utils.py thin re-export barrel (~90 lines)
|
||||||
├── whitelists.py provider CIDR constants, local/remote load
|
│ ├── models.py Request, IPStats, aggregate()
|
||||||
├── bad_patterns.py malicious URL/file regex patterns
|
│ ├── ip_utils.py IP parsing, whitelist lookups, sorting
|
||||||
├── whois.py query_whois_subnet, consolidate_by_subnet
|
│ ├── flags.py flag_scanners, flag_denied_only, flag_malicious_patterns
|
||||||
├── mikrotik.py RouterOS .rsc script generation
|
│ ├── analyzer.py Analyzer pipeline base class
|
||||||
├── files.py read_lines, find_logs, write_csv/json/lines
|
│ ├── whitelists.py provider CIDR constants, local/remote load
|
||||||
├── reporting.py Column, render_table, render_kv, timestamp_name
|
│ ├── bad_patterns.py malicious URL/file regex patterns
|
||||||
|
│ ├── whois.py query_whois_subnet, consolidate_by_subnet
|
||||||
|
│ ├── mikrotik.py RouterOS .rsc script generation
|
||||||
|
│ ├── files.py read_lines, find_logs, write_csv/json/lines
|
||||||
|
│ └── reporting.py Column, render_table, render_kv, timestamp_name
|
||||||
├── data/ whitelist source files (cached locally)
|
├── data/ whitelist source files (cached locally)
|
||||||
│ ├── openfactory/
|
│ ├── openfactory/
|
||||||
│ │ └── geofeed.csv
|
│ │ └── geofeed.csv
|
||||||
@@ -60,29 +66,28 @@ intrusion-detection/
|
|||||||
├── reports/ generated reports (per-run + per-source)
|
├── reports/ generated reports (per-run + per-source)
|
||||||
│ ├── copyparty/
|
│ ├── copyparty/
|
||||||
│ ├── npm/
|
│ ├── npm/
|
||||||
│ └── mikrotik-block.rsc consolidated .rsc (scan.py only)
|
│ └── mikrotik/ firewall audit snapshots
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
`copyparty.py` and `npm.py` are thin adapters. Each supplies a log matcher,
|
`app/copyparty.py` and `app/npm.py` are thin adapters. Each supplies a log
|
||||||
a line parser, a flagging rule, and column definitions. `utils.py` is a barrel
|
matcher, a line parser, a flagging rule, and column definitions.
|
||||||
module that re-exports everything from the sub-modules so callers only need
|
|
||||||
`import utils`.
|
|
||||||
|
|
||||||
Core responsibilities by module:
|
Core responsibilities by module:
|
||||||
|
|
||||||
| Module | Owns |
|
| Module | Owns |
|
||||||
| ----------------- | -------------------------------------------------------------------------------- |
|
| --------------------- | -------------------------------------------------------------------------------- |
|
||||||
| `models.py` | `Request`, `IPStats`, `aggregate()` |
|
| `app/models.py` | `Request`, `IPStats`, `aggregate()` |
|
||||||
| `ip_utils.py` | `parse_ip`, `whitelist_of`, `is_whitelisted`, `sort_ips`, `split_versions` |
|
| `app/ip_utils.py` | `parse_ip`, `whitelist_of`, `is_whitelisted`, `sort_ips`, `split_versions` |
|
||||||
| `flags.py` | `flag_scanners`, `flag_denied_only`, `flag_malicious_patterns`, `by_total` |
|
| `app/flags.py` | `flag_scanners`, `flag_denied_only`, `flag_malicious_patterns`, `by_total` |
|
||||||
| `analyzer.py` | `Analyzer` — discover → load → analyze → report → write |
|
| `app/analyzer.py` | `Analyzer` — discover → load → analyze → report → write |
|
||||||
| `whitelists.py` | provider CIDR constants, local-file / remote / built-in loading |
|
| `app/whitelists.py` | provider CIDR constants, local-file / remote / built-in loading |
|
||||||
| `bad_patterns.py` | malicious URL/file regex classification |
|
| `app/bad_patterns.py` | malicious URL/file regex classification |
|
||||||
| `whois.py` | `query_whois_subnet`, `consolidate_by_subnet` |
|
| `app/whois.py` | `query_whois_subnet`, `consolidate_by_subnet` |
|
||||||
| `mikrotik.py` | `mikrotik_script`, `write_mikrotik`, `split_cidr_versions` |
|
| `app/mikrotik.py` | `mikrotik_script`, `write_mikrotik`, `split_cidr_versions` |
|
||||||
| `files.py` | `read_lines`, `find_logs`, `validate_dir`, `ensure_dirs`, `write_csv/json/lines` |
|
| `app/firewall.py` | `MikrotikFirewall` — SSH connect, sync blocklist, audit state |
|
||||||
| `reporting.py` | `Column`, `render_table`, `render_kv`, `timestamp_name` |
|
| `app/files.py` | `read_lines`, `find_logs`, `validate_dir`, `ensure_dirs`, `write_csv/json/lines` |
|
||||||
|
| `app/reporting.py` | `Column`, `render_table`, `render_kv`, `timestamp_name` |
|
||||||
|
|
||||||
Console output and saved reports are the **same string** (`Analyzer.text_report()`).
|
Console output and saved reports are the **same string** (`Analyzer.text_report()`).
|
||||||
|
|
||||||
@@ -94,50 +99,57 @@ Console output and saved reports are the **same string** (`Analyzer.text_report(
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# individual scanners
|
# unified entry point (both sources, optional firewall sync)
|
||||||
python copyparty.py
|
python app.py
|
||||||
python npm.py
|
python app.py --quiet
|
||||||
|
python app.py --update-firewall --dry-run
|
||||||
|
python app.py --update-firewall
|
||||||
|
|
||||||
# consolidated (both sources, unified blocklist)
|
# individual scanners (still runnable directly)
|
||||||
python scan.py
|
python -m app.copyparty
|
||||||
|
python -m app.npm
|
||||||
```
|
```
|
||||||
|
|
||||||
All scripts accept CLI overrides:
|
All scripts accept CLI overrides:
|
||||||
|
|
||||||
| Flag | Default | Meaning |
|
| Flag | Default | Meaning |
|
||||||
| ----------------- | -------------------- | ----------------------------- |
|
| ------------------- | -------------------- | ---------------------------------- |
|
||||||
| `--log-path` | see below | log directory |
|
| `--log-path` | see below | log directory |
|
||||||
| `--report-dir` | `reports/<name>` | output directory |
|
| `--report-dir` | `reports/<name>` | output directory |
|
||||||
| `--top N` | `30` | rows in the top-IP table |
|
| `--top N` | `30` | rows in the top-IP table |
|
||||||
| `--quiet` | off | write files, print only paths |
|
| `--quiet` | off | write files, print only paths |
|
||||||
| `--no-rsc` | off | skip MikroTik export |
|
| `--min-errors N` | `5` (`npm.py`) | error count threshold |
|
||||||
| `--min-errors N` | `5` (`npm.py`) | error count threshold |
|
| `--error-ratio F` | `0.5` (`npm.py`) | error ratio threshold |
|
||||||
| `--error-ratio F` | `0.5` (`npm.py`) | error ratio threshold |
|
| `--min-denied N` | `1` (`copyparty.py`) | denied-hit threshold |
|
||||||
| `--min-denied N` | `1` (`copyparty.py`) | denied-hit threshold |
|
| `--update-firewall` | off | sync blocklist to MikroTik via SSH |
|
||||||
|
| `--dry-run` | off | preview firewall changes, no apply |
|
||||||
|
|
||||||
`scan.py` accepts all flags from both scanners plus `--copyparty-log-path`,
|
`app.py` accepts all flags from both scanners plus `--copyparty-log-path`,
|
||||||
`--copyparty-report-dir`, `--npm-log-path`, `--npm-report-dir`, and
|
`--copyparty-report-dir`, `--npm-log-path`, `--npm-report-dir`, and
|
||||||
`--report-dir` for the consolidated output.
|
`--report-dir` for the consolidated output.
|
||||||
|
|
||||||
Default log paths (overridable by `.env`):
|
Default log paths (overridable by `.env`):
|
||||||
|
|
||||||
| Script | Env var | Default |
|
| Script | Env var | Default |
|
||||||
| -------------- | -------------------- | -------------- |
|
| ------------------ | -------------------- | --------------- |
|
||||||
| `copyparty.py` | `COPYPARTY_LOG_PATH` | `P:\copyparty` |
|
| `app/copyparty.py` | `COPYPARTY_LOG_PATH` | `P:\copyparty` |
|
||||||
| `npm.py` | `NPM_LOG_PATH` | `Y:\npm\logs` |
|
| `app/npm.py` | `NPM_LOG_PATH` | `Y:\npm\logs` |
|
||||||
|
| `app/firewall.py` | `ROUTER_IP` | `192.168.88.1` |
|
||||||
|
| | `ROUTER_USER` | `admin` |
|
||||||
|
| | `ROUTER_PASSWORD` | _(set in .env)_ |
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
python npm.py --log-path D:\logs\npm --min-errors 10 --error-ratio 0.8
|
python -m app.npm --log-path D:\logs\npm --min-errors 10 --error-ratio 0.8
|
||||||
python copyparty.py --top 100 --no-rsc
|
python -m app.copyparty --top 100
|
||||||
python scan.py --quiet --no-rsc
|
python app.py --quiet --update-firewall --dry-run
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
Each script writes to its own report directory. `scan.py` also writes a
|
Each script writes to its own report directory. `app.py` also writes
|
||||||
consolidated `.rsc`:
|
firewall audit snapshots:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
reports/
|
reports/
|
||||||
@@ -154,8 +166,7 @@ reports/
|
|||||||
│ │ ├── blocked_ipv4.txt final block set (non-whitelisted)
|
│ │ ├── blocked_ipv4.txt final block set (non-whitelisted)
|
||||||
│ │ ├── blocked_ipv6.txt
|
│ │ ├── blocked_ipv6.txt
|
||||||
│ │ ├── authed_users.json authenticated user counts
|
│ │ ├── authed_users.json authenticated user counts
|
||||||
│ │ ├── requests.csv every parsed request
|
│ │ └── requests.csv every parsed request
|
||||||
│ │ └── mikrotik-block.rsc
|
|
||||||
│ └── 2026-08-02-12-00-00.txt timestamped report
|
│ └── 2026-08-02-12-00-00.txt timestamped report
|
||||||
├── npm/
|
├── npm/
|
||||||
│ ├── data/
|
│ ├── data/
|
||||||
@@ -169,10 +180,15 @@ reports/
|
|||||||
│ │ ├── blocked_ipv6.txt
|
│ │ ├── blocked_ipv6.txt
|
||||||
│ │ ├── ua_summary.csv user agent breakdown
|
│ │ ├── ua_summary.csv user agent breakdown
|
||||||
│ │ ├── host_summary.csv virtual host breakdown
|
│ │ ├── host_summary.csv virtual host breakdown
|
||||||
│ │ ├── requests.csv
|
│ │ └── requests.csv
|
||||||
│ │ └── mikrotik-block.rsc
|
|
||||||
│ └── 2026-08-02-12-00-00.txt
|
│ └── 2026-08-02-12-00-00.txt
|
||||||
└── mikrotik-block.rsc consolidated (scan.py only)
|
└── mikrotik/
|
||||||
|
├── data/
|
||||||
|
│ ├── address_list_ipv4.json
|
||||||
|
│ ├── address_list_ipv6.json
|
||||||
|
│ ├── firewall_ipv4.json
|
||||||
|
│ └── firewall_ipv6.json
|
||||||
|
└── 2026-08-04-18-30-28.json firewall audit snapshot
|
||||||
```
|
```
|
||||||
|
|
||||||
## Detection
|
## Detection
|
||||||
@@ -259,13 +275,13 @@ Fields: `[datetime]`, upstream status, proxy status, method, scheme, host,
|
|||||||
## Extending
|
## Extending
|
||||||
|
|
||||||
- **new whitelist provider** → add URLs, local file paths, and fallback CIDRs
|
- **new whitelist provider** → add URLs, local file paths, and fallback CIDRs
|
||||||
to `whitelists.py`
|
to `app/whitelists.py`
|
||||||
- **new detection pattern** → add a `BadPattern` to `bad_patterns.py`
|
- **new detection pattern** → add a `BadPattern` to `app/bad_patterns.py`
|
||||||
- **new detection rule** → add a `flag_*()` function to `flags.py`, return it
|
- **new detection rule** → add a `flag_*()` function to `app/flags.py`, return it
|
||||||
from the analyzer's `flag()` method
|
from the analyzer's `flag()` method
|
||||||
- **new log source** → subclass `analyzer.Analyzer`, implement `parse_line()` +
|
- **new log source** → subclass `app.analyzer.Analyzer`, implement `parse_line()` +
|
||||||
`flag()`, declare `ip_columns` / `request_columns`
|
`flag()`, declare `ip_columns` / `request_columns`
|
||||||
- **new output file** → override `write_extra(data_dir)` and return the paths
|
- **new output file** → override `write_extra(data_dir)` and return the paths
|
||||||
written
|
written
|
||||||
- **new I/O format** → add writer to `files.py`
|
- **new I/O format** → add writer to `app/files.py`
|
||||||
- **new report section** → add rendering logic to `reporting.py`
|
- **new report section** → add rendering logic to `app/reporting.py`
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Intrusion Detection System — unified entry point.
|
||||||
|
|
||||||
|
Runs both copyparty and NPM log analyzers, consolidates blocklist
|
||||||
|
candidates, and optionally synchronizes the MikroTik RouterOS firewall.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python app.py --quiet
|
||||||
|
python app.py --update-firewall --dry-run
|
||||||
|
python app.py --update-firewall
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from app.scan import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Intrusion Detection System — app package
|
||||||
@@ -13,13 +13,13 @@ from collections import Counter
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
|
|
||||||
from files import ensure_dirs, find_logs, read_lines, validate_dir, write_csv, write_json, write_lines
|
from .files import ensure_dirs, find_logs, read_lines, validate_dir, write_csv, write_json, write_lines
|
||||||
from flags import by_total, flag_malicious_patterns
|
from .flags import by_total, flag_malicious_patterns
|
||||||
from ip_utils import is_whitelisted, split_versions
|
from .ip_utils import is_whitelisted, split_versions
|
||||||
from mikrotik import write_mikrotik
|
from .mikrotik import write_mikrotik
|
||||||
from models import IPStats, Request, aggregate
|
from .models import IPStats, Request, aggregate
|
||||||
from reporting import Column, columns_header, columns_row, render_kv, render_table, timestamp_name
|
from .reporting import Column, columns_header, columns_row, render_kv, render_table, timestamp_name
|
||||||
from whitelists import refresh_whitelists
|
from .whitelists import refresh_whitelists
|
||||||
|
|
||||||
|
|
||||||
class Analyzer:
|
class Analyzer:
|
||||||
File renamed without changes.
@@ -12,17 +12,17 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from analyzer import Analyzer
|
from .analyzer import Analyzer
|
||||||
from ip_utils import split_versions
|
from .ip_utils import split_versions
|
||||||
from files import write_json, write_lines
|
from .files import write_json, write_lines
|
||||||
from flags import flag_denied_only
|
from .flags import flag_denied_only
|
||||||
from models import IPStats, Request
|
from .models import IPStats, Request
|
||||||
from utils import arg_parser
|
from .utils import arg_parser
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_LOG_PATH = os.environ.get("COPYPARTY_LOG_PATH", r"P:\copyparty")
|
DEFAULT_LOG_PATH = os.environ.get("COPYPARTY_LOG_PATH", r"P:\copyparty")
|
||||||
DEFAULT_REPORT_DIR = os.path.join(
|
DEFAULT_REPORT_DIR = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)), "reports", "copyparty")
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "reports", "copyparty")
|
||||||
|
|
||||||
# "HH:MM:SS.mmm <ip> <port> LEVEL: message"
|
# "HH:MM:SS.mmm <ip> <port> LEVEL: message"
|
||||||
# System lines ("hsrv", "root", ...) have no port and are skipped.
|
# System lines ("hsrv", "root", ...) have no port and are skipped.
|
||||||
File renamed without changes.
@@ -13,10 +13,12 @@ import paramiko
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import shlex
|
import shlex
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
from ip_utils import is_whitelisted
|
from .ip_utils import is_whitelisted
|
||||||
|
|
||||||
DATA_DIR = os.path.join(os.path.dirname(__file__), "data", "mikrotik")
|
DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(
|
||||||
REPORT_DIR = os.path.join(os.path.dirname(__file__), "reports")
|
os.path.abspath(__file__))), "data", "mikrotik")
|
||||||
|
REPORT_DIR = os.path.join(os.path.dirname(
|
||||||
|
os.path.dirname(os.path.abspath(__file__))), "reports")
|
||||||
MIKROTIK_DATA_DIR = os.path.join(REPORT_DIR, "mikrotik", "data")
|
MIKROTIK_DATA_DIR = os.path.join(REPORT_DIR, "mikrotik", "data")
|
||||||
|
|
||||||
SSH_TIMEOUT = 10 # seconds
|
SSH_TIMEOUT = 10 # seconds
|
||||||
@@ -6,8 +6,8 @@ Detection functions that identify hostile IPs based on aggregated stats.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import bad_patterns
|
from . import bad_patterns
|
||||||
from models import IPStats
|
from .models import IPStats
|
||||||
|
|
||||||
|
|
||||||
def flag_scanners(stats: dict[str, IPStats], min_errors: int = 5,
|
def flag_scanners(stats: dict[str, IPStats], min_errors: int = 5,
|
||||||
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from whitelists import WHITELIST_NETS as _WHITELIST_NETS
|
from .whitelists import WHITELIST_NETS as _WHITELIST_NETS
|
||||||
|
|
||||||
|
|
||||||
def parse_ip(value: str):
|
def parse_ip(value: str):
|
||||||
@@ -7,8 +7,8 @@ import ipaddress
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from ip_utils import is_ipv4, is_ipv6, is_whitelisted, parse_ip
|
from .ip_utils import is_ipv4, is_ipv6, is_whitelisted, parse_ip
|
||||||
from whitelists import WHITELISTS
|
from .whitelists import WHITELISTS
|
||||||
|
|
||||||
|
|
||||||
def split_cidr_versions(targets: Iterable[str]) -> tuple[list[str], list[str]]:
|
def split_cidr_versions(targets: Iterable[str]) -> tuple[list[str], list[str]]:
|
||||||
@@ -10,8 +10,8 @@ from collections import Counter
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
import bad_patterns
|
from . import bad_patterns
|
||||||
from ip_utils import ip_version, whitelist_of
|
from .ip_utils import ip_version, whitelist_of
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
+6
-6
@@ -12,16 +12,16 @@ import os
|
|||||||
import re
|
import re
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
from analyzer import Analyzer
|
from .analyzer import Analyzer
|
||||||
from files import write_csv
|
from .files import write_csv
|
||||||
from flags import flag_scanners
|
from .flags import flag_scanners
|
||||||
from models import Request
|
from .models import Request
|
||||||
from utils import arg_parser
|
from .utils import arg_parser
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_LOG_PATH = os.environ.get("NPM_LOG_PATH", r"Y:\npm\logs")
|
DEFAULT_LOG_PATH = os.environ.get("NPM_LOG_PATH", r"Y:\npm\logs")
|
||||||
DEFAULT_REPORT_DIR = os.path.join(
|
DEFAULT_REPORT_DIR = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)), "reports", "npm")
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "reports", "npm")
|
||||||
|
|
||||||
# [02/Aug/2026:05:01:31 +0200] - 401 401 - GET https host "/path"
|
# [02/Aug/2026:05:01:31 +0200] - 401 401 - GET https host "/path"
|
||||||
# [Client IP] [Length N] [Gzip X] [Sent-to IP] "UA" "Referer"
|
# [Client IP] [Length N] [Gzip X] [Sent-to IP] "UA" "Referer"
|
||||||
File renamed without changes.
@@ -11,15 +11,15 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import utils
|
from . import utils
|
||||||
from firewall import MikrotikFirewall
|
from .firewall import MikrotikFirewall
|
||||||
from copyparty import CopypartyAnalyzer, DEFAULT_LOG_PATH as CP_DEFAULT_LOG, DEFAULT_REPORT_DIR as CP_DEFAULT_REPORT
|
from .copyparty import CopypartyAnalyzer, DEFAULT_LOG_PATH as CP_DEFAULT_LOG, DEFAULT_REPORT_DIR as CP_DEFAULT_REPORT
|
||||||
from npm import NpmAnalyzer, DEFAULT_LOG_PATH as NPM_DEFAULT_LOG, DEFAULT_REPORT_DIR as NPM_DEFAULT_REPORT
|
from .npm import NpmAnalyzer, DEFAULT_LOG_PATH as NPM_DEFAULT_LOG, DEFAULT_REPORT_DIR as NPM_DEFAULT_REPORT
|
||||||
from ip_utils import is_whitelisted, split_versions
|
from .ip_utils import is_whitelisted, split_versions
|
||||||
from whois import consolidate_by_subnet
|
from .whois import consolidate_by_subnet
|
||||||
|
|
||||||
DEFAULT_CONSOLIDATED_REPORT_DIR = os.path.join(
|
DEFAULT_CONSOLIDATED_REPORT_DIR = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)), "reports")
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "reports")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
File renamed without changes.
@@ -22,7 +22,7 @@ from typing import Any
|
|||||||
# Paths
|
# Paths
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
_HERE = os.path.dirname(os.path.abspath(__file__))
|
_HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
_DATA_DIR = os.path.join(_HERE, "data")
|
_DATA_DIR = os.path.join(_HERE, "data")
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -9,11 +9,12 @@ import os
|
|||||||
import re
|
import re
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from ip_utils import ip_version, parse_ip
|
from .ip_utils import ip_version, parse_ip
|
||||||
|
|
||||||
# WHOIS Cache file path
|
# WHOIS Cache file path
|
||||||
_WHOIS_CACHE_PATH = os.path.join(
|
_WHOIS_CACHE_PATH = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)), "data", "whois_cache.json"
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))
|
||||||
|
), "data", "whois_cache.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
_whois_cache: dict[str, str] = {}
|
_whois_cache: dict[str, str] = {}
|
||||||
Reference in new issue
Block a user