-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathidrs_monitor.py
More file actions
152 lines (133 loc) · 5.21 KB
/
Copy pathidrs_monitor.py
File metadata and controls
152 lines (133 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
idrs_monitor.py — Mini IDRS entry point.
This file is intentionally thin (~50 lines of wiring).
All logic lives in core/ modules and plugins/.
Usage:
sudo python idrs_monitor.py -i ens33
Options:
-i / --iface Network interface to sniff (required)
--config Path to config.yaml (default: config.yaml)
"""
from __future__ import annotations
import argparse
import logging
import os
# Allow --config flag to set the path before config.py singleton loads
_parser = argparse.ArgumentParser(
description="Mini IDRS — Intrusion Detection & Response System",
add_help=False,
)
_parser.add_argument("--config", default="config.yaml")
_known, _remaining = _parser.parse_known_args()
os.environ.setdefault("IDRS_CONFIG", _known.config)
# Now safe to import the config singleton
from core.config import cfg
from core.firewall import FirewallManager, NftablesAPIBackend
from core.logger import setup_logging
from core.packet_capture import PacketCapture
from core.persistence import BlockStore
from core.pipeline import EventPipeline
from core.scheduler import IDRSScheduler
from core.victim import VictimBlocker
from core.whitelist import WhitelistManager
from plugins.base import DetectionContext
from plugins.ssh_brute_force import SshBruteForceDetector
from plugins.syn_flood import SynFloodDetector
from plugins.xmas_scan import XmasScanDetector
def main() -> None:
# --- CLI ---
parser = argparse.ArgumentParser(
description="Mini IDRS — Intrusion Detection & Response System"
)
parser.add_argument(
"-i", "--iface", required=True,
help="Network interface to sniff (e.g. ens33)"
)
parser.add_argument(
"--config", default="config.yaml",
help="Path to config.yaml (default: config.yaml)"
)
args = parser.parse_args()
# --- Logging ---
setup_logging(cfg.paths.logs, cfg.logging.level)
log = logging.getLogger("idrs")
log.info("=" * 60)
log.info("Mini IDRS starting")
log.info(f" Monitor IP : {cfg.network.monitor_ip}")
log.info(f" Victim IP : {cfg.network.victim_ip}")
log.info(f" Firewall IP: {cfg.network.firewall_ip}")
log.info(f" Interface : {args.iface}")
log.info("=" * 60)
# --- Core components ---
whitelist_mgr = WhitelistManager(cfg.paths.whitelist)
block_store = BlockStore(cfg.paths.blocked)
firewall_mgr = FirewallManager(
NftablesAPIBackend(cfg.firewall_api.url, cfg.firewall_api.api_key)
)
victim_blocker = VictimBlocker(
cfg.network.victim_ip,
cfg.victim.ssh_port,
cfg.victim.ssh_user,
cfg.victim.ssh_pass,
)
# --- Detection plugins ---
plugins = [
XmasScanDetector(),
SynFloodDetector(),
SshBruteForceDetector(),
]
# --- Shared detection context (thresholds are a live dict updated by Scheduler) ---
thresholds: dict = {
"syn_flood": {
"threshold": cfg.detection.syn_flood.threshold,
"window_seconds": cfg.detection.syn_flood.window_seconds,
},
"ssh_brute_force": {
"threshold": cfg.detection.ssh_brute_force.threshold,
"window_seconds": cfg.detection.ssh_brute_force.window_seconds,
},
}
# Load existing thresholds from thresholds.json if present
import json
from pathlib import Path
t_path = Path(cfg.paths.thresholds)
if t_path.exists():
try:
with open(t_path, "r") as fh:
data = json.load(fh)
if "syn_flood" in data:
thresholds["syn_flood"].update(data["syn_flood"])
if "ssh_brute_force" in data:
thresholds["ssh_brute_force"].update(data["ssh_brute_force"])
log.info(f"Loaded existing thresholds from {t_path}")
except Exception as exc:
log.warning(f"Failed to load thresholds from {t_path} at start: {exc}")
context = DetectionContext(
victim_ip = cfg.network.victim_ip,
monitor_ip = cfg.network.monitor_ip,
thresholds = thresholds,
whitelist = set(whitelist_mgr.all()),
)
# --- Event pipeline ---
pipeline = EventPipeline(whitelist_mgr, block_store, firewall_mgr, victim_blocker)
# --- Scheduler (background thread) ---
scheduler = IDRSScheduler(
firewall_api_url = cfg.firewall_api.url,
firewall_api_key = cfg.firewall_api.api_key,
whitelist_mgr = whitelist_mgr,
block_store = block_store,
detection_context = context,
thresholds_file = cfg.paths.thresholds,
stats_file = cfg.paths.stats,
health_check_interval = cfg.scheduler.health_check_interval_seconds,
whitelist_reload_interval = cfg.scheduler.whitelist_reload_seconds,
thresholds_reload_interval = cfg.scheduler.thresholds_reload_seconds,
stats_interval = cfg.scheduler.stats_interval_seconds,
block_cleanup_hours = cfg.scheduler.block_cleanup_hours,
)
scheduler.start()
# --- Packet capture (blocks until Ctrl-C) ---
capture = PacketCapture(plugins, context, pipeline)
capture.start(args.iface)
if __name__ == "__main__":
main()