OrwaMian/Network-Sentinel
GitHub: OrwaMian/Network-Sentinel
Stars: 0 | Forks: 0
# Network Sentinel
Network Sentinel monitors network activity on your local machine and raises alerts — and optionally takes automated action — when it detects port scanning, brute force authentication attempts, connections to known-malicious IPs, or abnormal connection rate spikes. It is designed as both a functional security tool and a portfolio demonstration of Blue Team detection engineering principles.
## What this tool is NOT
Honesty about scope is a Blue Team virtue. Network Sentinel is **not**:
- **Not a DDoS prevention tool.** Volumetric DDoS attacks are handled upstream at the ISP or CDN level. By the time a real DDoS reaches your host, your uplink is already saturated and there is nothing a host-based tool can do. Network Sentinel handles attack classes where the host has meaningful agency: reconnaissance, credential attacks, and malicious outbound connections.
- **Not a replacement for endpoint protection.** Windows Defender, Microsoft Defender for Endpoint, or a commercial EDR product provide far deeper kernel-level visibility. Network Sentinel is a supplementary layer, not a substitute.
- **Not a SIEM.** It produces SIEM-compatible JSON Lines logs, but it is not a log aggregation, correlation, or alerting platform.
- **Not a commercial-grade product.** This is an educational and portfolio project demonstrating Blue Team detection thinking. It should not be treated as a production security control without significant additional hardening and testing.
## Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ Network Sentinel │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│ │ Port Scan │ │Brute Force │ │ Threat Feed │ │ Rate │ │
│ │ Detector │ │ Detector │ │ Detector │ │ Anomaly │ │
│ │ (psutil) │ │ (pywin32) │ │(local/API) │ │ Detector │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌──────┴────────────────┴────────────────┴───────────────┴──────┐ │
│ │ Python logging pipeline │ │
│ │ (log_event() → handlers fan out to all consumers) │ │
│ └──────┬─────────────────────────┬──────────────────────────────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌────────▼────────┐ ┌──────────────────┐ │
│ │ Firewall │ │ Structured │ │ Live Terminal │ │
│ │ Responder │ │ Logger │ │ Dashboard │ │
│ │ (netsh) │ │(.log + .jsonl) │ │ (rich) │ │
│ └─────────────┘ └─────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Each detector runs in its own daemon thread so no single detector can block the others. Alerts flow through the standard Python `logging` pipeline — a structured `log_event()` call attaches metadata to the log record, and multiple handlers consume it independently: a rotating text log, a JSON Lines log, the dashboard's in-memory alert store, and (optionally) the firewall responder.
## Detectors
| Detector | Data source | Alert level | Event type |
|---|---|---|---|
| Port scan | `psutil.net_connections()` | WARNING | `PORT_SCAN_DETECTED` |
| Brute force | Windows Event Log (4625/4624) | WARNING / CRITICAL | `BRUTE_FORCE_DETECTED` / `BRUTE_FORCE_SUCCESS` |
| Threat feed | `psutil` + local blocklist / AbuseIPDB | CRITICAL | `THREAT_FEED_HIT` |
| Rate anomaly | `psutil.net_connections()` delta | WARNING | `RATE_ANOMALY_DETECTED` |
## Installation
### Prerequisites
- **Windows 11** (Windows 10 also supported; not tested on older versions)
- **Python 3.10 or later** — download from [python.org](https://www.python.org/downloads/)
- **Administrator privileges** — required for Event Log access and firewall rule management
### Enable Windows Advanced Audit Policy (required for brute force detection)
auditpol /set /subcategory:"Logon" /failure:enable /success:enable
Or via the GUI: **Local Security Policy** (`secpol.msc`) → **Security Settings → Advanced Audit Policy Configuration → Logon/Logoff → Audit Logon → Failure**.
### Install dependencies
# Clone the repository
git clone https://github.com/muhammadmian/network-sentinel.git
cd network-sentinel
# Create and activate a virtual environment (recommended)
python -m venv venv
venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
## Quick start
# Run with the live dashboard (default)
python -m network_sentinel.main
# Log-only mode — no dashboard, useful for running as a background process
python -m network_sentinel.main --no-dashboard
# Specify a custom config file
python -m network_sentinel.main --config my_config.yaml
**To test port scan detection:** Once the tool is running, use Nmap from another machine or a VM:
nmap -sS -p 1-1000
An alert should appear in the dashboard within the configured time window (default: 60 seconds).
## Sample output
Dashboard (live terminal view):
╔══════════════════════════════════════════════════════════════════╗
║ Network Sentinel v0.1.0 — Live View ║
╠══════════════════════════════════════════════════════════════════╣
║ Uptime: 00:03:17 │ Alerts (total): 2 │ Blocked IPs: 0 ║
╠═══════════════════════════════════╦══════════════════════════════╣
║ RECENT ALERTS ║ ACTIVE DETECTORS ║
║ ║ ● port-scan-detector ║
║ 20:14:02 WARNING PORT_SCAN_… ║ ● brute-force-detector ║
║ from 203.0.113.5 ║ ● threat-feed-detector ║
║ ports: 23, 80, 443, 8080 (+7) ║ ● rate-anomaly-detector ║
║ ║ ║
╚═══════════════════════════════════╩══════════════════════════════╝
JSON Lines log entry (one line per event, suitable for SIEM ingestion):
{
"timestamp": "2026-05-25T20:14:02.831Z",
"level": "WARNING",
"event_type": "PORT_SCAN_DETECTED",
"source_ip": "203.0.113.5",
"detector": "port_scan",
"severity": "HIGH",
"details": {
"distinct_ports": 10,
"window_seconds": 60,
"sample_ports": [23, 80, 443, 8080, 3389, 22, 21, 25, 110, 8443]
}
}
## Configuration reference
All settings live in `config.yaml`. The file is heavily commented — read it for full details.
### General
| Setting | Default | Description |
|---|---|---|
| `general.poll_interval_seconds` | `5` | How often (seconds) each detector checks for new events |
| `general.ip_whitelist` | `[127.0.0.1, ::1]` | IPs that never trigger alerts — add your router, VPN gateway, etc. |
### Port scan detector
| Setting | Default | Description |
|---|---|---|
| `port_scan.enabled` | `true` | Enable or disable this detector |
| `port_scan.threshold_ports` | `10` | Distinct ports probed within the window before alerting |
| `port_scan.window_seconds` | `60` | Sliding time window for port counting |
| `port_scan.tracked_states` | `[ESTABLISHED, SYN_SENT, ...]` | Connection states that count as a probe |
### Brute force detector
| Setting | Default | Description |
|---|---|---|
| `brute_force.enabled` | `true` | Enable or disable this detector |
| `brute_force.threshold_failures` | `5` | Failed logons (Event ID 4625) before alerting |
| `brute_force.window_seconds` | `120` | Sliding time window for failure counting |
| `brute_force.alert_on_success_after_failure` | `true` | Raise CRITICAL alert if a login succeeds after failures |
### Threat feed detector
| Setting | Default | Description |
|---|---|---|
| `threat_feed.enabled` | `true` | Enable or disable this detector |
| `threat_feed.local_blocklist_path` | `data/known_bad_ips.txt` | Path to local IP blocklist (one IP per line, `#` for comments) |
| `threat_feed.abuseipdb.enabled` | `false` | Enable AbuseIPDB live feed (requires an API key) |
| `threat_feed.abuseipdb.api_key` | `""` | Your AbuseIPDB free-tier API key |
| `threat_feed.abuseipdb.confidence_threshold` | `75` | Minimum AbuseIPDB confidence score (0–100) |
| `threat_feed.abuseipdb.refresh_interval_seconds` | `3600` | How often to refresh the AbuseIPDB feed |
### Rate anomaly detector
| Setting | Default | Description |
|---|---|---|
| `rate_anomaly.enabled` | `true` | Enable or disable this detector |
| `rate_anomaly.max_connections_per_second` | `20` | New connections per second from one IP before alerting |
| `rate_anomaly.baseline_period_seconds` | `60` | Startup silence period before alerting begins |
### Firewall responder (auto-block)
| Setting | Default | Description |
|---|---|---|
| `firewall.auto_block_enabled` | **`false`** | **Must be explicitly set to `true` to enable auto-blocking** |
| `firewall.block_on_detectors` | `[port_scan, brute_force, threat_feed]` | Which detectors may trigger a block |
| `firewall.rule_name_prefix` | `NetSentinel_Block` | Prefix for firewall rule names (makes them easy to find and clean up) |
| `firewall.block_duration_seconds` | `3600` | Auto-blocks expire after this many seconds; `0` = permanent |
## Local threat feed format
Edit `data/known_bad_ips.txt` to add known-bad IPs:
# Lines starting with # are comments
# One IP per line — IPv4 and IPv6 both supported
# Inline comments are also supported
198.51.100.1 # known C2 server
203.0.113.42 # malware distribution
2001:db8::bad # IPv6 example
To use the AbuseIPDB live feed instead of (or in addition to) the local list, set `threat_feed.abuseipdb.enabled: true` and add your API key. A free-tier AbuseIPDB account gives 1,000 API calls per day, which is more than enough for the default hourly refresh.
## Limitations and known caveats
- **Blind to encrypted tunnels.** If attacker C2 traffic is encrypted and uses ports that look normal (e.g., 443), the threat feed detector won't catch it unless the destination IP is on the blocklist.
- **psutil connection state accuracy.** On Windows, `psutil` reads from the same data source as `netstat`. SYN-only scans (no full TCP handshake) may not appear depending on OS and driver version.
- **Brute force source IP.** Windows Event ID 4625 includes the source IP for network logon attempts, but local interactive logon failures (someone sitting at the keyboard) won't have a source IP. The detector handles this gracefully by skipping those events.
- **No packet capture.** Network Sentinel does not use raw packet capture. It relies on connection tables and event logs. This is a deliberate design choice — packet capture requires kernel-level drivers and is out of scope for a host-based tool of this type.
- **Rate anomaly first-poll silence.** The rate anomaly detector cannot flag connections on its very first poll because it has no prior snapshot to compare against. It will also remain silent during the configured `baseline_period_seconds`. This is by design.
- **Auto-block side effects.** Misconfigured whitelists could block legitimate traffic. Always test in detection-only mode first. Auto-block is disabled by default.
- **Requires Administrator.** Without Administrator privileges, `psutil.net_connections()` on Windows returns a partial view, and Event Log access will be denied. The tool handles this gracefully with logged warnings, but coverage will be reduced.
## Running the tests
# Run the full test suite
python -m unittest discover -s tests -v
# Run a single test module
python -m unittest tests.test_port_scan -v
## Linux portability notes
| Feature | Linux compatible? | Notes |
|---|---|---|
| Port scan detection | Yes | `psutil` is cross-platform |
| Connection rate anomaly | Yes | `psutil` is cross-platform |
| Threat feed matching | Yes | No OS-specific dependencies |
| Brute force detection | Partial | Would need to read `/var/log/auth.log` or use `journalctl` instead of Windows Event Log |
| Auto-block | Partial | Would use `iptables`/`nftables` instead of `netsh advfirewall` |
| Dashboard | Yes | `rich` is cross-platform |
## Future enhancements
- [ ] Email / webhook alerting (send alerts to Slack, Teams, or email on CRITICAL events)
- [ ] Export blocked IP list and alert history to CSV for post-incident review
- [ ] Windows Service wrapper (run as a background service on startup)
- [ ] GeoIP lookup for alert enrichment (country of origin for suspicious IPs)
- [ ] MITRE ATT&CK technique tagging on alerts (e.g., T1046 for port scanning)
- [ ] Machine learning baseline for rate anomaly detection (instead of a static threshold)
- [ ] Cross-host correlation via syslog forwarding to a central collector
## Development
# Run tests
python -m unittest discover -s tests -v
# Check code style (requires ruff)
pip install ruff
python -m ruff check network_sentinel/
# Check types (requires mypy)
pip install mypy
python -m mypy network_sentinel/