chore: update
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
RUSTFS_ACCESS_KEY=iBacJPHUHSf6SMTnxrr
|
||||
RUSTFS_SECRET_KEY=4jNzZhstv1WkwTwtvR4gHSbrx01m4sJl4LBBleeJ
|
||||
|
||||
XAVIA_ADMIN_PASSWORD=2VYfheOweyMiP510GGfjNYmq3vJGJ
|
||||
XAVIA_UPLOAD_KEY=dNW2tiNXRR6w1cLwlmCOyKFIKvoTz8xQMSyd
|
||||
XAVIA_PRIVATE_KEY_BASE_64=MlRvcGlyNHpFRjhYOTlvUjMxbHFCVHRQdjYyelh4Wnc0MDM4TkZaVQ==
|
||||
XAVIA_POSTGRES_USER=xavia
|
||||
XAVIA_POSTGRES_PASSWORD=6DzLcsb5rgWukuGdrHtRBQ222f
|
||||
XAVIA_POSTGRES_DB=releases_db
|
||||
@@ -0,0 +1,99 @@
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: s3_nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./nginx/certs:/etc/nginx/certs:ro
|
||||
- nginx_logs:/var/log/nginx
|
||||
depends_on:
|
||||
- rustfs
|
||||
- xavia
|
||||
networks:
|
||||
- s3_net
|
||||
|
||||
rustfs_perm:
|
||||
image: alpine:latest
|
||||
container_name: rustfs_perm
|
||||
volumes:
|
||||
- /mnt/data:/data
|
||||
command: chown -R 10001:10001 /data
|
||||
|
||||
rustfs:
|
||||
image: rustfs/rustfs:latest
|
||||
depends_on:
|
||||
rustfs_perm:
|
||||
condition: service_completed_successfully
|
||||
hostname: rustfs
|
||||
container_name: rustfs
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /mnt/data:/data
|
||||
- /mnt/logs:/logs
|
||||
environment:
|
||||
- RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY:-iBacJPHUHSf6SMTnxrr}
|
||||
- RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY:-4jNzZhstv1WkwTwtvR4gHSbrx01m4sJl4LBBleeJ}
|
||||
- RUSTFS_SERVER_DOMAINS=rustfs.uber-stup.club
|
||||
- RUSTFS_CONSOLE_ENABLE=true
|
||||
- RUSTFS_ADDRESS=:9000
|
||||
- RUSTFS_CONSOLE_ADDRESS=:9001
|
||||
networks:
|
||||
- s3_net
|
||||
|
||||
xavia_db:
|
||||
image: postgres:16-alpine
|
||||
container_name: xavia_db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=${XAVIA_POSTGRES_USER:-xavia}
|
||||
- POSTGRES_PASSWORD=${XAVIA_POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${XAVIA_POSTGRES_DB:-releases_db}
|
||||
volumes:
|
||||
- xavia_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- s3_net
|
||||
|
||||
xavia:
|
||||
image: xaviaio/xavia-ota:latest
|
||||
container_name: xavia
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- HOST=https://ota.uber-stup.club
|
||||
- BLOB_STORAGE_TYPE=local
|
||||
- DB_TYPE=postgres
|
||||
- ADMIN_PASSWORD=${XAVIA_ADMIN_PASSWORD}
|
||||
- UPLOAD_KEY=${XAVIA_UPLOAD_KEY}
|
||||
- PRIVATE_KEY_BASE_64=${XAVIA_PRIVATE_KEY_BASE_64}
|
||||
- POSTGRES_USER=${XAVIA_POSTGRES_USER:-xavia}
|
||||
- POSTGRES_PASSWORD=${XAVIA_POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${XAVIA_POSTGRES_DB:-releases_db}
|
||||
- POSTGRES_HOST=xavia_db
|
||||
- POSTGRES_PORT=5432
|
||||
volumes:
|
||||
- xavia_blobs:/app/blobs
|
||||
depends_on:
|
||||
- xavia_db
|
||||
networks:
|
||||
- s3_net
|
||||
|
||||
dozzle-agent:
|
||||
image: amir20/dozzle:latest
|
||||
command: agent
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- "7007:7007"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
s3_net:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
nginx_logs:
|
||||
xavia_db_data:
|
||||
xavia_blobs:
|
||||
@@ -0,0 +1,98 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
resolver 127.0.0.11 valid=10s ipv6=off;
|
||||
|
||||
# Redirect HTTP -> HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# ── RustFS Console ──────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name rustfs.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/rustfs_access.log;
|
||||
error_log /var/log/nginx/rustfs_error.log;
|
||||
|
||||
location / {
|
||||
set $upstream http://rustfs:9001;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 500m;
|
||||
}
|
||||
}
|
||||
|
||||
# ── RustFS S3 API ───────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name s3.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/rustfs_s3_access.log;
|
||||
error_log /var/log/nginx/rustfs_s3_error.log;
|
||||
|
||||
location / {
|
||||
set $upstream http://rustfs:9000;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 2g;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Xavia OTA ───────────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ota.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/xavia_access.log;
|
||||
error_log /var/log/nginx/xavia_error.log;
|
||||
|
||||
location / {
|
||||
set $upstream http://xavia:3000;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 500m;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
# ClamAV Integration with Wazuh
|
||||
|
||||
Integration guide for deploying ClamAV antivirus with Wazuh monitoring stack.
|
||||
|
||||
## Overview
|
||||
|
||||
ClamAV scans files and containers for malware, while Wazuh collects and analyzes ClamAV logs for:
|
||||
- Real-time malware detection alerts
|
||||
- Ransomware detection
|
||||
- Signature database update status
|
||||
- Scan statistics and quarantine actions
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ClamAV Container (clamav) │
|
||||
│ • Scans Docker containers/files │
|
||||
│ • Generates logs: clamav.log │
|
||||
│ • Freshclam updates signatures │
|
||||
└──────────────┬──────────────────────┘
|
||||
│ (logs volume)
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ Wazuh Manager (wazuh.manager) │
|
||||
│ • Collects ClamAV logs │
|
||||
│ • Parses with decoders │
|
||||
│ • Matches detection rules │
|
||||
│ • Sends alerts to indexer │
|
||||
└──────────────┬──────────────────────┘
|
||||
│ (syslog format)
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ Wazuh Dashboard (UI) │
|
||||
│ • Display malware detections │
|
||||
│ • Show scan results │
|
||||
│ • Alert severity levels │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
### 1. Add ClamAV to docker-compose
|
||||
|
||||
The following service has been added to `docker-compose-security.yml`:
|
||||
|
||||
```yaml
|
||||
clamav:
|
||||
image: clamav/clamav:stable
|
||||
container_name: clamav
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- FRESHCLAM_CHECKS=24
|
||||
- CLAMD_SCAN_MAX_FILESIZE=100M
|
||||
volumes:
|
||||
- clamav_data:/var/lib/clamav # Signature database
|
||||
- clamav_logs:/var/log/clamav # Log output
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- monitoring_net
|
||||
```
|
||||
|
||||
### 2. Deploy ClamAV
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/docker
|
||||
docker compose -f docker-compose-security.yml up -d clamav
|
||||
|
||||
# Verify deployment
|
||||
docker ps | grep clamav
|
||||
docker logs clamav
|
||||
```
|
||||
|
||||
### 3. Wazuh Configuration
|
||||
|
||||
#### Log Collection
|
||||
|
||||
File: `wazuh/config/wazuh_manager/localfile_clamav.conf`
|
||||
|
||||
Configures Wazuh to collect:
|
||||
- `clamav.log` — Main scanner logs
|
||||
- `freshclam.log` — Signature update logs
|
||||
- `alert.log` — High-priority detections
|
||||
|
||||
#### Detection Rules
|
||||
|
||||
File: `wazuh/config/wazuh_manager/rules/clamav_rules.xml`
|
||||
|
||||
Key rules (level/priority):
|
||||
|
||||
| Rule ID | Level | Trigger | Example |
|
||||
|---------|-------|---------|---------|
|
||||
| 100501 | 15 | FOUND/Infected | Malware detected |
|
||||
| 100502 | 12 | Trojan/PUA | Potentially unwanted app |
|
||||
| 100503 | 15 | .Virus/Worm | Classic virus detection |
|
||||
| 100504 | 15 | Ransomware | Ransomware families |
|
||||
| 100505 | 3 | Update successful | Signature DB refreshed |
|
||||
| 100506 | 10 | Update failed | Download/connection error |
|
||||
| 100507 | 8 | Daemon error | ClamAV process error |
|
||||
| 100515 | 16 | Multiple hits in 1h | Possible outbreak |
|
||||
|
||||
---
|
||||
|
||||
## Log Format
|
||||
|
||||
### ClamAV Log Example
|
||||
|
||||
```
|
||||
Jun 10 14:35:22 clamav clamd[1234]: /var/data/suspect.exe: Trojan.Win32.Generic!c FOUND
|
||||
Jun 10 14:35:25 clamav freshclam[5678]: ClamAV update completed. 1 databases updated.
|
||||
Jun 10 14:36:01 clamav clamd[1234]: Scanning started
|
||||
Jun 10 14:36:45 clamav clamd[1234]: Scanning finished. 2 files scanned, 0 threats found
|
||||
```
|
||||
|
||||
### Wazuh Alert Example
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-06-10T14:35:22.000Z",
|
||||
"rule": {
|
||||
"id": "100501",
|
||||
"level": 15,
|
||||
"description": "ClamAV: Malware detected"
|
||||
},
|
||||
"data": {
|
||||
"srcfile": "/var/data/suspect.exe",
|
||||
"alert": "Trojan.Win32.Generic!c FOUND"
|
||||
},
|
||||
"groups": ["malware", "clamav", "infection"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Operations
|
||||
|
||||
### Check ClamAV Status
|
||||
|
||||
```bash
|
||||
# Container status
|
||||
docker ps | grep clamav
|
||||
|
||||
# View logs
|
||||
docker logs clamav
|
||||
|
||||
# Manual scan
|
||||
docker exec clamav clamscan -r /var/data
|
||||
```
|
||||
|
||||
### Update Signatures
|
||||
|
||||
ClamAV automatically updates signatures (configured via `FRESHCLAM_CHECKS=24`).
|
||||
|
||||
Manual update:
|
||||
```bash
|
||||
docker exec clamav freshclam
|
||||
```
|
||||
|
||||
### View Wazuh Alerts
|
||||
|
||||
1. Access Wazuh Dashboard: `https://10.0.0.2`
|
||||
2. Go to: **Security Events** → **Search**
|
||||
3. Filter by:
|
||||
- `rule.id: 100501` — Malware detections
|
||||
- `rule.id: 100504` — Ransomware alerts
|
||||
- `rule.groups: malware` — All malware-related events
|
||||
|
||||
### Query via API
|
||||
|
||||
```bash
|
||||
# Get recent malware detections
|
||||
curl -k -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
"https://monitoring-uber:55000/api/v0/search?q=rule.id:100501&pretty"
|
||||
|
||||
# Get ClamAV scan statistics
|
||||
curl -k -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
"https://monitoring-uber:55000/api/v0/search?q=group:clamav&pretty"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tuning & Optimization
|
||||
|
||||
### Scan Performance
|
||||
|
||||
Adjust scan parameters in docker-compose environment:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- CLAMD_SCAN_MAX_FILESIZE=100M # Max file size to scan
|
||||
- CLAMD_MAX_SCAN_SIZE=200M # Max total scan size
|
||||
- CLAMD_SCAN_PE_PLUS=yes # Enhanced PE detection
|
||||
- CLAMD_SCAN_ARCHIVE=yes # Scan inside archives
|
||||
- CLAMD_MAX_FILES=10000 # Max files to scan
|
||||
```
|
||||
|
||||
### Update Frequency
|
||||
|
||||
Default: 24 checks per day (every hour)
|
||||
|
||||
Change via:
|
||||
```yaml
|
||||
environment:
|
||||
- FRESHCLAM_CHECKS=48 # 2-hourly updates
|
||||
```
|
||||
|
||||
### Alert Severity
|
||||
|
||||
Adjust rule levels in `clamav_rules.xml` based on your risk tolerance:
|
||||
- Level 3-6: Info/Low
|
||||
- Level 8-10: Medium
|
||||
- Level 12-15: High
|
||||
- Level 16+: Critical/Outbreak
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### ClamAV Not Scanning
|
||||
|
||||
```bash
|
||||
# Check daemon is running
|
||||
docker exec clamav ps aux | grep clamd
|
||||
|
||||
# Check signatures are loaded
|
||||
docker exec clamav clamscan --version
|
||||
|
||||
# Manually scan
|
||||
docker exec clamav clamscan /var/data
|
||||
```
|
||||
|
||||
### Signature Updates Failing
|
||||
|
||||
```bash
|
||||
# Check freshclam logs
|
||||
docker logs clamav | grep freshclam
|
||||
|
||||
# Manual update with verbose output
|
||||
docker exec clamav freshclam -v
|
||||
|
||||
# Check internet connectivity
|
||||
docker exec clamav wget https://cvd.clamav.net
|
||||
```
|
||||
|
||||
### Wazuh Not Receiving Logs
|
||||
|
||||
```bash
|
||||
# Check logs are being generated
|
||||
docker exec clamav tail -f /var/log/clamav/clamav.log
|
||||
|
||||
# Check Wazuh log collection
|
||||
docker exec wazuh_manager tail -f /var/ossec/logs/ossec.log | grep clamav
|
||||
|
||||
# Verify rules loaded
|
||||
docker exec wazuh_manager cat /var/ossec/etc/rules/clamav_rules.xml | head -10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files Modified/Created
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `docker-compose-security.yml` | Added ClamAV service + volumes |
|
||||
| `wazuh/config/wazuh_manager/localfile_clamav.conf` | Log collection config |
|
||||
| `wazuh/config/wazuh_manager/rules/clamav_rules.xml` | Malware detection rules |
|
||||
| `CLAMAV_INTEGRATION.md` | This documentation |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Deploy: `docker compose up -d clamav`
|
||||
2. Wait for initial database download (5-10 minutes)
|
||||
3. Monitor logs: `docker logs -f clamav`
|
||||
4. Check Wazuh dashboard for alerts
|
||||
5. Configure scan schedules/locations as needed
|
||||
6. Set up active response (optional) for automatic quarantine
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# Firewall Configuration Rules
|
||||
|
||||
Updated: 2026-06-10
|
||||
|
||||
## Overview
|
||||
|
||||
Firewall rules for monitoring stack with Wazuh, Dozzle, Beszel, and VPN infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## monitoring-uber (185.103.167.138)
|
||||
|
||||
### Inbound Rules (INPUT)
|
||||
|
||||
| Port | Protocol | Source | Purpose | Status |
|
||||
|------|----------|--------|---------|--------|
|
||||
| 22 | TCP | Admin IPs | SSH administration | ALLOW |
|
||||
| 22 | TCP | 185.103.166.119 (prod) | SSH — BLOCKED | **DROP** |
|
||||
| 22 | TCP | 185.103.166.112 (pre-prod) | SSH — BLOCKED | **DROP** |
|
||||
| 22 | TCP | 80.96.58.164 (s3) | SSH — BLOCKED | **DROP** |
|
||||
| 1514 | TCP | 185.103.166.119 | Wazuh agents (prod) | ALLOW |
|
||||
| 1514 | TCP | 185.103.166.112 | Wazuh agents (pre-prod) | ALLOW |
|
||||
| 51820 | UDP | Any | WireGuard VPN | ALLOW |
|
||||
| 443 | TCP | 10.0.0.0/24 | Wazuh Dashboard (VPN) | ALLOW |
|
||||
| 8080 | TCP | 10.0.0.0/24 | Dozzle logs (VPN) | ALLOW |
|
||||
| 8090 | TCP | 10.0.0.0/24 | Beszel monitoring (VPN) | ALLOW |
|
||||
| 9000-9001 | TCP | 10.0.0.0/24 | S3/RustFS (VPN) | ALLOW |
|
||||
|
||||
### Outbound Rules (OUTPUT)
|
||||
- **Default:** ACCEPT (all traffic allowed)
|
||||
- Allows DNS, updates, internet access
|
||||
|
||||
### Forward Rules (FORWARD)
|
||||
- **Default:** DROP (no transit traffic)
|
||||
|
||||
### Persistence
|
||||
- Rules saved to `/etc/iptables/rules.v4`
|
||||
- Auto-loaded on boot via `iptables-persistent`
|
||||
|
||||
---
|
||||
|
||||
## vpn-uber (45.150.111.158)
|
||||
|
||||
### Inbound Rules (INPUT)
|
||||
|
||||
| Port | Protocol | Source | Purpose | Status |
|
||||
|------|----------|--------|---------|--------|
|
||||
| 22 | TCP | Any | SSH administration | ALLOW |
|
||||
| 51820 | UDP | Any | WireGuard VPN | ALLOW |
|
||||
| 10001 | TCP | 10.0.0.0/24 | Beszel agent (from VPN only) | ALLOW |
|
||||
|
||||
### Outbound Rules (OUTPUT)
|
||||
- **Default:** ACCEPT (all traffic allowed)
|
||||
|
||||
### Forward Rules (FORWARD)
|
||||
- **Default:** ACCEPT
|
||||
- Enables routing: wg0 ↔ eth0 (VPN ↔ Internet)
|
||||
- ESTABLISHED/RELATED always allowed
|
||||
|
||||
### Network Features
|
||||
- NAT masquerade: `eth0` (POSTROUTING)
|
||||
- IP forwarding: enabled (`net.ipv4.ip_forward=1`)
|
||||
- Allows VPN clients to reach internet through VPN server
|
||||
|
||||
### Persistence
|
||||
- Rules saved to `/etc/iptables/rules.v4`
|
||||
- IP forwarding saved to `/etc/sysctl.conf`
|
||||
|
||||
---
|
||||
|
||||
## Security Hardening
|
||||
|
||||
### Principle: Least Privilege
|
||||
1. **SSH restrictions**: Production servers (prod, pre-prod, s3) **cannot** SSH into monitoring-uber
|
||||
- Prevents lateral movement if a prod server is compromised
|
||||
- Admins must SSH directly to monitoring-uber or via VPN
|
||||
|
||||
2. **Service isolation**: All user-facing services (Wazuh, Dozzle, Beszel) accessible **only via VPN**
|
||||
- Not exposed to public internet
|
||||
- Network: 10.0.0.0/24 (private VPN)
|
||||
|
||||
3. **Port whitelist**: Only required ports open
|
||||
- Wazuh agent ingest: 1514/tcp (prod/pre-prod only)
|
||||
- VPN: 51820/udp (all)
|
||||
- SSH: 22/tcp (admin access, blocked from prod servers)
|
||||
- Monitoring agents: 10001/tcp (VPN only)
|
||||
|
||||
### Attack Surface Reduction
|
||||
- Production agents cannot access monitoring infrastructure
|
||||
- Monitoring dashboard only accessible via VPN
|
||||
- No exposed dashboards or logs to public internet
|
||||
- SSH brute-force: limited by rate (ESTABLISHED/RELATED state tracking)
|
||||
|
||||
---
|
||||
|
||||
## Updating Rules
|
||||
|
||||
### monitoring-uber
|
||||
```bash
|
||||
ssh root@185.103.167.138
|
||||
./firewall-monitoring-uber.sh
|
||||
```
|
||||
|
||||
### vpn-uber
|
||||
```bash
|
||||
ssh root@45.150.111.158
|
||||
./firewall-vpn-server.sh
|
||||
```
|
||||
|
||||
### Verify Rules Applied
|
||||
```bash
|
||||
# Check current rules
|
||||
iptables -L INPUT -n
|
||||
iptables -L FORWARD -n
|
||||
|
||||
# Check saved rules
|
||||
cat /etc/iptables/rules.v4
|
||||
```
|
||||
|
||||
### Restore Rules on Boot
|
||||
Rules are automatically restored via `/etc/iptables/rules.v4` if `iptables-persistent` is installed:
|
||||
```bash
|
||||
apt-get install iptables-persistent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Beszel Agent Configuration
|
||||
|
||||
Beszel agents installed on all infrastructure servers:
|
||||
|
||||
| Server | Type | Port | Access |
|
||||
|--------|------|------|--------|
|
||||
| prod-uber | Docker | 10001 | Public IP (185.103.166.119:10001) |
|
||||
| pre-prod-uber | Docker | 10001 | Public IP (185.103.166.112:10001) |
|
||||
| s3-uber | Docker | 10001 | Public IP (80.96.58.164:10001) |
|
||||
| vpn-uber | Binarie (systemd) | 10001 | VPN IP (10.0.0.1:10001) |
|
||||
|
||||
**Note:** vpn-uber agent is accessible **only from VPN** due to firewall rules.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service not reachable
|
||||
```bash
|
||||
# Check if service is listening
|
||||
ss -tlnp | grep <port>
|
||||
|
||||
# Check firewall allows traffic
|
||||
iptables -L INPUT -n | grep <port>
|
||||
|
||||
# Test connectivity
|
||||
nc -zv <ip> <port>
|
||||
```
|
||||
|
||||
### SSH access denied from prod
|
||||
- Expected behavior (security hardening)
|
||||
- Use admin SSH keys or SSH via VPN instead
|
||||
|
||||
### Beszel agent shows offline
|
||||
- Check agent is listening: `ss -tlnp | grep 10001`
|
||||
- Check firewall allows Beszel dashboard to reach agent
|
||||
- Verify network routing between monitoring-uber and agent server
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
# OWASP Top 10 ModSecurity Rules — Wazuh Active Response
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Ce système détecte et répond aux attaques OWASP Top 10 via ModSecurity + Wazuh.
|
||||
|
||||
**Deux couches de détection :**
|
||||
|
||||
| Type | Trigger | Règle | Level | AR |
|
||||
|------|---------|-------|-------|-----|
|
||||
| **Bloqué (403)** | HTTP 403 | 100220-100281 | 12-15 | Fermer 4h-24h |
|
||||
| **Remontée (Warning)** | Anomaly scoring | 100320-100381 | 6-11 | Fermer 30min-6h |
|
||||
|
||||
---
|
||||
|
||||
## Correspondances CRS ModSecurity
|
||||
|
||||
```
|
||||
941xxx — XSS (Cross-Site Scripting)
|
||||
942xxx — SQL Injection, LDAP Injection, etc.
|
||||
943xxx — XXE (XML External Entity)
|
||||
930xxx — Path Traversal, RFI, RCE, LFI
|
||||
932xxx — Remote Command Execution
|
||||
933xxx — PHP Injection
|
||||
934xxx — Java Injection
|
||||
950xxx — Exploit attempts
|
||||
951xxx — Regex DoS, Scanner detection
|
||||
952xxx — Restricted File Access
|
||||
953xxx — Insecure File Upload
|
||||
954xxx — Proxy abuse, Scanner detection
|
||||
955xxx — HTTP Response Splitting, Header Injection
|
||||
970xxx — SSRF (Server-Side Request Forgery)
|
||||
971xxx — SSRF (alternative patterns)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Règles par OWASP Category
|
||||
|
||||
### OWASP #1 : Broken Access Control
|
||||
|
||||
**Détecte :** Path Traversal, File Inclusion, Unauthorized Access
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100250 | Bloqué | 930xx (path\|traversal\|lfi) | 12 | LFI/Path Traversal bloquée |
|
||||
| 100251 | Bloqué | 930xx (rfi\|remote\|include) | 13 | RFI bloquée |
|
||||
| 100252 | Bloqué | 952xx | 11 | File Access bloquée |
|
||||
| 100293 | Bloqué | Freq(100250)×4/180s | 12 | Path Traversal brute-force |
|
||||
| 100350 | Remontée | 930xx (path\|traversal\|lfi) | 8 | LFI attempt (warning) |
|
||||
| 100351 | Remontée | 930xx (rfi\|remote\|include) | 9 | RFI attempt (warning) |
|
||||
| 100352 | Remontée | 952xx | 8 | File Access attempt (warning) |
|
||||
|
||||
**Active Response :**
|
||||
- Bloqué : `firewall-drop 6h`
|
||||
- Brute-force : `firewall-drop 24h`
|
||||
- Remontée : `firewall-drop 2h-4h`
|
||||
|
||||
---
|
||||
|
||||
### OWASP #3 : Injection
|
||||
|
||||
**Détecte :** SQLi, LDAP, Command Injection, PHP/Java Injection
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100220 | Bloqué | 942xx | 13 | SQL Injection bloquée |
|
||||
| 100221 | Bloqué | 942xx (LDAP pattern) | 12 | LDAP Injection bloquée |
|
||||
| 100222 | Bloqué | 932xx | 14 | Command Injection bloquée |
|
||||
| 100223 | Bloqué | 933xx | 13 | PHP Injection bloquée |
|
||||
| 100224 | Bloqué | 934xx | 13 | Java Injection bloquée |
|
||||
| 100290 | Bloqué | Freq(100220)×3/60s | 14 | SQLi brute-force |
|
||||
| 100292 | Bloqué | Freq(100222)×2/60s | 15 | Command Injection CRITICAL |
|
||||
| 100320 | Remontée | 942xx | 9 | SQLi attempt (warning) |
|
||||
| 100321 | Remontée | 932xx | 10 | Command Injection attempt |
|
||||
| 100322 | Remontée | 942xx (LDAP) | 9 | LDAP Injection attempt |
|
||||
| 100323 | Remontée | 933xx\|934xx | 9 | PHP/Java Injection attempt |
|
||||
| 100394 | Remontée | Freq(100320)×5/300s | 10 | SQLi anomaly scoring |
|
||||
| 100396 | Remontée | Freq(100321)×2/60s | 12 | Command Injection CRITICAL |
|
||||
|
||||
**Active Response :**
|
||||
- SQLi Bloquée : `firewall-drop 6h`
|
||||
- SQLi Brute-force : `firewall-drop 24h + host-deny permanent`
|
||||
- Command Injection : `firewall-drop 24h + host-deny`
|
||||
- Command Injection CRITICAL : `firewall-drop permanent + host-deny permanent`
|
||||
- SQLi Remontée : `firewall-drop 2h`
|
||||
- SQLi Anomaly : `firewall-drop 4h`
|
||||
- Command Injection Remontée : `firewall-drop 4h`
|
||||
|
||||
---
|
||||
|
||||
### OWASP #6 : Vulnerable & Outdated Components
|
||||
|
||||
**Détecte :** RCE, Exploit attempts, known vulnerabilities
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100230 | Bloqué | 930xx\|950xx | 14 | RCE/Exploit bloquée |
|
||||
| 100330 | Remontée | 930xx\|950xx | 11 | RCE/Exploit attempt (warning) |
|
||||
|
||||
**Active Response :**
|
||||
- Bloqué : `firewall-drop 24h`
|
||||
- Remontée : `firewall-drop 6h`
|
||||
|
||||
---
|
||||
|
||||
### OWASP #7 : Authentication & Session Management
|
||||
|
||||
**Détecte :** XSS, Header Injection, Session hijacking attempts
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100240 | Bloqué | 941xx | 12 | XSS bloquée |
|
||||
| 100241 | Bloqué | 955xx | 12 | Header Injection bloquée |
|
||||
| 100291 | Bloqué | Freq(100240)×5/120s | 13 | XSS anomaly scoring |
|
||||
| 100340 | Remontée | 941xx | 8 | XSS attempt (warning) |
|
||||
| 100341 | Remontée | 955xx | 8 | Header Injection attempt |
|
||||
| 100395 | Remontée | Freq(100340)×8/300s | 10 | XSS anomaly scoring |
|
||||
|
||||
**Active Response :**
|
||||
- XSS Bloquée : `firewall-drop 4h`
|
||||
- XSS Anomaly : `firewall-drop 6h`
|
||||
- Header Injection : `firewall-drop 6h`
|
||||
- XSS Remontée : `firewall-drop 1h`
|
||||
- Header Remontée : `firewall-drop 2h`
|
||||
|
||||
---
|
||||
|
||||
### OWASP #8 : Software & Data Integrity Failures
|
||||
|
||||
**Détecte :** XXE, Deserialization attacks
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100260 | Bloqué | 943xx | 13 | XXE bloquée |
|
||||
| 100360 | Remontée | 943xx | 9 | XXE attempt (warning) |
|
||||
|
||||
**Active Response :**
|
||||
- Bloqué : `firewall-drop 12h`
|
||||
- Remontée : `firewall-drop 4h`
|
||||
|
||||
---
|
||||
|
||||
### OWASP #9 : Logging & Monitoring Failures
|
||||
|
||||
**Détecte :** Web scanners, bot activity, reconnaissance
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100270 | Bloqué | 951xx\|954xx | 10 | Scanner detection (bloquée) |
|
||||
| 100370 | Remontée | 951xx\|954xx | 6 | Scanner detection (warning) |
|
||||
|
||||
**Active Response :**
|
||||
- Bloqué : `firewall-drop 2h`
|
||||
- Remontée : `firewall-drop 30min`
|
||||
|
||||
---
|
||||
|
||||
### Autres : SSRF & File Upload
|
||||
|
||||
| Rule ID | Type | Patterns | Level | Description |
|
||||
|---------|------|----------|-------|-------------|
|
||||
| 100280 | Bloqué | 970xx\|971xx | 13 | SSRF bloquée |
|
||||
| 100281 | Bloqué | 953xx | 12 | File Upload bloquée |
|
||||
| 100380 | Remontée | 970xx\|971xx | 9 | SSRF attempt |
|
||||
| 100381 | Remontée | 953xx | 8 | File Upload attempt |
|
||||
|
||||
**Active Response :**
|
||||
- SSRF Bloquée : `firewall-drop 12h`
|
||||
- File Upload Bloquée : `firewall-drop 6h`
|
||||
- SSRF Remontée : `firewall-drop 4h`
|
||||
- File Upload Remontée : `firewall-drop 2h`
|
||||
|
||||
---
|
||||
|
||||
## Timeline des Active Responses
|
||||
|
||||
### Bloquées (HTTP 403)
|
||||
|
||||
| Durée | Règles | Motif |
|
||||
|-------|--------|-------|
|
||||
| Permanent | 100292 | Command Injection CRITICAL (2+ tentatives / 60s) |
|
||||
| 24h | 100290 | SQLi brute-force (3+ / 60s) |
|
||||
| 24h | 100230 | RCE/Exploit |
|
||||
| 12h | 100251, 100260, 100280 | RFI, XXE, SSRF |
|
||||
| 6h | 100220, 100221, 100250, 100252, 100281, 100330 | SQLi, LDAP, Path Traversal, File Access, Upload, RCE |
|
||||
| 4h | 100240 | XSS |
|
||||
| 2h | 100270 | Scanner |
|
||||
|
||||
### Remontées (Anomaly Scoring)
|
||||
|
||||
| Durée | Règles | Motif |
|
||||
|-------|--------|-------|
|
||||
| Permanent | 100396 | Command Injection (2+ / 60s) |
|
||||
| 6h | 100395, 100330, 100351 | XSS anomaly, RCE, RFI |
|
||||
| 4h | 100394, 100321, 100323, 100360, 100380 | SQLi anomaly, Cmd Inj, PHP/Java, XXE, SSRF |
|
||||
| 2h | 100320, 100322, 100341, 100350, 100352, 100381 | SQLi, LDAP, Header Inj, Path Traversal, File Access, Upload |
|
||||
| 30min | 100370 | Scanner |
|
||||
|
||||
---
|
||||
|
||||
## Files
|
||||
|
||||
- **`modsecurity_owasp_rules.xml`** — Définition des règles (100220-100396)
|
||||
- **`ossec.conf`** — Active-response configs (firewall-drop, durées)
|
||||
- **`firewall-monitoring-uber.sh`** — iptables pour autoriser trafic ModSec
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
**Dashboard Wazuh :**
|
||||
|
||||
1. **Alerts → Security Events → OWASP**
|
||||
2. **Visualization:**
|
||||
- Blocking rate (HTTP 403)
|
||||
- Anomaly scoring trends
|
||||
- Top attackers (srcip)
|
||||
- Attack distribution by category
|
||||
|
||||
**Logs:**
|
||||
|
||||
```bash
|
||||
# On monitoring-uber
|
||||
tail -f /var/ossec/logs/alerts/alerts.json | grep -i "owasp\|100[23][0-9][0-9]"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tuning
|
||||
|
||||
Les seuils de fréquence peuvent être ajustés :
|
||||
|
||||
- **SQLi anomaly:** `frequency="5" timeframe="300"` → Réduire pour être plus agressif
|
||||
- **XSS anomaly:** `frequency="8" timeframe="300"` → Augmenter pour réduire false positives
|
||||
- **Command Injection:** `frequency="2" timeframe="60"` → Critique, ne pas modifier
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- **First-match semantics:** Wazuh évalue les règles par ID croissant → les règles bloquées (100220+) ont priorité sur les remontées (100320+)
|
||||
- **Field matching:** Les patterns utilisent `<field name="transaction.messages.message">` pour matcher les CRS rule IDs dans les logs ModSecurity
|
||||
- **SCA suppressed:** Les alertes SCA (CIS benchmark) sont à level 0 (voir `local_sca_noise.xml`)
|
||||
- **Persistence:** Tous les AR sont sauvegardés dans `iptables-save` → survient les reboots
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
# VPN Deployment Summary
|
||||
|
||||
## Infrastructure
|
||||
|
||||
| Role | Hostname | IP Public | IP VPN | Status |
|
||||
|------|----------|-----------|--------|--------|
|
||||
| **VPN Server** | vpn-uber | 45.150.111.158 | 10.0.0.1/24 | ✓ Active |
|
||||
| **Monitoring** | monitoring-uber | 185.103.167.138 | 10.0.0.2/24 | ✓ Connected |
|
||||
| **Admins** | (clients) | — | 10.0.0.3+ | Ready |
|
||||
|
||||
---
|
||||
|
||||
## Server Credentials
|
||||
|
||||
### VPN Server (vpn-uber)
|
||||
|
||||
- **IP Public:** 45.150.111.158
|
||||
- **Port:** 51820/udp
|
||||
- **Server Private Key:** (secured at `/etc/wireguard/privatekey`)
|
||||
- **Server Public Key:** `VQa6g1foaXhJgYWbwyJ9R/EAmmXg0nOnhPhbIIPLlmg=`
|
||||
- **Network:** 10.0.0.0/24
|
||||
- **Interface IP:** 10.0.0.1
|
||||
|
||||
**SSH Access:**
|
||||
```bash
|
||||
ssh root@45.150.111.158
|
||||
# Password: yqZ98EJL1h3ISlfT6l (from host.ini)
|
||||
```
|
||||
|
||||
### Monitoring Server (monitoring-uber)
|
||||
|
||||
- **IP Public:** 185.103.167.138
|
||||
- **VPN IP:** 10.0.0.2/24
|
||||
- **Status:** Connected to VPN ✓
|
||||
- **Firewall:** Configured (iptables)
|
||||
- **Interface:** wg0 UP
|
||||
|
||||
**SSH Access:**
|
||||
```bash
|
||||
ssh root@185.103.167.138
|
||||
# Password: rL9lY6YkcDQmfRuZ3Z (from host.ini)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## VPN Configuration
|
||||
|
||||
### Firewall Rules
|
||||
|
||||
**VPN Server (vpn-uber):**
|
||||
```
|
||||
INPUT:
|
||||
✓ 22/tcp (SSH)
|
||||
✓ 51820/udp (WireGuard)
|
||||
✗ Everything else → REJECT
|
||||
|
||||
OUTPUT:
|
||||
✓ All
|
||||
|
||||
FORWARD:
|
||||
✓ wg0 interface (VPN traffic)
|
||||
✓ NAT masquerade (10.0.0.0/24 → Internet)
|
||||
```
|
||||
|
||||
**Monitoring Server (monitoring-uber):**
|
||||
```
|
||||
INPUT:
|
||||
✓ 1514/tcp FROM 185.103.166.119 (Prod agents)
|
||||
✓ 1514/tcp FROM 185.103.166.112 (Pre-prod agents)
|
||||
✓ 51820/udp (VPN)
|
||||
✓ 443/tcp FROM 10.0.0.0/24 (Wazuh Dashboard)
|
||||
✓ 8080/tcp FROM 10.0.0.0/24 (Dozzle)
|
||||
✓ 9090/tcp FROM 10.0.0.0/24 (Beszel)
|
||||
✓ 9000-9001/tcp FROM 10.0.0.0/24 (S3/RustFS)
|
||||
✗ Everything else → DROP
|
||||
|
||||
OUTPUT:
|
||||
✓ All (Internet)
|
||||
```
|
||||
|
||||
### WireGuard Routing
|
||||
|
||||
```
|
||||
VPN Server (10.0.0.1)
|
||||
↓
|
||||
Monitoring (10.0.0.2) — Connected ✓
|
||||
↓
|
||||
Admin Clients (10.0.0.3+) — Ready to connect
|
||||
```
|
||||
|
||||
**Current Peers:**
|
||||
```
|
||||
peer: 4WLn2BR9ZGhM195mIvLbZR7tP/mb7ks4+mZ5ppZ21xw= (monitoring-uber)
|
||||
allowed ips: 10.0.0.2/32
|
||||
status: Connected ✓ (45ms latency, 0% loss)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Services Accessible via VPN
|
||||
|
||||
Once connected to VPN from admin client:
|
||||
|
||||
| Service | URL | Port | Status |
|
||||
|---------|-----|------|--------|
|
||||
| **Wazuh Dashboard** | https://10.0.0.2 | 443 | ✓ (VPN only) |
|
||||
| **Dozzle** | http://10.0.0.2:8080 | 8080 | ✓ (VPN only) |
|
||||
| **Beszel** | http://10.0.0.2:9090 | 9090 | ✓ (VPN only) |
|
||||
| **S3/RustFS Console** | http://10.0.0.2:9001 | 9001 | ✓ (VPN only) |
|
||||
| **S3/RustFS API** | http://10.0.0.2:9000 | 9000 | ✓ (VPN only) |
|
||||
|
||||
**Mode:** VPN + Internet normal (no kill switch)
|
||||
- Admins can access services via VPN
|
||||
- Admins keep normal Internet access
|
||||
- If VPN drops → automatic fallback to Internet
|
||||
|
||||
---
|
||||
|
||||
## Next Steps for Admins
|
||||
|
||||
### 1. Generate Client Configs
|
||||
|
||||
```bash
|
||||
./wireguard-admin-client.sh admin1 45.150.111.158 "VQa6g1foaXhJgYWbwyJ9R/EAmmXg0nOnhPhbIIPLlmg="
|
||||
```
|
||||
|
||||
Creates: `admin1.conf`
|
||||
|
||||
### 2. Add Client to VPN Server
|
||||
|
||||
SSH to VPN server:
|
||||
```bash
|
||||
ssh root@45.150.111.158
|
||||
```
|
||||
|
||||
Then:
|
||||
```bash
|
||||
# Get client's public key from admin1.conf (PrivateKey → PublicKey)
|
||||
wg set wg0 peer <CLIENT_PUBKEY> allowed-ips 10.0.0.3/32
|
||||
wg show
|
||||
```
|
||||
|
||||
### 3. Admin Setup
|
||||
|
||||
- Install WireGuard app (wireguard.com/install)
|
||||
- Import admin1.conf
|
||||
- Connect to VPN
|
||||
- Test access to services
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### From Monitoring Server
|
||||
|
||||
```bash
|
||||
# Test VPN connection
|
||||
ping 10.0.0.1
|
||||
# Response: 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=45.0 ms
|
||||
|
||||
# Check VPN status
|
||||
ip addr show wg0
|
||||
ip route show | grep wg0
|
||||
|
||||
# VPN traffic
|
||||
tcpdump -i wg0
|
||||
```
|
||||
|
||||
### From VPN Server
|
||||
|
||||
```bash
|
||||
# Monitor active connections
|
||||
wg show
|
||||
|
||||
# Check interface
|
||||
ip addr show wg0
|
||||
|
||||
# Verify firewall rules
|
||||
iptables -L
|
||||
iptables -L -t nat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Monitoring not connecting to VPN
|
||||
|
||||
```bash
|
||||
# Check WireGuard daemon
|
||||
ssh root@185.103.167.138
|
||||
systemctl status wg-quick@wg0
|
||||
journalctl -u wg-quick@wg0 -n 20
|
||||
|
||||
# Restart
|
||||
systemctl restart wg-quick@wg0
|
||||
```
|
||||
|
||||
### VPN Server not accepting peers
|
||||
|
||||
```bash
|
||||
# On VPN server, verify WireGuard is running
|
||||
wg show
|
||||
|
||||
# Check if peer was added correctly
|
||||
wg show wg0
|
||||
|
||||
# If not showing, re-add:
|
||||
wg set wg0 peer <CLIENT_PUBKEY> allowed-ips 10.0.0.X/32
|
||||
```
|
||||
|
||||
### Admin client can't connect
|
||||
|
||||
- Verify VPN server is listening: `netstat -ulnp | grep 51820`
|
||||
- Verify firewall allows 51820/udp: `ufw status` or `iptables -L`
|
||||
- Check client config has correct server IP and pubkey
|
||||
- Try reconnecting after 2-3 seconds
|
||||
|
||||
---
|
||||
|
||||
## Files & Scripts Used
|
||||
|
||||
- `firewall-vpn-server.sh` — VPN server firewall (iptables)
|
||||
- `wireguard-server-setup.sh` — WireGuard server install + config
|
||||
- `firewall-monitoring-uber.sh` — Monitoring firewall (iptables)
|
||||
- `wireguard-client-setup.sh` — WireGuard client install
|
||||
- `wireguard-admin-client.sh` — Generate admin client configs
|
||||
- `VPN_SETUP.md` — Full setup guide (phases 1-7)
|
||||
|
||||
---
|
||||
|
||||
## Persistence
|
||||
|
||||
All configurations survive reboot:
|
||||
|
||||
- **Firewall:** `/etc/iptables/rules.v4` (loaded via iptables-restore)
|
||||
- **WireGuard:** Enabled at boot via `systemctl enable wg-quick@wg0`
|
||||
- **Routes:** Persistent in wg0 config
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Firewall rules block unauthorized access
|
||||
- WireGuard handshake: 45ms latency (acceptable)
|
||||
- No kill switch enabled (VPN + Internet normal)
|
||||
- Services (Wazuh, Dozzle, Beszel, S3) accessible ONLY via VPN
|
||||
- Agents (prod/pre-prod) still have direct access to Wazuh manager (1514/tcp)
|
||||
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
✓ VPN Server deployed on vpn-uber (45.150.111.158)
|
||||
✓ Monitoring-uber connected to VPN (10.0.0.2)
|
||||
✓ Firewall configured on both servers
|
||||
✓ VPN connection tested (45ms, 0% loss)
|
||||
✓ Ready for admin client setup
|
||||
@@ -0,0 +1,255 @@
|
||||
# VPN Setup for Monitoring Stack
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Internet (public)
|
||||
├─ [Prod/Pre-prod] (accessible)
|
||||
│ └─→(1514/tcp)→ monitoring-uber (port ouvert)
|
||||
│
|
||||
├─ [VPN Server] (nouveau VPS, 1 CPU 2GB RAM)
|
||||
│ └─ WireGuard 0.0.0.0:51820/udp
|
||||
│
|
||||
└─ [monitoring-uber] (185.103.167.138)
|
||||
├─ Client VPN (10.0.0.2)
|
||||
└─ Services: Wazuh, Dozzle, Beszel, S3 (VPN only)
|
||||
|
||||
VPN Network: 10.0.0.0/24
|
||||
├─ VPN Server: 10.0.0.1
|
||||
├─ monitoring-uber: 10.0.0.2
|
||||
└─ Admins: 10.0.0.3+
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
**Mode:** VPN + Internet normal (pas de kill switch)
|
||||
- Admins connectés au VPN → accès à services VPN (10.0.0.0/24)
|
||||
- Admins gardent aussi accès à Internet normal (pas de restriction)
|
||||
- Si VPN tombe → retrouvent Internet automatiquement
|
||||
|
||||
---
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: VPN Server Setup (nouveau VPS)
|
||||
|
||||
```bash
|
||||
# 1. Login to VPS
|
||||
ssh root@<VPN_SERVER_IP>
|
||||
|
||||
# 2. Run firewall setup
|
||||
chmod +x /path/to/firewall-vpn-server.sh
|
||||
./firewall-vpn-server.sh
|
||||
|
||||
# 3. Setup WireGuard server
|
||||
chmod +x /path/to/wireguard-server-setup.sh
|
||||
./wireguard-server-setup.sh
|
||||
|
||||
# Output will show:
|
||||
# - Server Public Key (note this)
|
||||
# - Example: aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE=
|
||||
```
|
||||
|
||||
Save the **Server Public Key** — you'll need it for clients.
|
||||
|
||||
### Phase 2: monitoring-uber VPN Client
|
||||
|
||||
```bash
|
||||
# 1. Login to monitoring-uber
|
||||
ssh root@185.103.167.138
|
||||
|
||||
# 2. Run firewall setup
|
||||
chmod +x /path/to/firewall-monitoring-uber.sh
|
||||
./firewall-monitoring-uber.sh
|
||||
|
||||
# 3. Setup WireGuard client
|
||||
# Syntax: wireguard-client-setup.sh <VPN_SERVER_IP> <VPN_SERVER_PUBKEY>
|
||||
chmod +x /path/to/wireguard-client-setup.sh
|
||||
./wireguard-client-setup.sh <VPN_SERVER_IP> "<SERVER_PUBKEY>"
|
||||
|
||||
# Example:
|
||||
# ./wireguard-client-setup.sh 123.45.67.89 "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE="
|
||||
|
||||
# Output will show:
|
||||
# - Client Public Key (note this)
|
||||
# - Example: XyZ9876543210AbCdEfGhIjKlMnOpQrStUvWxYz=
|
||||
```
|
||||
|
||||
### Phase 3: Add monitoring-uber to VPN Server
|
||||
|
||||
```bash
|
||||
# Back on VPS, add monitoring-uber as a peer
|
||||
ssh root@<VPN_SERVER_IP>
|
||||
|
||||
# Use the Client Public Key from Phase 2
|
||||
wg set wg0 peer <CLIENT_PUBKEY> allowed-ips 10.0.0.2/32
|
||||
|
||||
# Verify
|
||||
wg show
|
||||
|
||||
# Example output:
|
||||
# interface: wg0
|
||||
# public key: aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE=
|
||||
# private key: (hidden)
|
||||
# listening port: 51820
|
||||
#
|
||||
# peer: XyZ9876543210AbCdEfGhIjKlMnOpQrStUvWxYz=
|
||||
# endpoint: <monitoring-uber-ip>:xxxxx
|
||||
# allowed ips: 10.0.0.2/32
|
||||
# latest handshake: X seconds ago
|
||||
# transfer: X B received, X B sent
|
||||
```
|
||||
|
||||
### Phase 4: Verify VPN Connection
|
||||
|
||||
```bash
|
||||
# On monitoring-uber
|
||||
ping 10.0.0.1
|
||||
|
||||
# Should respond
|
||||
# PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
|
||||
# 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=XX.X ms
|
||||
|
||||
# Check interface
|
||||
ip addr show wg0
|
||||
```
|
||||
|
||||
### Phase 5: Rebind Services to VPN IP
|
||||
|
||||
```bash
|
||||
# On monitoring-uber
|
||||
chmod +x /path/to/rebind-services-to-vpn.sh
|
||||
./rebind-services-to-vpn.sh
|
||||
|
||||
# This will update docker-compose-security.yml:
|
||||
# - Wazuh Dashboard: 0.0.0.0:443 → 10.0.0.2:443
|
||||
# - Dozzle: 0.0.0.0:8080 → 10.0.0.2:8080
|
||||
# - Beszel: 0.0.0.0:9090 → 10.0.0.2:9090
|
||||
# - S3/RustFS: 0.0.0.0:9000/9001 → 10.0.0.2:9000/9001
|
||||
# - Wazuh Manager: stays on 0.0.0.0:1514 (for agents)
|
||||
|
||||
# Restart services
|
||||
cd /home/ubuntu/docker
|
||||
docker compose -f docker-compose-security.yml down
|
||||
docker compose -f docker-compose-security.yml up -d
|
||||
|
||||
# Verify
|
||||
docker ps
|
||||
```
|
||||
|
||||
### Phase 6: Create Admin VPN Clients
|
||||
|
||||
```bash
|
||||
# Generate config for each admin
|
||||
chmod +x /path/to/wireguard-admin-client.sh
|
||||
|
||||
# Syntax: wireguard-admin-client.sh <name> <vps_ip> <vps_pubkey>
|
||||
./wireguard-admin-client.sh admin1 123.45.67.89 "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE="
|
||||
./wireguard-admin-client.sh admin2 123.45.67.89 "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE="
|
||||
|
||||
# Output: admin1.conf, admin2.conf
|
||||
|
||||
# For each admin, add to VPN server:
|
||||
ssh root@<VPN_SERVER_IP>
|
||||
wg set wg0 peer <ADMIN1_PUBKEY> allowed-ips 10.0.0.3/32
|
||||
wg set wg0 peer <ADMIN2_PUBKEY> allowed-ips 10.0.0.4/32
|
||||
|
||||
# Verify
|
||||
wg show
|
||||
```
|
||||
|
||||
### Phase 7: Admin Connection
|
||||
|
||||
Each admin:
|
||||
|
||||
1. Download WireGuard app: https://www.wireguard.com/install/
|
||||
2. Import config file (admin1.conf, admin2.conf, etc.)
|
||||
3. Connect to VPN
|
||||
4. Access services:
|
||||
- **Wazuh Dashboard**: https://10.0.0.2
|
||||
- **Dozzle**: http://10.0.0.2:8080
|
||||
- **Beszel**: http://10.0.0.2:9090
|
||||
- **S3/RustFS Console**: http://10.0.0.2:9001
|
||||
|
||||
## Firewall Rules Summary
|
||||
|
||||
### VPS VPN Server
|
||||
|
||||
| Protocol | Port | Source | Action |
|
||||
|----------|------|--------|--------|
|
||||
| UDP | 51820 | Any | ACCEPT (WireGuard) |
|
||||
| TCP | 22 | Any | ACCEPT (SSH) |
|
||||
| ICMP | echo-request | Any | ACCEPT |
|
||||
| Any | Any | Any | REJECT |
|
||||
|
||||
NAT masquerade enabled for VPN → Internet routing.
|
||||
|
||||
### monitoring-uber (185.103.167.138)
|
||||
|
||||
| Protocol | Port | Source | Action |
|
||||
|----------|------|--------|--------|
|
||||
| TCP | 1514 | 185.103.166.119 | ACCEPT (Prod Wazuh Agent) |
|
||||
| TCP | 1514 | 185.103.166.112 | ACCEPT (Pre-prod Wazuh Agent) |
|
||||
| UDP | 51820 | Any | ACCEPT (VPN) |
|
||||
| TCP | 443 | 10.0.0.0/24 | ACCEPT (Wazuh Dashboard — VPN) |
|
||||
| TCP | 8080 | 10.0.0.0/24 | ACCEPT (Dozzle — VPN) |
|
||||
| TCP | 9090 | 10.0.0.0/24 | ACCEPT (Beszel — VPN) |
|
||||
| TCP | 9000-9001 | 10.0.0.0/24 | ACCEPT (S3 — VPN) |
|
||||
| TCP | 22 | Any | ACCEPT (SSH) |
|
||||
| Any | Any | Any | DROP (Deny all) |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### VPN connection not establishing
|
||||
|
||||
```bash
|
||||
# On monitoring-uber
|
||||
systemctl status wg-quick@wg0
|
||||
journalctl -u wg-quick@wg0 -n 20
|
||||
|
||||
# Restart
|
||||
systemctl restart wg-quick@wg0
|
||||
```
|
||||
|
||||
### Can't access services over VPN
|
||||
|
||||
```bash
|
||||
# On monitoring-uber, check bindings
|
||||
netstat -tlnp | grep -E "(443|8080|9090|9000)"
|
||||
|
||||
# Should show 10.0.0.2 (not 0.0.0.0)
|
||||
```
|
||||
|
||||
### Wazuh agents can't connect
|
||||
|
||||
Make sure firewall allows 1514/tcp from prod/pre-prod:
|
||||
|
||||
```bash
|
||||
# On monitoring-uber
|
||||
iptables -L INPUT -v | grep 1514
|
||||
```
|
||||
|
||||
Should show rules for prod (185.103.166.119) and pre-prod (185.103.166.112).
|
||||
|
||||
## Persistence & Boot
|
||||
|
||||
All rules are saved with:
|
||||
- `iptables-save` → `/etc/iptables/rules.v4`
|
||||
- WireGuard: `systemctl enable wg-quick@wg0`
|
||||
|
||||
Both survive reboots.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Deploy VPS VPN Server
|
||||
- [ ] Run firewall + WireGuard setup on VPS
|
||||
- [ ] Get Server Public Key
|
||||
- [ ] Deploy firewall + WireGuard client on monitoring-uber
|
||||
- [ ] Add monitoring-uber peer on VPS
|
||||
- [ ] Verify VPN connection (ping 10.0.0.1)
|
||||
- [ ] Rebind services to VPN IP
|
||||
- [ ] Restart docker containers
|
||||
- [ ] Generate admin client configs
|
||||
- [ ] Add admin peers on VPS
|
||||
- [ ] Test admin VPN connection
|
||||
- [ ] Test service access (Wazuh, Dozzle, Beszel, S3)
|
||||
@@ -0,0 +1,10 @@
|
||||
[Interface]
|
||||
Address = 10.0.0.3/32
|
||||
PrivateKey = ePPTC7QXatWQd9qZWmAqlgd+IskVQ9/7rvwsfUtosEs=
|
||||
DNS = 8.8.8.8
|
||||
|
||||
[Peer]
|
||||
PublicKey = VQa6g1foaXhJgYWbwyJ9R/EAmmXg0nOnhPhbIIPLlmg=
|
||||
AllowedIPs = 10.0.0.0/24
|
||||
Endpoint = 45.150.111.158:51820
|
||||
PersistentKeepalive = 25
|
||||
Regular → Executable
+30
-94
@@ -1,5 +1,4 @@
|
||||
services:
|
||||
# ─── Dozzle ───────────────────────────────────────────────
|
||||
dozzle:
|
||||
image: amir20/dozzle:latest
|
||||
container_name: dozzle
|
||||
@@ -10,11 +9,10 @@ services:
|
||||
environment:
|
||||
DOZZLE_AUTH_PROVIDER: simple
|
||||
DOZZLE_AUTH_TTL: 48h
|
||||
DOZZLE_REMOTE_AGENT: "5.181.0.112:7007|demo-uber|VPS,185.234.9.102:7007|mln-uber|VPS"
|
||||
DOZZLE_REMOTE_AGENT: "185.103.166.112:7007|pre-prod-uber|VPS,185.103.166.119:7007|prod-uber|VPS"
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── Nginx ────────────────────────────────────────────────
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: monitoring_nginx
|
||||
@@ -29,10 +27,35 @@ services:
|
||||
depends_on:
|
||||
- dozzle
|
||||
- wazuh.dashboard
|
||||
- beszel
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── ClamAV Antivirus ────────────────────────────────────
|
||||
clamav:
|
||||
image: clamav/clamav:stable
|
||||
container_name: clamav
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- FRESHCLAM_CHECKS=24
|
||||
- CLAMD_SCAN_MAX_FILESIZE=100M
|
||||
volumes:
|
||||
- clamav_data:/var/lib/clamav
|
||||
- clamav_logs:/var/log/clamav
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── Beszel Hub ───────────────────────────────────────────
|
||||
beszel:
|
||||
image: henrygd/beszel:latest
|
||||
container_name: beszel
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- beszel_data:/beszel_data
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── Wazuh Manager ────────────────────────────────────────
|
||||
wazuh.manager:
|
||||
image: wazuh/wazuh-manager:4.14.5
|
||||
hostname: wazuh.manager
|
||||
@@ -131,99 +154,11 @@ services:
|
||||
- wazuh.manager
|
||||
networks:
|
||||
- monitoring_net
|
||||
rustfs_perm:
|
||||
image: alpine:latest
|
||||
container_name: rustfs_perm
|
||||
volumes:
|
||||
- /mnt/data:/data
|
||||
command: chown -R 1000:1000 /data
|
||||
rustfs:
|
||||
image: rustfs/rustfs:latest
|
||||
depends_on:
|
||||
rustfs_perm:
|
||||
condition: service_completed_successfully
|
||||
hostname: rustfs
|
||||
container_name: rustfs
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /mnt/data:/data
|
||||
environment:
|
||||
- RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY:-rustfsadmin}
|
||||
- RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY:-rustfsadmin}
|
||||
- RUSTFS_SERVER_DOMAINS=rustfs.uber-stup.club
|
||||
- RUSTFS_CONSOLE_ENABLE=true
|
||||
- RUSTFS_ADDRESS=:9000
|
||||
- RUSTFS_CONSOLE_ADDRESS=:9001
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── Xavia OTA — PostgreSQL ───────────────────────────────
|
||||
xavia_db:
|
||||
image: postgres:16-alpine
|
||||
container_name: xavia_db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=${XAVIA_POSTGRES_USER:-xavia}
|
||||
- POSTGRES_PASSWORD=${XAVIA_POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${XAVIA_POSTGRES_DB:-releases_db}
|
||||
volumes:
|
||||
- xavia_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
# ─── Xavia OTA ────────────────────────────────────────────
|
||||
xavia:
|
||||
image: xaviaio/xavia-ota:latest
|
||||
container_name: xavia
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- HOST=https://ota.uber-stup.club
|
||||
- BLOB_STORAGE_TYPE=local
|
||||
- DB_TYPE=postgres
|
||||
- ADMIN_PASSWORD=${XAVIA_ADMIN_PASSWORD}
|
||||
- UPLOAD_KEY=${XAVIA_UPLOAD_KEY}
|
||||
- PRIVATE_KEY_BASE_64=${XAVIA_PRIVATE_KEY_BASE_64}
|
||||
- POSTGRES_USER=${XAVIA_POSTGRES_USER:-xavia}
|
||||
- POSTGRES_PASSWORD=${XAVIA_POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${XAVIA_POSTGRES_DB:-releases_db}
|
||||
- POSTGRES_HOST=xavia_db
|
||||
- POSTGRES_PORT=5432
|
||||
volumes:
|
||||
- xavia_blobs:/app/blobs
|
||||
depends_on:
|
||||
- xavia_db
|
||||
networks:
|
||||
- monitoring_net
|
||||
# ─── Gitea ────────────────────────────────────────────────
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__database__DB_TYPE=sqlite3
|
||||
- GITEA__server__DOMAIN=${GITEA_DOMAIN:-gitea.uber-stup.club}
|
||||
- GITEA__server__ROOT_URL=https://${GITEA_DOMAIN:-gitea.uber-stup.club}
|
||||
- GITEA__server__HTTP_PORT=3000
|
||||
- GITEA__service__DISABLE_REGISTRATION=${GITEA_DISABLE_REGISTRATION:-true}
|
||||
- GITEA__service__REQUIRE_SIGNIN_VIEW=true
|
||||
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
|
||||
- GITEA__security__INTERNAL_TOKEN=${GITEA_INTERNAL_TOKEN}
|
||||
volumes:
|
||||
- gitea_data:/data
|
||||
networks:
|
||||
- monitoring_net
|
||||
|
||||
networks:
|
||||
monitoring_net:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
# Xavia
|
||||
xavia_db_data:
|
||||
xavia_blobs:
|
||||
# Wazuh
|
||||
wazuh_api_configuration:
|
||||
wazuh_etc:
|
||||
wazuh_logs:
|
||||
@@ -237,5 +172,6 @@ volumes:
|
||||
filebeat_var:
|
||||
wazuh_indexer_data:
|
||||
nginx_logs:
|
||||
# Gitea
|
||||
gitea_data:
|
||||
beszel_data:
|
||||
clamav_data:
|
||||
clamav_logs:
|
||||
Regular → Executable
+1
-1
@@ -2,5 +2,5 @@ users:
|
||||
admin:
|
||||
name: Admin
|
||||
email: admin@uber-stup.club
|
||||
password: $2a$11$/JnHCr3JYFZxuoY5COpjM.2MMJUYyKsFmgu/5qphIrbDLVz1qTCOC
|
||||
password: $2b$11$AOUC5QG2l8Ee0gUKIyZGKuHdL0iuvDa3C0bVAl2Gyt6Axx7.E/hHm
|
||||
roles: download
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# Firewall monitoring-uber (185.103.167.138)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# INBOUND:
|
||||
# • 1514/tcp FROM prod (185.103.166.119) — agents Wazuh
|
||||
# • 1514/tcp FROM pre-prod (185.103.166.112) — agents Wazuh
|
||||
# • 51820/udp — VPN WireGuard
|
||||
# • 10.0.0.0/24 (VPN admins) → 443, 8080, 8090, 9000, 9001
|
||||
# • SSH: BLOCKED from prod/pre-prod/s3 (security hardening)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# OUTBOUND:
|
||||
# • Tout (0.0.0.0/0) — Internet, updates, DNS
|
||||
# • VPN vers VPS
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
echo "[*] Configurant firewall monitoring-uber..."
|
||||
|
||||
# Flush des règles existantes
|
||||
iptables -F
|
||||
iptables -X
|
||||
iptables -t nat -F
|
||||
iptables -t nat -X
|
||||
iptables -t mangle -F
|
||||
iptables -t mangle -X
|
||||
|
||||
# Politique par défaut
|
||||
iptables -P INPUT DROP
|
||||
iptables -P FORWARD DROP
|
||||
iptables -P OUTPUT ACCEPT
|
||||
|
||||
# ─── INPUT ────────────────────────────────────────────────────────
|
||||
# Loopback (services internes)
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
|
||||
# Established/Related
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# SSH (administration locale, bloquer depuis prod/pre-prod/s3)
|
||||
iptables -A INPUT -p tcp --dport 22 -s 185.103.166.119 -j DROP # prod
|
||||
iptables -A INPUT -p tcp --dport 22 -s 185.103.166.112 -j DROP # pre-prod
|
||||
iptables -A INPUT -p tcp --dport 22 -s 80.96.58.164 -j DROP # s3
|
||||
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # allow from other sources
|
||||
|
||||
# ─── Agents Wazuh (prod + pre-prod) ────────────────────────────
|
||||
# Prod: 185.103.166.119
|
||||
iptables -A INPUT -p tcp --dport 1514 -s 185.103.166.119 -j ACCEPT
|
||||
|
||||
# Pre-prod: 185.103.166.112
|
||||
iptables -A INPUT -p tcp --dport 1514 -s 185.103.166.112 -j ACCEPT
|
||||
|
||||
# ─── VPN (WireGuard) ──────────────────────────────────────────
|
||||
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
|
||||
# ─── Services (accessibles via VPN seulement) ─────────────────
|
||||
# Admins via VPN: 10.0.0.0/24
|
||||
|
||||
# Wazuh Dashboard (443/https)
|
||||
iptables -A INPUT -p tcp --dport 443 -s 10.0.0.0/24 -j ACCEPT
|
||||
|
||||
# Dozzle (8080/http)
|
||||
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/24 -j ACCEPT
|
||||
|
||||
# Beszel (8090/http)
|
||||
iptables -A INPUT -p tcp --dport 8090 -s 10.0.0.0/24 -j ACCEPT
|
||||
|
||||
# S3/RustFS (9000/9001)
|
||||
iptables -A INPUT -p tcp --dport 9000 -s 10.0.0.0/24 -j ACCEPT
|
||||
iptables -A INPUT -p tcp --dport 9001 -s 10.0.0.0/24 -j ACCEPT
|
||||
|
||||
# ─── ICMP ─────────────────────────────────────────────────────
|
||||
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
|
||||
|
||||
# Reject le reste
|
||||
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
|
||||
|
||||
# ─── FORWARD ──────────────────────────────────────────────────
|
||||
# Blocker forward par défaut (services locaux, pas de transit)
|
||||
iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited
|
||||
|
||||
# ─── Sauvegarder ──────────────────────────────────────────────
|
||||
mkdir -p /etc/iptables
|
||||
iptables-save > /etc/iptables/rules.v4
|
||||
|
||||
echo "[✓] Firewall monitoring-uber configuré"
|
||||
echo ""
|
||||
echo "Règles appliquées (ALLOW) :"
|
||||
echo " • SSH 22/tcp — from admin IPs only (BLOCKED from prod/pre-prod/s3)"
|
||||
echo " • Wazuh 1514/tcp FROM prod (185.103.166.119) — agents Wazuh"
|
||||
echo " • Wazuh 1514/tcp FROM pre-prod (185.103.166.112) — agents Wazuh"
|
||||
echo " • VPN 51820/udp — WireGuard"
|
||||
echo " • Wazuh Dashboard 443/tcp FROM 10.0.0.0/24 (VPN)"
|
||||
echo " • Dozzle 8080/tcp FROM 10.0.0.0/24 (VPN)"
|
||||
echo " • Beszel 8090/tcp FROM 10.0.0.0/24 (VPN)"
|
||||
echo " • S3/RustFS 9000-9001/tcp FROM 10.0.0.0/24 (VPN)"
|
||||
echo " • OUTPUT (Internet/DNS)"
|
||||
echo ""
|
||||
echo "Règles appliquées (DENY) :"
|
||||
echo " • SSH 22/tcp FROM prod (185.103.166.119) — BLOCKED"
|
||||
echo " • SSH 22/tcp FROM pre-prod (185.103.166.112) — BLOCKED"
|
||||
echo " • SSH 22/tcp FROM s3 (80.96.58.164) — BLOCKED"
|
||||
echo " • All other INPUT/FORWARD — default DROP"
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# Firewall VPS VPN Server (WireGuard) — vpn-uber (45.150.111.158)
|
||||
# Allow: WireGuard (51820/udp), SSH (22/tcp), Beszel agent (10001/tcp from VPN)
|
||||
# Reject: tout le reste
|
||||
# NAT: masquerade pour routage VPN
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
echo "[*] Configurant firewall VPS VPN Server..."
|
||||
|
||||
# Flush des règles existantes
|
||||
iptables -F
|
||||
iptables -X
|
||||
iptables -t nat -F
|
||||
iptables -t nat -X
|
||||
iptables -t mangle -F
|
||||
iptables -t mangle -X
|
||||
|
||||
# Politique par défaut
|
||||
iptables -P INPUT DROP
|
||||
iptables -P FORWARD ACCEPT
|
||||
iptables -P OUTPUT ACCEPT
|
||||
|
||||
# ─── INPUT ────────────────────────────────────────────────────────
|
||||
# Loopback
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
|
||||
# Established/Related
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# SSH (administration)
|
||||
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
||||
|
||||
# WireGuard
|
||||
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
|
||||
# Beszel Agent (10001/tcp) — accessible depuis VPN uniquement
|
||||
iptables -A INPUT -p tcp --dport 10001 -s 10.0.0.0/24 -j ACCEPT
|
||||
|
||||
# ICMP (ping, MTU discovery)
|
||||
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
|
||||
|
||||
# Reject le reste
|
||||
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
|
||||
|
||||
# ─── FORWARD ──────────────────────────────────────────────────────
|
||||
# VPN ↔ Internet
|
||||
iptables -A FORWARD -i wg0 -j ACCEPT
|
||||
iptables -A FORWARD -o wg0 -j ACCEPT
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# ─── NAT ──────────────────────────────────────────────────────────
|
||||
# Masquerade pour routage VPN
|
||||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
# ─── Sauvegarder ──────────────────────────────────────────────────
|
||||
mkdir -p /etc/iptables
|
||||
iptables-save > /etc/iptables/rules.v4
|
||||
|
||||
# ─── IP Forwarding ────────────────────────────────────────────────
|
||||
sysctl -w net.ipv4.ip_forward=1
|
||||
grep -q "net.ipv4.ip_forward" /etc/sysctl.conf || echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
|
||||
|
||||
echo "[✓] Firewall VPS VPN Server configuré"
|
||||
echo ""
|
||||
echo "Règles appliquées (ALLOW) :"
|
||||
echo " • SSH 22/tcp — administration"
|
||||
echo " • WireGuard 51820/udp — VPN peers"
|
||||
echo " • Beszel Agent 10001/tcp FROM 10.0.0.0/24 — monitoring dashboard"
|
||||
echo " • ICMP (ping, MTU discovery)"
|
||||
echo ""
|
||||
echo "Configuration :"
|
||||
echo " • FORWARD ACCEPT (VPN ↔ Internet routing)"
|
||||
echo " • NAT masquerade activé (eth0)"
|
||||
echo " • IP forwarding activé (net.ipv4.ip_forward=1)"
|
||||
echo " • Default INPUT policy: DROP"
|
||||
@@ -0,0 +1,74 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
# Main HTTPS server
|
||||
server {
|
||||
listen 0.0.0.0:80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 0.0.0.0:443 ssl default_server;
|
||||
listen [::]:443 ssl default_server;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
# Wazuh (root)
|
||||
location / {
|
||||
proxy_pass https://wazuh.dashboard:5601/;
|
||||
proxy_ssl_verify off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host wazuh.dashboard:5601;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
}
|
||||
|
||||
# Dozzle
|
||||
location /dozzle {
|
||||
proxy_pass http://dozzle:8080;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_redirect ~^http://dozzle:8080/(.*)$ /dozzle/$1;
|
||||
proxy_redirect ~^/$/ /dozzle/;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
|
||||
# Beszel
|
||||
location /beszel {
|
||||
proxy_pass http://beszel:8090;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_redirect ~^http://beszel:8090/(.*)$ /beszel/$1;
|
||||
proxy_redirect ~^/$/ /beszel/;
|
||||
sub_filter 'href="/' 'href="/beszel/';
|
||||
sub_filter 'src="/' 'src="/beszel/';
|
||||
sub_filter 'url(/' 'url(/beszel/';
|
||||
sub_filter_once off;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
resolver 127.0.0.11 valid=10s ipv6=off;
|
||||
|
||||
upstream wazuh_backend {
|
||||
server wazuh.dashboard:5601;
|
||||
}
|
||||
|
||||
upstream dozzle_backend {
|
||||
server dozzle:8080;
|
||||
}
|
||||
|
||||
upstream beszel_backend {
|
||||
server beszel:8090;
|
||||
}
|
||||
|
||||
# Redirect HTTP to HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# Main HTTPS server
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
listen [::]:443 ssl default_server;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
# Root redirects to /wazuh
|
||||
location = / {
|
||||
return 301 https://$host/wazuh;
|
||||
}
|
||||
|
||||
# Wazuh
|
||||
location /wazuh/ {
|
||||
proxy_pass https://wazuh_backend/;
|
||||
proxy_ssl_verify off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# Dozzle
|
||||
location /dozzle/ {
|
||||
proxy_pass http://dozzle_backend/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
|
||||
# Beszel
|
||||
location /beszel/ {
|
||||
proxy_pass http://beszel_backend/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
}
|
||||
}
|
||||
Regular → Executable
+95
-107
@@ -5,6 +5,8 @@ events {
|
||||
}
|
||||
|
||||
http {
|
||||
resolver 127.0.0.11 valid=10s ipv6=off;
|
||||
|
||||
# Redirect HTTP -> HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
@@ -12,10 +14,70 @@ http {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# ── Default server (by IP + path) ────────────────────────
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
# Root → Wazuh Dashboard
|
||||
location = / {
|
||||
return 301 https://$host/wazuh;
|
||||
}
|
||||
|
||||
# /wazuh → Wazuh Dashboard
|
||||
location /wazuh/ {
|
||||
set $upstream https://wazuh.dashboard:5601;
|
||||
proxy_pass $upstream;
|
||||
proxy_ssl_verify off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
}
|
||||
|
||||
# /dozzle → Dozzle
|
||||
location /dozzle/ {
|
||||
set $upstream http://dozzle:8080;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
|
||||
# /beszel → Beszel
|
||||
location /beszel/ {
|
||||
set $upstream http://beszel:8090;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Dozzle ──────────────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name dozzle.uber-stup.club;
|
||||
server_name dozzle.demo-uber.xyz;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
@@ -26,7 +88,8 @@ http {
|
||||
error_log /var/log/nginx/dozzle_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://dozzle:8080;
|
||||
set $upstream http://dozzle:8080;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_buffering off;
|
||||
@@ -39,113 +102,10 @@ http {
|
||||
}
|
||||
}
|
||||
|
||||
# ── RustFS Console ──────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name rustfs.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/rustfs_access.log;
|
||||
error_log /var/log/nginx/rustfs_error.log;
|
||||
|
||||
# Console web (port 9001)
|
||||
location / {
|
||||
proxy_pass http://rustfs:9001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 500m;
|
||||
}
|
||||
}
|
||||
|
||||
# ── RustFS S3 API ───────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name s3.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/rustfs_s3_access.log;
|
||||
error_log /var/log/nginx/rustfs_s3_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://rustfs:9000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 2g;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Xavia OTA ───────────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ota.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/xavia_access.log;
|
||||
error_log /var/log/nginx/xavia_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://xavia:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 500m;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Gitea ───────────────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name gitea.uber-stup.club;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/gitea_access.log;
|
||||
error_log /var/log/nginx/gitea_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://gitea:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
client_max_body_size 100m;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Wazuh Dashboard ─────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name wazuh.uber-stup.club;
|
||||
server_name wazuh.demo-uber.xyz;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
@@ -156,7 +116,8 @@ http {
|
||||
error_log /var/log/nginx/wazuh_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass https://wazuh.dashboard:5601;
|
||||
set $upstream https://wazuh.dashboard:5601;
|
||||
proxy_pass $upstream;
|
||||
|
||||
proxy_ssl_verify off;
|
||||
|
||||
@@ -177,4 +138,31 @@ http {
|
||||
proxy_hide_header X-XSS-Protection;
|
||||
}
|
||||
}
|
||||
|
||||
# ── Beszel ──────────────────────────────────────────────
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name beszel.demo-uber.xyz;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
access_log /var/log/nginx/beszel_access.log;
|
||||
error_log /var/log/nginx/beszel_error.log;
|
||||
|
||||
location / {
|
||||
set $upstream http://beszel:8090;
|
||||
proxy_pass $upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# Rebind services to private VPN IP (10.0.0.2)
|
||||
# Services: Wazuh Dashboard, Dozzle, Beszel, S3/RustFS
|
||||
#
|
||||
# IMPORTANT:
|
||||
# - Wazuh Manager stays on 0.0.0.0:1514 (agents need access)
|
||||
# - Other services bind to 10.0.0.2 (VPN only)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
VPN_IP="10.0.0.2"
|
||||
COMPOSE_FILE="/home/ubuntu/docker/docker-compose-security.yml"
|
||||
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
echo "[!] File not found: $COMPOSE_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[*] Rebinding services to VPN IP ($VPN_IP)..."
|
||||
echo " Config: $COMPOSE_FILE"
|
||||
|
||||
# ─── Wazuh Dashboard (443) ────────────────────────────────────
|
||||
echo "[*] Updating Wazuh Dashboard (443)..."
|
||||
sed -i 's|0\.0\.0\.0:443:|'"$VPN_IP"':443:|g' "$COMPOSE_FILE"
|
||||
|
||||
# ─── Dozzle (8080) ────────────────────────────────────────────
|
||||
echo "[*] Updating Dozzle (8080)..."
|
||||
sed -i 's|0\.0\.0\.0:8080:|'"$VPN_IP"':8080:|g' "$COMPOSE_FILE"
|
||||
|
||||
# ─── Beszel (9090) ────────────────────────────────────────────
|
||||
echo "[*] Updating Beszel (9090)..."
|
||||
sed -i 's|0\.0\.0\.0:9090:|'"$VPN_IP"':9090:|g' "$COMPOSE_FILE"
|
||||
|
||||
# ─── RustFS / S3 (9000, 9001) ─────────────────────────────────
|
||||
echo "[*] Updating RustFS/S3 (9000, 9001)..."
|
||||
sed -i 's|0\.0\.0\.0:9000:|'"$VPN_IP"':9000:|g' "$COMPOSE_FILE"
|
||||
sed -i 's|0\.0\.0\.0:9001:|'"$VPN_IP"':9001:|g' "$COMPOSE_FILE"
|
||||
|
||||
# ─── Keep Wazuh Manager on 0.0.0.0:1514 ───────────────────────
|
||||
# (agents need public access)
|
||||
|
||||
echo ""
|
||||
echo "[✓] Services rebound to $VPN_IP"
|
||||
echo ""
|
||||
echo "Verify changes:"
|
||||
grep -n "ports:" -A 2 "$COMPOSE_FILE" | grep -E "(443|8080|9090|9000|9001|1514)" || true
|
||||
|
||||
echo ""
|
||||
echo "Services now listening on:"
|
||||
echo " • 0.0.0.0:1514 — Wazuh Manager (agents)"
|
||||
echo " • $VPN_IP:443 — Wazuh Dashboard (VPN only)"
|
||||
echo " • $VPN_IP:8080 — Dozzle (VPN only)"
|
||||
echo " • $VPN_IP:9090 — Beszel (VPN only)"
|
||||
echo " • $VPN_IP:9000/9001 — RustFS (VPN only)"
|
||||
echo ""
|
||||
echo "Next: Restart services"
|
||||
echo " cd /home/ubuntu/docker"
|
||||
echo " docker compose -f docker-compose-security.yml down"
|
||||
echo " docker compose -f docker-compose-security.yml up -d"
|
||||
Regular → Executable
Regular → Executable
@@ -0,0 +1,45 @@
|
||||
---
|
||||
_meta:
|
||||
type: "internalusers"
|
||||
config_version: 2
|
||||
|
||||
admin:
|
||||
hash: "$2b$12$lNbkFg7B3IN.BXwZHjztteTDd3hTIvT/kTJhRFqfUY/228Bw45POO"
|
||||
reserved: true
|
||||
backend_roles:
|
||||
- "admin"
|
||||
description: "Admin user"
|
||||
|
||||
kibanaserver:
|
||||
hash: "$2b$12$czi/zi7uht/K5.vcCvsXueFi6ot7GFwFfVBax7rCaNqBq1jhTOZ7u"
|
||||
reserved: true
|
||||
description: "Kibanaserver user"
|
||||
|
||||
kibanaro:
|
||||
hash: "$2b$12$lNbkFg7B3IN.BXwZHjztteTDd3hTIvT/kTJhRFqfUY/228Bw45POO"
|
||||
reserved: false
|
||||
backend_roles:
|
||||
- "kibanauser"
|
||||
- "readall"
|
||||
description: "Kibana read-only user"
|
||||
|
||||
logstash:
|
||||
hash: "$2b$12$lNbkFg7B3IN.BXwZHjztteTDd3hTIvT/kTJhRFqfUY/228Bw45POO"
|
||||
reserved: false
|
||||
backend_roles:
|
||||
- "logstash"
|
||||
description: "Logstash user"
|
||||
|
||||
readall:
|
||||
hash: "$2b$12$lNbkFg7B3IN.BXwZHjztteTDd3hTIvT/kTJhRFqfUY/228Bw45POO"
|
||||
reserved: false
|
||||
backend_roles:
|
||||
- "readall"
|
||||
description: "Readall user"
|
||||
|
||||
snapshotrestore:
|
||||
hash: "$2b$12$lNbkFg7B3IN.BXwZHjztteTDd3hTIvT/kTJhRFqfUY/228Bw45POO"
|
||||
reserved: false
|
||||
backend_roles:
|
||||
- "snapshotrestore"
|
||||
description: "Snapshotrestore user"
|
||||
Regular → Executable
+4
@@ -0,0 +1,4 @@
|
||||
<!-- ModSecurity decoder — non utilisé, remplacé par règles json+location -->
|
||||
<decoder name="waf-modsec-unused">
|
||||
<prematch>UNUSED_MODSEC_PLACEHOLDER_NEVER_MATCHES</prematch>
|
||||
</decoder>
|
||||
Regular → Executable
@@ -0,0 +1,23 @@
|
||||
<!-- ClamAV Log Monitoring -->
|
||||
<!-- Collect ClamAV logs for antivirus detection -->
|
||||
|
||||
<!-- ClamAV Main Log -->
|
||||
<localfile>
|
||||
<log_format>syslog</log_format>
|
||||
<location>/var/log/clamav/clamav.log</location>
|
||||
<source_type>log</source_type>
|
||||
</localfile>
|
||||
|
||||
<!-- ClamAV Freshclam (Signature Updates) Log -->
|
||||
<localfile>
|
||||
<log_format>syslog</log_format>
|
||||
<location>/var/log/clamav/freshclam.log</location>
|
||||
<source_type>log</source_type>
|
||||
</localfile>
|
||||
|
||||
<!-- ClamAV Alert Log (High Priority Detections) -->
|
||||
<localfile>
|
||||
<log_format>syslog</log_format>
|
||||
<location>/var/log/clamav/alert.log</location>
|
||||
<source_type>log</source_type>
|
||||
</localfile>
|
||||
Regular → Executable
+628
@@ -317,6 +317,338 @@
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- SSH brute-force (3 tentatives / 60s) → firewall-drop 1 heure -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100300</rules_id>
|
||||
<timeout>3600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- SSH scan de comptes (3 users inexistants / 60s) → firewall-drop 24 heures -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100301</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- Sudo brute-force (3 échecs / 5 min) → disable-account 2h + firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>disable-account</command>
|
||||
<location>local</location>
|
||||
<rules_id>100310</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100310</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP Top 10 — Active Response (ModSecurity)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- OWASP#3 SQL Injection (100220) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100220</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 SQL Injection brute-force (100290) → firewall-drop 24h + host-deny -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100290</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<active-response>
|
||||
<command>host-deny</command>
|
||||
<location>local</location>
|
||||
<rules_id>100290</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 LDAP Injection (100221) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100221</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection (100222) → firewall-drop 24h + host-deny permanent -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100222</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<active-response>
|
||||
<command>host-deny</command>
|
||||
<location>local</location>
|
||||
<rules_id>100222</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection brute-force CRITICAL (100292) → permanent ban -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100292</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<active-response>
|
||||
<command>host-deny</command>
|
||||
<location>local</location>
|
||||
<rules_id>100292</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 PHP/Java Injection (100223, 100224) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100223,100224</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#6 RCE / Exploit attempts (100230) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100230</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS attacks (100240) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100240</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS brute-force (100291) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100291</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 HTTP Header Injection (100241) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100241</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal / LFI (100250) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100250</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal brute-force (100293) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100293</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Remote File Inclusion (100251) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100251</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Restricted File Access (100252) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100252</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#8 XXE (XML External Entity) (100260) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100260</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#9 Scanner Detection (100270) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100270</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP SSRF (100280) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100280</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP File Upload (100281) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100281</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP — Remontées (non-bloquées, anomaly scoring)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- OWASP#3 SQLi remontée (100320) → firewall-drop 2h (soft) -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100320</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 SQLi anomaly (100394) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100394</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection remontée (100321) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100321</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection anomaly CRITICAL (100396) → permanent ban -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100396</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 LDAP/PHP/Java remontées (100322, 100323) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100322,100323</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#6 RCE/Exploit remontée (100330) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100330</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS remontée (100340) → firewall-drop 1h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100340</rules_id>
|
||||
<timeout>3600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS anomaly (100395) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100395</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 Header Injection remontée (100341) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100341</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal remontée (100350) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100350</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 RFI remontée (100351) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100351</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 File Access remontée (100352) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100352</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#8 XXE remontée (100360) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100360</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#9 Scanner remontée (100370) → firewall-drop 30min -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100370</rules_id>
|
||||
<timeout>1800</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP SSRF remontée (100380) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100380</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP File Upload remontée (100381) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>local</location>
|
||||
<rules_id>100381</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<active-response>
|
||||
<disabled>no</disabled>
|
||||
<command>host-deny</command>
|
||||
@@ -396,6 +728,302 @@
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- SSH brute-force (3 tentatives / 60s) → firewall-drop 1 heure sur tous les agents -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100300</rules_id>
|
||||
<timeout>3600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- SSH scan de comptes → firewall-drop 24 heures sur tous les agents -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100301</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP Top 10 — Active Response (ModSecurity - location=all)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- OWASP#3 SQLi (100220) → firewall-drop 6h (tous agents) -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100220</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 SQLi brute-force (100290) → firewall-drop 24h (tous agents) -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100290</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 LDAP (100221) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100221</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection (100222) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100222</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection CRITICAL (100292) → permanent ban -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100292</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 PHP/Java (100223, 100224) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100223,100224</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#6 RCE/Exploit (100230) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100230</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS (100240) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100240</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS brute-force (100291) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100291</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 Header Injection (100241) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100241</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal/LFI (100250) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100250</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal brute-force (100293) → firewall-drop 24h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100293</rules_id>
|
||||
<timeout>86400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 RFI (100251) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100251</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 File Access (100252) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100252</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#8 XXE (100260) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100260</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#9 Scanner (100270) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100270</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP SSRF (100280) → firewall-drop 12h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100280</rules_id>
|
||||
<timeout>43200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP File Upload (100281) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100281</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP — Remontées (location=all)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- OWASP#3 SQLi remontée (100320) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100320</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 SQLi anomaly (100394) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100394</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection remontée (100321) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100321</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 Command Injection CRITICAL (100396) → permanent -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100396</rules_id>
|
||||
<timeout>0</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#3 LDAP/PHP/Java (100322, 100323) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100322,100323</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#6 RCE/Exploit (100330) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100330</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS remontée (100340) → firewall-drop 1h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100340</rules_id>
|
||||
<timeout>3600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 XSS anomaly (100395) → firewall-drop 6h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100395</rules_id>
|
||||
<timeout>21600</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#7 Header Injection (100341) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100341</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 Path Traversal (100350) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100350</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 RFI (100351) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100351</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#1 File Access (100352) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100352</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#8 XXE (100360) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100360</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP#9 Scanner (100370) → firewall-drop 30min -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100370</rules_id>
|
||||
<timeout>1800</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP SSRF (100380) → firewall-drop 4h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100380</rules_id>
|
||||
<timeout>14400</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- OWASP File Upload (100381) → firewall-drop 2h -->
|
||||
<active-response>
|
||||
<command>firewall-drop</command>
|
||||
<location>all</location>
|
||||
<rules_id>100381</rules_id>
|
||||
<timeout>7200</timeout>
|
||||
</active-response>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
LOG ANALYSIS (commandes système)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<group name="clamav">
|
||||
<rule id="100500" level="0">
|
||||
<decoded_as>syslog</decoded_as>
|
||||
<program_name>clam</program_name>
|
||||
<description>ClamAV message grouping</description>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Malware Detections (Critical) -->
|
||||
<rule id="100501" level="15">
|
||||
<parent>100500</parent>
|
||||
<regex>FOUND|Infected|detected</regex>
|
||||
<description>ClamAV: Malware detected - $(var malware_name)</description>
|
||||
<group>malware,clamav,infection</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Trojan/PUA Detection -->
|
||||
<rule id="100502" level="12">
|
||||
<parent>100500</parent>
|
||||
<regex>Trojan|PUA|unwanted|grayware</regex>
|
||||
<description>ClamAV: Potentially Unwanted Application detected</description>
|
||||
<group>malware,clamav,pua</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Virus Detection -->
|
||||
<rule id="100503" level="15">
|
||||
<parent>100500</parent>
|
||||
<regex>\.Virus\.|\.Win\.|\.Linux\.|\.Worm\.|\.Backdoor</regex>
|
||||
<description>ClamAV: Virus detected - High severity</description>
|
||||
<group>malware,clamav,virus</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Ransomware Detection -->
|
||||
<rule id="100504" level="15">
|
||||
<parent>100500</parent>
|
||||
<regex>Ransomware|Encrypted|Cryptolocker|BadRabbit|WannaCry</regex>
|
||||
<description>ClamAV: Ransomware detected</description>
|
||||
<group>malware,clamav,ransomware</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Signature Update Success -->
|
||||
<rule id="100505" level="3">
|
||||
<parent>100500</parent>
|
||||
<program_name>freshclam</program_name>
|
||||
<regex>ClamAV update completed successfully|updated</regex>
|
||||
<description>ClamAV: Signature database updated successfully</description>
|
||||
<group>clamav,updates</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Signature Update Failed -->
|
||||
<rule id="100506" level="10">
|
||||
<parent>100500</parent>
|
||||
<program_name>freshclam</program_name>
|
||||
<regex>ERROR|Failed|error downloading|connection failed|timeout</regex>
|
||||
<description>ClamAV: Signature update failed</description>
|
||||
<group>clamav,updates,error</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Daemon Error -->
|
||||
<rule id="100507" level="8">
|
||||
<parent>100500</parent>
|
||||
<program_name>clamd</program_name>
|
||||
<regex>ERROR|error|CRITICAL</regex>
|
||||
<description>ClamAV: Daemon error</description>
|
||||
<group>clamav,error</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Scanner Started -->
|
||||
<rule id="100508" level="3">
|
||||
<parent>100500</parent>
|
||||
<regex>Scanning started|initializing scanner</regex>
|
||||
<description>ClamAV: Scanning started</description>
|
||||
<group>clamav,scanning</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Scanner Completed -->
|
||||
<rule id="100509" level="3">
|
||||
<parent>100500</parent>
|
||||
<regex>Scanning finished|scan completed</regex>
|
||||
<description>ClamAV: Scanning completed</description>
|
||||
<group>clamav,scanning</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Corrupted Files Alert -->
|
||||
<rule id="100510" level="8">
|
||||
<parent>100500</parent>
|
||||
<regex>corrupted|corrupt file|damaged|unreadable</regex>
|
||||
<description>ClamAV: Corrupted file detected</description>
|
||||
<group>clamav,corruption</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Quarantine Actions -->
|
||||
<rule id="100511" level="10">
|
||||
<parent>100500</parent>
|
||||
<regex>quarantine|moved|removed|deleted|archived</regex>
|
||||
<description>ClamAV: File quarantined/removed</description>
|
||||
<group>clamav,quarantine,action</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Scan Statistics -->
|
||||
<rule id="100512" level="3">
|
||||
<parent>100500</parent>
|
||||
<regex>infects|infected files|detected</regex>
|
||||
<description>ClamAV: Scan statistics</description>
|
||||
<group>clamav,statistics</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Permission Denied -->
|
||||
<rule id="100513" level="6">
|
||||
<parent>100500</parent>
|
||||
<regex>Permission denied|access denied|unable to scan</regex>
|
||||
<description>ClamAV: Permission denied when scanning file</description>
|
||||
<group>clamav,access</group>
|
||||
</rule>
|
||||
|
||||
<!-- ClamAV Database Problem -->
|
||||
<rule id="100514" level="10">
|
||||
<parent>100500</parent>
|
||||
<regex>database error|bad database|corrupt database|outdated database</regex>
|
||||
<description>ClamAV: Database problem detected</description>
|
||||
<group>clamav,database,error</group>
|
||||
</rule>
|
||||
|
||||
<!-- Aggregate: Multiple Malware Detections in Short Time -->
|
||||
<rule id="100515" level="16">
|
||||
<parent>100501</parent>
|
||||
<frequency>3</timeframe>3600</frequency>
|
||||
<same_source_ip />
|
||||
<description>ClamAV: Multiple malware detections in short time - possible outbreak</description>
|
||||
<group>malware,clamav,outbreak</group>
|
||||
</rule>
|
||||
|
||||
<!-- Aggregate: Ransomware Alert with Infection -->
|
||||
<rule id="100516" level="16">
|
||||
<if_matched_sid>100501</if_matched_sid>
|
||||
<if_matched_sid>100504</if_matched_sid>
|
||||
<same_source_ip />
|
||||
<timeframe>300</timeframe>
|
||||
<description>ClamAV: Ransomware and virus detected together - critical threat</description>
|
||||
<group>malware,clamav,ransomware,critical</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
Active-Response — règles de détection précoce pour l'AR graduée
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Ces règles viennent EN PLUS des bans existants sur les règles natives
|
||||
(5710, 5716, etc.) pour produire des alertes clairement labellisées
|
||||
et déclencher des AR spécifiques par scénario d'attaque.
|
||||
-->
|
||||
|
||||
<!-- ─── SSH ─────────────────────────────────────────────────────────── -->
|
||||
<group name="syslog,sshd,authentication_failures,">
|
||||
|
||||
<!-- 3 mots de passe incorrects en 60s depuis la même IP
|
||||
Note : le ban PERMANENT sur 5716 (1ère tentative) reste actif en parallèle.
|
||||
Cette règle produit une alerte "brute-force" explicite + AR temporaire graduée. -->
|
||||
<rule id="100300" level="10" frequency="3" timeframe="60">
|
||||
<if_matched_sid>5716</if_matched_sid>
|
||||
<same_source_ip />
|
||||
<description>SSH: brute-force — 3 mots de passe faux en 60s depuis $(srcip)</description>
|
||||
<group>authentication_failures,ssh_brute,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 3 users inexistants en 60s depuis la même IP → scan de comptes -->
|
||||
<rule id="100301" level="12" frequency="3" timeframe="60">
|
||||
<if_matched_sid>5710</if_matched_sid>
|
||||
<same_source_ip />
|
||||
<description>SSH: scan de comptes — 3 users inexistants en 60s depuis $(srcip)</description>
|
||||
<group>authentication_failures,ssh_scan,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
<!-- ─── SUDO ─────────────────────────────────────────────────────────── -->
|
||||
<group name="syslog,sudo,authentication_failures,">
|
||||
|
||||
<!-- 3 échecs sudo en 5 min par le même utilisateur.
|
||||
Couverture non présente dans les règles natives → AR disable-account. -->
|
||||
<rule id="100310" level="10" frequency="3" timeframe="300">
|
||||
<if_matched_sid>5401</if_matched_sid>
|
||||
<same_user />
|
||||
<description>Sudo: 3 échecs d'auth en 5 min — tentative d'escalade de privilèges</description>
|
||||
<group>authentication_failures,sudo_brute,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
Règles ModSecurity — WAF container (gestion-waf)
|
||||
Le decoder json intégré parse les events — on utilise <field> + <location>.
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<group name="web,modsecurity,">
|
||||
|
||||
<!-- Base : tout event JSON provenant du log ModSecurity -->
|
||||
<rule id="100100" level="3">
|
||||
<decoded_as>json</decoded_as>
|
||||
<location>modsec_audit.log</location>
|
||||
<field name="transaction.client_ip">\.+</field>
|
||||
<description>ModSecurity: WAF event capturé</description>
|
||||
<group>web,modsecurity,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Accès bloqué (HTTP 403) -->
|
||||
<rule id="100102" level="10">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.response.http_code">^403$</field>
|
||||
<description>ModSecurity: accès bloqué (403) — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>web,modsecurity,attack,blocked,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Trafic passant avec règle déclenchée (warning, anomaly scoring) -->
|
||||
<rule id="100101" level="6">
|
||||
<if_sid>100100</if_sid>
|
||||
<description>ModSecurity: règle WAF déclenchée (non bloqué) — $(transaction.client_ip)</description>
|
||||
<group>web,modsecurity,attack,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Blocages répétés depuis la même IP -->
|
||||
<rule id="100103" level="12" frequency="5" timeframe="60">
|
||||
<if_matched_sid>100102</if_matched_sid>
|
||||
<description>ModSecurity: blocages répétés — possible scan ou attaque soutenue</description>
|
||||
<group>web,modsecurity,attack,blocked,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
@@ -0,0 +1,113 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
Suppression des alertes SCA (Security Configuration Assessment)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Les scans CIS benchmark génèrent des centaines d'alertes par cycle.
|
||||
Toutes passées à level 0 — les résultats restent consultables dans
|
||||
l'onglet SCA du dashboard sans polluer le flux d'alertes.
|
||||
-->
|
||||
|
||||
<group name="sca,">
|
||||
|
||||
<!-- ─── Résumés de scan (score < 90%, <80%, <50%, <30%) ─────────── -->
|
||||
<rule id="19001" level="0" overwrite="yes">
|
||||
<if_sid>19000</if_sid>
|
||||
<field name="sca.type">^summary</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA summary — supprimé (voir onglet SCA du dashboard).</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19002" level="0" overwrite="yes">
|
||||
<if_sid>19001</if_sid>
|
||||
<field name="sca.score">^8\d</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA summary: score < 90% — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19003" level="0" overwrite="yes">
|
||||
<if_sid>19001</if_sid>
|
||||
<field name="sca.score">^7\d|^6\d|^5\d</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA summary: score < 80% — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19004" level="0" overwrite="yes">
|
||||
<if_sid>19001</if_sid>
|
||||
<field name="sca.score">^4\d|^3\d</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA summary: score < 50% — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19005" level="0" overwrite="yes">
|
||||
<if_sid>19001</if_sid>
|
||||
<field name="sca.score">^2\d|^1\d$|^\d$</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA summary: score < 30% — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<!-- ─── Checks individuels (passed / failed / not applicable) ────── -->
|
||||
<rule id="19007" level="0" overwrite="yes">
|
||||
<if_sid>19006</if_sid>
|
||||
<field name="sca.check.result">^failed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA check failed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19008" level="0" overwrite="yes">
|
||||
<if_sid>19006</if_sid>
|
||||
<field name="sca.check.result">^passed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA check passed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19009" level="0" overwrite="yes">
|
||||
<if_sid>19006</if_sid>
|
||||
<field name="sca.check.result">^not applicable</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA check not applicable — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<!-- ─── Changements de statut entre scans ───────────────────────── -->
|
||||
<rule id="19010" level="0" overwrite="yes">
|
||||
<if_sid>19008</if_sid>
|
||||
<field name="sca.check.previous_result">^failed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: failed → passed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19011" level="0" overwrite="yes">
|
||||
<if_sid>19007</if_sid>
|
||||
<field name="sca.check.previous_result">^passed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: passed → failed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19012" level="0" overwrite="yes">
|
||||
<if_sid>19009</if_sid>
|
||||
<field name="sca.check.previous_result">^passed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: passed → not applicable — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19013" level="0" overwrite="yes">
|
||||
<if_sid>19009</if_sid>
|
||||
<field name="sca.check.previous_result">^failed</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: failed → not applicable — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19014" level="0" overwrite="yes">
|
||||
<if_sid>19007</if_sid>
|
||||
<field name="sca.check.previous_result">^not applicable</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: not applicable → failed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
<rule id="19015" level="0" overwrite="yes">
|
||||
<if_sid>19008</if_sid>
|
||||
<field name="sca.check.previous_result">^not applicable</field>
|
||||
<options>no_full_log</options>
|
||||
<description>SCA: not applicable → passed — supprimé.</description>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
Regular → Executable
+11
-12
@@ -107,28 +107,27 @@
|
||||
</group>
|
||||
|
||||
<!-- ─── IOC Suricata/Windows — parents exclus (0475, 0580, 0840) ──────────
|
||||
Ces règles dans 0999-malicious-ioc-rules.xml ont des if_sid qui
|
||||
pointent vers des fichiers exclus. Sans overwrite, analysisd log des
|
||||
warnings (7617)/(7619) au démarrage. On les remplace par des règles
|
||||
level 0 pour silence les warnings sans affecter la détection IOC SSH. -->
|
||||
IMPORTANT: <match>PLACEHOLDER_NEVER_MATCHES</match> au lieu de <match>.</match>
|
||||
pour éviter que ces rules catch-all bloquent l'évaluation des rules avec
|
||||
un ID plus élevé (first-match semantics dans Wazuh). -->
|
||||
<group name="ids,">
|
||||
<rule id="99917" level="0" overwrite="yes">
|
||||
<match>.</match>
|
||||
<description>Suricata: malicious domain — non applicable (pas d'agent Suricata).</description>
|
||||
<match>WAZUH_PLACEHOLDER_SURICATA_NEVER_MATCHES</match>
|
||||
<description>Suricata: malicious domain — overwrite placeholder (non applicable).</description>
|
||||
</rule>
|
||||
<rule id="99918" level="0" overwrite="yes">
|
||||
<match>.</match>
|
||||
<description>Suricata: malicious domain DNS — non applicable.</description>
|
||||
<match>WAZUH_PLACEHOLDER_SURICATA_DNS_NEVER_MATCHES</match>
|
||||
<description>Suricata: malicious domain DNS — overwrite placeholder (non applicable).</description>
|
||||
</rule>
|
||||
</group>
|
||||
|
||||
<group name="windows,windows_security,">
|
||||
<rule id="99919" level="0" overwrite="yes">
|
||||
<match>.</match>
|
||||
<description>Windows: failed logon malicious IP — non applicable (pas d'agent Windows).</description>
|
||||
<match>WAZUH_PLACEHOLDER_WINDOWS_FAILED_NEVER_MATCHES</match>
|
||||
<description>Windows: failed logon malicious IP — overwrite placeholder (non applicable).</description>
|
||||
</rule>
|
||||
<rule id="99920" level="0" overwrite="yes">
|
||||
<match>.</match>
|
||||
<description>Windows: successful logon malicious IP — non applicable.</description>
|
||||
<match>WAZUH_PLACEHOLDER_WINDOWS_SUCCESS_NEVER_MATCHES</match>
|
||||
<description>Windows: successful logon malicious IP — overwrite placeholder (non applicable).</description>
|
||||
</rule>
|
||||
</group>
|
||||
@@ -0,0 +1,352 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
ModSecurity OWASP Top 10 — Règles granulaires
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Détection des attaques OWASP Top 10 via ModSecurity + active-response
|
||||
|
||||
Correspondances CRS (OWASP ModSec Core Rule Set) :
|
||||
• 941xxx : XSS (Cross-Site Scripting)
|
||||
• 942xxx : SQL Injection, LDAP Injection
|
||||
• 943xxx : XXE (XML External Entity)
|
||||
• 930xxx : Path Traversal, RFI (Remote File Inclusion)
|
||||
• 932xxx : Remote Command Execution
|
||||
• 933xxx : PHP Injection
|
||||
• 934xxx : Java Injection
|
||||
• 950xxx : Exploit attempts
|
||||
• 951xxx : Regex DoS
|
||||
• 952xxx : Restricted File Access
|
||||
• 953xxx : Insecure File Upload
|
||||
• 954xxx : Proxy Abuse
|
||||
• 955xxx : Malicious HTTP Headers
|
||||
• 970xxx : SSRF / Open Redirect
|
||||
-->
|
||||
|
||||
<group name="web,modsecurity,owasp,">
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
RÈGLES BLOQUÉES (100102 - HTTP 403)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #3 : INJECTION (SQLi, Command Injection, LDAP, etc.)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- SQL Injection BLOQUÉE (942xx) -->
|
||||
<rule id="100220" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">942[0-9]</field>
|
||||
<description>OWASP#3 SQL Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,sql_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- LDAP Injection (942xx - LDAP patterns) -->
|
||||
<rule id="100221" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">942[0-9].*LDAP\|ldap_filter</field>
|
||||
<description>OWASP#3 LDAP Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,ldap_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Command Injection / OS Command Execution (932xx) -->
|
||||
<rule id="100222" level="14">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">932[0-9]</field>
|
||||
<description>OWASP#3 Remote Command Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,command_injection,rce,</group>
|
||||
</rule>
|
||||
|
||||
<!-- PHP Injection (933xx) -->
|
||||
<rule id="100223" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">933[0-9]</field>
|
||||
<description>OWASP#3 PHP Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,php_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Java Injection (934xx) -->
|
||||
<rule id="100224" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">934[0-9]</field>
|
||||
<description>OWASP#3 Java Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,java_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #6 : VULNERABLE & OUTDATED COMPONENTS (Exploit attempts)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Remote Code Execution attempts (930xx, 950xx) -->
|
||||
<rule id="100230" level="14">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9]\|950[0-9]</field>
|
||||
<description>OWASP#6 RCE / Exploit attempt bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_vulnerable_components,rce,exploit,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #7 : AUTHENTICATION & SESSION (XSS/CSRF/Session Theft)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Cross-Site Scripting (941xx) -->
|
||||
<rule id="100240" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">941[0-9]</field>
|
||||
<description>OWASP#7 XSS attack bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_auth,xss,session_theft,</group>
|
||||
</rule>
|
||||
|
||||
<!-- HTTP Response Splitting / Header Injection (955xx) -->
|
||||
<rule id="100241" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">955[0-9]</field>
|
||||
<description>OWASP#7 HTTP Header Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_auth,header_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #1 : BROKEN ACCESS CONTROL (Path Traversal, Bypass)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Path Traversal / Local File Inclusion (930xx - LFI patterns) -->
|
||||
<rule id="100250" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9].*\(path\|traversal\|lfi\)</field>
|
||||
<description>OWASP#1 Path Traversal / LFI bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,lfi,path_traversal,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Remote File Inclusion (930xx - RFI patterns) -->
|
||||
<rule id="100251" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9].*\(rfi\|remote\|include\)</field>
|
||||
<description>OWASP#1 Remote File Inclusion bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,rfi,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Restricted File Access (952xx) -->
|
||||
<rule id="100252" level="11">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">952[0-9]</field>
|
||||
<description>OWASP#1 Unauthorized File Access bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,file_access,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #8 : SOFTWARE & DATA INTEGRITY (XXE, Deserialization)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- XML External Entity (XXE) (943xx) -->
|
||||
<rule id="100260" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">943[0-9]</field>
|
||||
<description>OWASP#8 XML External Entity (XXE) bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_data_integrity,xxe,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
OWASP #9 : LOGGING & MONITORING FAILURES (Scanner Detection)
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Web Application Scanner Detection (951xx, 954xx) -->
|
||||
<rule id="100270" level="10">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">951[0-9]\|954[0-9]</field>
|
||||
<description>OWASP#9 Web Scanner / Bot detected — $(transaction.client_ip)</description>
|
||||
<group>owasp_monitoring,scanner_detection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
AUTRES : SSRF, Open Redirect, Malicious File Upload
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Server-Side Request Forgery (970xx, 971xx) -->
|
||||
<rule id="100280" level="13">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">970[0-9]\|971[0-9]</field>
|
||||
<description>OWASP Server-Side Request Forgery (SSRF) bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_misc,ssrf,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Insecure File Upload (953xx) -->
|
||||
<rule id="100281" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">953[0-9]</field>
|
||||
<description>OWASP Insecure File Upload bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_misc,file_upload,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
FRÉQUENCE & PATTERNS RÉPÉTÉS
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- SQLi répétées (brute-force injection) -->
|
||||
<rule id="100290" level="14" frequency="3" timeframe="60">
|
||||
<if_matched_sid>100220</if_matched_sid>
|
||||
<description>OWASP#3 SQL Injection brute-force — $(transaction.client_ip) tentatives répétées</description>
|
||||
<group>owasp_injection,sql_injection,brute_force,</group>
|
||||
</rule>
|
||||
|
||||
<!-- XSS répétées (scanner ou attaque soutenue) -->
|
||||
<rule id="100291" level="13" frequency="5" timeframe="120">
|
||||
<if_matched_sid>100240</if_matched_sid>
|
||||
<description>OWASP#7 XSS attack pattern — $(transaction.client_ip) attaque soutenue</description>
|
||||
<group>owasp_auth,xss,</group>
|
||||
</rule>
|
||||
|
||||
<!-- RCE attempts répétées (critiques) -->
|
||||
<rule id="100292" level="15" frequency="2" timeframe="60">
|
||||
<if_matched_sid>100222</if_matched_sid>
|
||||
<description>OWASP#3 Command Injection attempts — $(transaction.client_ip) CRITICAL</description>
|
||||
<group>owasp_injection,command_injection,critical,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Path Traversal brute-force -->
|
||||
<rule id="100293" level="12" frequency="4" timeframe="180">
|
||||
<if_matched_sid>100250</if_matched_sid>
|
||||
<description>OWASP#1 Path Traversal brute-force — $(transaction.client_ip)</description>
|
||||
<group>owasp_access_control,lfi,brute_force,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
RÈGLES REMONTÉES (100100 - tous les events, bloqués ou non)
|
||||
Patterns OWASP détectés sans être bloqués
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- OWASP#3 SQLi remontée (942xx - non bloquée, anomaly scoring) -->
|
||||
<rule id="100320" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">942[0-9]</field>
|
||||
<description>OWASP#3 SQL Injection attempt (anomaly scoring) — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,sql_injection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#3 Command Injection remontée (932xx - non bloquée) -->
|
||||
<rule id="100321" level="10">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">932[0-9]</field>
|
||||
<description>OWASP#3 Command Injection attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,command_injection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#3 LDAP Injection remontée (942xx LDAP) -->
|
||||
<rule id="100322" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">942[0-9].*LDAP\|ldap_filter</field>
|
||||
<description>OWASP#3 LDAP Injection attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,ldap_injection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#3 PHP/Java Injection remontée (933xx, 934xx) -->
|
||||
<rule id="100323" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">933[0-9]\|934[0-9]</field>
|
||||
<description>OWASP#3 Code Injection attempt (PHP/Java) — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_injection,code_injection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#6 RCE/Exploit remontée (930xx, 950xx - non bloquée) -->
|
||||
<rule id="100330" level="11">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9]\|950[0-9]</field>
|
||||
<description>OWASP#6 RCE / Exploit attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_vulnerable_components,rce,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#7 XSS remontée (941xx - non bloquée) -->
|
||||
<rule id="100340" level="8">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">941[0-9]</field>
|
||||
<description>OWASP#7 XSS attempt (anomaly scoring) — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_auth,xss,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#7 Header Injection remontée (955xx) -->
|
||||
<rule id="100341" level="8">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">955[0-9]</field>
|
||||
<description>OWASP#7 HTTP Header Injection attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_auth,header_injection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#1 Path Traversal remontée (930xx LFI patterns) -->
|
||||
<rule id="100350" level="8">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9].*\(path\|traversal\|lfi\)</field>
|
||||
<description>OWASP#1 Path Traversal attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,lfi,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#1 RFI remontée (930xx RFI patterns) -->
|
||||
<rule id="100351" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">930[0-9].*\(rfi\|remote\|include\)</field>
|
||||
<description>OWASP#1 Remote File Inclusion attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,rfi,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#1 File Access remontée (952xx) -->
|
||||
<rule id="100352" level="8">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">952[0-9]</field>
|
||||
<description>OWASP#1 Unauthorized File Access attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_access_control,file_access,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#8 XXE remontée (943xx) -->
|
||||
<rule id="100360" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">943[0-9]</field>
|
||||
<description>OWASP#8 XML External Entity (XXE) attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_data_integrity,xxe,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP#9 Scanner remontée (951xx, 954xx) -->
|
||||
<rule id="100370" level="6">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">951[0-9]\|954[0-9]</field>
|
||||
<description>OWASP#9 Web Scanner / Bot detected — $(transaction.client_ip)</description>
|
||||
<group>owasp_monitoring,scanner_detection,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP SSRF remontée (970xx, 971xx) -->
|
||||
<rule id="100380" level="9">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">970[0-9]\|971[0-9]</field>
|
||||
<description>OWASP Server-Side Request Forgery (SSRF) attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_misc,ssrf,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- OWASP File Upload remontée (953xx) -->
|
||||
<rule id="100381" level="8">
|
||||
<if_sid>100100</if_sid>
|
||||
<field name="transaction.messages.message">953[0-9]</field>
|
||||
<description>OWASP Insecure File Upload attempt — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>owasp_misc,file_upload,warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
FRÉQUENCE — Attaques par anomaly scoring répétées
|
||||
═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- SQLi anomaly scoring répétée -->
|
||||
<rule id="100394" level="10" frequency="5" timeframe="300">
|
||||
<if_matched_sid>100320</if_matched_sid>
|
||||
<description>OWASP#3 SQL Injection anomaly scoring — $(transaction.client_ip) tentatives répétées</description>
|
||||
<group>owasp_injection,sql_injection,anomaly,</group>
|
||||
</rule>
|
||||
|
||||
<!-- XSS anomaly scoring répétée -->
|
||||
<rule id="100395" level="10" frequency="8" timeframe="300">
|
||||
<if_matched_sid>100340</if_matched_sid>
|
||||
<description>OWASP#7 XSS anomaly scoring — $(transaction.client_ip) attaque soutenue</description>
|
||||
<group>owasp_auth,xss,anomaly,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Command Injection tentatives répétées -->
|
||||
<rule id="100396" level="12" frequency="2" timeframe="60">
|
||||
<if_matched_sid>100321</if_matched_sid>
|
||||
<description>OWASP#3 Command Injection attempts — $(transaction.client_ip) CRITICAL</description>
|
||||
<group>owasp_injection,command_injection,anomaly,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
@@ -0,0 +1,44 @@
|
||||
<group name="web,modsecurity,attack,">
|
||||
|
||||
<!-- Règles spécialisées par type d'attaque — basées sur local_modsecurity_rules.xml (rule 100102) -->
|
||||
|
||||
<!-- SQL Injection bloquée -->
|
||||
<rule id="100202" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">SQL Injection\|SQLi\|942[0-9]</field>
|
||||
<description>ModSecurity: SQL Injection bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>modsecurity_sqli,sql_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- XSS bloqué -->
|
||||
<rule id="100203" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">XSS\|941[0-9]</field>
|
||||
<description>ModSecurity: XSS bloqué — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>modsecurity_xss,xss,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Remote Code Execution bloqué -->
|
||||
<rule id="100204" level="14">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">RCE\|930[0-9]\|932[0-9]</field>
|
||||
<description>ModSecurity: tentative RCE bloquée — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>modsecurity_rce,rce,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Local File Inclusion bloqué -->
|
||||
<rule id="100205" level="12">
|
||||
<if_sid>100102</if_sid>
|
||||
<field name="transaction.messages.message">LFI\|930[0-9]</field>
|
||||
<description>ModSecurity: LFI bloqué — $(transaction.client_ip) → $(transaction.request.uri)</description>
|
||||
<group>modsecurity_lfi,lfi,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Blocages répétés — attaque soutenue -->
|
||||
<rule id="100210" level="14" frequency="5" timeframe="120">
|
||||
<if_matched_sid>100102</if_matched_sid>
|
||||
<description>ModSecurity: blocages répétés en 2 min — attaque soutenue</description>
|
||||
<group>modsecurity_repeated,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# Generate WireGuard client config for admin
|
||||
# Usage: wireguard-admin-client.sh <admin_name> <server_ip> <server_pubkey>
|
||||
# Output: admin_name.conf (ready for import in WireGuard app)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
ADMIN_NAME="${1:-admin1}"
|
||||
VPN_SERVER_IP="${2:-}"
|
||||
VPN_SERVER_PUBKEY="${3:-}"
|
||||
|
||||
if [ -z "$VPN_SERVER_IP" ] || [ -z "$VPN_SERVER_PUBKEY" ]; then
|
||||
echo "Usage: $0 <admin_name> <server_ip> <server_pubkey>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0 admin1 123.45.67.89 'aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE='"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[*] Generating WireGuard config for admin: $ADMIN_NAME"
|
||||
|
||||
# ─── Generate unique keys for this admin ───────────────────────
|
||||
ADMIN_PRIVATEKEY=$(wg genkey)
|
||||
ADMIN_PUBKEY=$(echo "$ADMIN_PRIVATEKEY" | wg pubkey)
|
||||
|
||||
# ─── Auto-assign IP from 10.0.0.3+ ─────────────────────────────
|
||||
# Format: [admin_name].conf uses 10.0.0.3, 10.0.0.4, etc.
|
||||
# You should track these manually or use a database
|
||||
ADMIN_IP="10.0.0.3" # ← CHANGE THIS for each admin
|
||||
|
||||
# ─── Create config file ────────────────────────────────────────
|
||||
cat > "${ADMIN_NAME}.conf" << EOF
|
||||
[Interface]
|
||||
Address = $ADMIN_IP/32
|
||||
PrivateKey = $ADMIN_PRIVATEKEY
|
||||
DNS = 8.8.8.8
|
||||
|
||||
[Peer]
|
||||
PublicKey = $VPN_SERVER_PUBKEY
|
||||
AllowedIPs = 10.0.0.0/24
|
||||
Endpoint = $VPN_SERVER_IP:51820
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
echo "[✓] Config created: ${ADMIN_NAME}.conf"
|
||||
echo ""
|
||||
echo "Configuration:"
|
||||
echo " Name: $ADMIN_NAME"
|
||||
echo " IP: $ADMIN_IP"
|
||||
echo " Public Key: $ADMIN_PUBKEY"
|
||||
echo ""
|
||||
echo "Steps to add to VPN server:"
|
||||
echo " 1. Copy public key above"
|
||||
echo " 2. SSH to VPN server"
|
||||
echo " 3. wg set wg0 peer $ADMIN_PUBKEY allowed-ips $ADMIN_IP/32"
|
||||
echo " 4. wg show"
|
||||
echo ""
|
||||
echo "To import on your device:"
|
||||
echo " 1. Install WireGuard app (Windows/Mac/Linux/iPhone/Android)"
|
||||
echo " 2. Import ${ADMIN_NAME}.conf"
|
||||
echo " 3. Connect to VPN"
|
||||
echo " 4. Access services:"
|
||||
echo " • Wazuh: https://10.0.0.2"
|
||||
echo " • Dozzle: http://10.0.0.2:8080"
|
||||
echo " • Beszel: http://10.0.0.2:9090"
|
||||
echo " • S3: http://10.0.0.2:9000"
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# WireGuard Client Setup (monitoring-uber)
|
||||
# Install WireGuard, generate client keys, auto-connect to VPN server
|
||||
# Client IP: 10.0.0.2/24
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
# ─── Parameters ────────────────────────────────────────────────────
|
||||
VPN_SERVER_IP="${1:-}" # IP publique du serveur VPN
|
||||
VPN_SERVER_PUBKEY="${2:-}" # Clé publique du serveur VPN
|
||||
|
||||
if [ -z "$VPN_SERVER_IP" ] || [ -z "$VPN_SERVER_PUBKEY" ]; then
|
||||
echo "Usage: $0 <VPN_SERVER_IP> <VPN_SERVER_PUBKEY>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0 123.45.67.89 'aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdE='"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[*] Setting up WireGuard Client on monitoring-uber..."
|
||||
echo " Server IP: $VPN_SERVER_IP"
|
||||
echo " Server Pubkey: $VPN_SERVER_PUBKEY"
|
||||
|
||||
# ─── Install WireGuard ─────────────────────────────────────────
|
||||
echo "[*] Installing WireGuard..."
|
||||
apt-get update -qq
|
||||
apt-get install -y wireguard wireguard-tools
|
||||
|
||||
# ─── Create key directory ──────────────────────────────────────
|
||||
mkdir -p /etc/wireguard
|
||||
cd /etc/wireguard
|
||||
umask 077
|
||||
|
||||
# ─── Generate client keys ──────────────────────────────────────
|
||||
if [ ! -f client_privatekey ]; then
|
||||
echo "[*] Generating client private key..."
|
||||
wg genkey > client_privatekey
|
||||
cat client_privatekey | wg pubkey > client_publickey
|
||||
echo "[✓] Keys generated"
|
||||
echo ""
|
||||
echo "Client Public Key (for server):"
|
||||
cat client_publickey
|
||||
echo ""
|
||||
else
|
||||
echo "[!] Client keys already exist"
|
||||
fi
|
||||
|
||||
# ─── Create wg0 configuration ──────────────────────────────────
|
||||
echo "[*] Creating WireGuard client configuration..."
|
||||
|
||||
PRIVATE_KEY=$(cat client_privatekey)
|
||||
CLIENT_PUBKEY=$(cat client_publickey)
|
||||
|
||||
cat > wg0.conf << EOF
|
||||
[Interface]
|
||||
# monitoring-uber VPN IP
|
||||
Address = 10.0.0.2/24
|
||||
ListenPort = 0
|
||||
PrivateKey = $PRIVATE_KEY
|
||||
|
||||
[Peer]
|
||||
# VPN Server
|
||||
PublicKey = $VPN_SERVER_PUBKEY
|
||||
AllowedIPs = 10.0.0.0/24
|
||||
Endpoint = $VPN_SERVER_IP:51820
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
chmod 600 wg0.conf
|
||||
|
||||
echo "[✓] Configuration created at /etc/wireguard/wg0.conf"
|
||||
|
||||
# ─── Enable at boot and start ──────────────────────────────────
|
||||
echo "[*] Enabling WireGuard at boot..."
|
||||
systemctl enable wg-quick@wg0 2>/dev/null || true
|
||||
systemctl start wg-quick@wg0
|
||||
|
||||
sleep 2
|
||||
|
||||
# Vérifier connexion
|
||||
if ip addr show wg0 &>/dev/null; then
|
||||
echo "[✓] WireGuard interface up"
|
||||
ip addr show wg0
|
||||
else
|
||||
echo "[!] WireGuard interface not up, check logs:"
|
||||
journalctl -u wg-quick@wg0 -n 10
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[✓] WireGuard Client configured"
|
||||
echo ""
|
||||
echo "Configuration Summary:"
|
||||
echo " • Interface: wg0"
|
||||
echo " • Client IP: 10.0.0.2/24"
|
||||
echo " • Server: $VPN_SERVER_IP:51820"
|
||||
echo " • Config: /etc/wireguard/wg0.conf"
|
||||
echo ""
|
||||
echo "IMPORTANT: Add this client public key to VPN server:"
|
||||
echo " wg set wg0 peer $(cat client_publickey) allowed-ips 10.0.0.2/32"
|
||||
echo ""
|
||||
echo "Verify connection:"
|
||||
echo " ping 10.0.0.1"
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# WireGuard Server Setup (VPS VPN)
|
||||
# Install WireGuard, generate server keys, configure interface
|
||||
# Network: 10.0.0.0/24
|
||||
# Server IP: 10.0.0.1
|
||||
# Listen: 0.0.0.0:51820/udp
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
set -e
|
||||
|
||||
echo "[*] Setting up WireGuard Server..."
|
||||
|
||||
# ─── Install WireGuard ─────────────────────────────────────────
|
||||
echo "[*] Installing WireGuard..."
|
||||
apt-get update -qq
|
||||
apt-get install -y wireguard wireguard-tools
|
||||
|
||||
# ─── Create key directory ──────────────────────────────────────
|
||||
mkdir -p /etc/wireguard
|
||||
cd /etc/wireguard
|
||||
umask 077
|
||||
|
||||
# ─── Generate server keys ──────────────────────────────────────
|
||||
if [ ! -f privatekey ]; then
|
||||
echo "[*] Generating server private key..."
|
||||
wg genkey > privatekey
|
||||
cat privatekey | wg pubkey > publickey
|
||||
echo "[✓] Keys generated"
|
||||
echo ""
|
||||
echo "Server Public Key:"
|
||||
cat publickey
|
||||
echo ""
|
||||
else
|
||||
echo "[!] Server keys already exist"
|
||||
fi
|
||||
|
||||
# ─── Create wg0 configuration ──────────────────────────────────
|
||||
echo "[*] Creating WireGuard interface configuration..."
|
||||
|
||||
cat > wg0.conf << 'EOF'
|
||||
[Interface]
|
||||
# Server IP dans le réseau VPN
|
||||
Address = 10.0.0.1/24
|
||||
ListenPort = 51820
|
||||
|
||||
# Charger la clé privée
|
||||
PrivateKey = PRIVATE_KEY_PLACEHOLDER
|
||||
|
||||
# Accepter VPN traffic
|
||||
PostUp = iptables -I FORWARD 1 -i %i -j ACCEPT; iptables -I FORWARD 1 -o %i -j ACCEPT; iptables -t nat -I POSTROUTING 1 -o eth0 -j MASQUERADE
|
||||
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
# Peers: monitoring-uber, admins (ajouté après)
|
||||
EOF
|
||||
|
||||
# Remplacer placeholder par clé réelle
|
||||
PRIVATE_KEY=$(cat privatekey)
|
||||
sed -i "s|PRIVATE_KEY_PLACEHOLDER|$PRIVATE_KEY|" wg0.conf
|
||||
|
||||
# ─── Enable WireGuard interface ────────────────────────────────
|
||||
echo "[*] Bringing up WireGuard interface..."
|
||||
ip link add dev wg0 type wireguard
|
||||
ip addr add 10.0.0.1/24 dev wg0
|
||||
ip link set wg0 up
|
||||
wg set wg0 private-key <(cat privatekey)
|
||||
wg set wg0 listen-port 51820
|
||||
|
||||
# ─── Enable at boot ───────────────────────────────────────────
|
||||
echo "[*] Enabling WireGuard at boot..."
|
||||
systemctl enable wg-quick@wg0 2>/dev/null || true
|
||||
systemctl start wg-quick@wg0 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "[✓] WireGuard Server configured"
|
||||
echo ""
|
||||
echo "Configuration Summary:"
|
||||
echo " • Interface: wg0"
|
||||
echo " • Server IP: 10.0.0.1/24"
|
||||
echo " • Listen: 0.0.0.0:51820/udp"
|
||||
echo " • Config: /etc/wireguard/wg0.conf"
|
||||
echo ""
|
||||
echo "Server Public Key (for clients):"
|
||||
cat publickey
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Create client configs with wg-quick or manually"
|
||||
echo " 2. Add peers to wg0:"
|
||||
echo " wg set wg0 peer <CLIENT_PUBKEY> allowed-ips 10.0.0.X/32"
|
||||
@@ -1,35 +0,0 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
Decoders ModSecurity — JSON Audit Log (libmodsecurity3)
|
||||
Format : {"transaction":{"client_ip":"...","request":{"uri":"..."},
|
||||
"response":{"http_code":N},"messages":[{"details":{"ruleId":"N"}}]}}
|
||||
Collecté via log_format:json sur les fichiers Docker container log
|
||||
(Wazuh extrait le champ "log" du wrapper Docker JSON avant décodage)
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Parent : toute transaction ModSecurity JSON -->
|
||||
<decoder name="docker-waf-modsec">
|
||||
<prematch>{"transaction":{</prematch>
|
||||
</decoder>
|
||||
|
||||
<!-- Accès bloqué (http_code exactement 403) avec règle déclenchée.
|
||||
Listé en premier — priorité sur docker-waf-modsec-rule. -->
|
||||
<decoder name="docker-waf-modsec-blocked">
|
||||
<parent>docker-waf-modsec</parent>
|
||||
<regex>"client_ip":"(\d+\.\d+\.\d+\.\d+)".+"uri":"([^"]+)".+"http_code":403.+"ruleId":"(\d+)"</regex>
|
||||
<order>srcip,url,id</order>
|
||||
</decoder>
|
||||
|
||||
<!-- Règle déclenchée sans blocage (warning / anomaly scoring).
|
||||
Capte aussi les non-403 avec ruleId. -->
|
||||
<decoder name="docker-waf-modsec-rule">
|
||||
<parent>docker-waf-modsec</parent>
|
||||
<regex>"client_ip":"(\d+\.\d+\.\d+\.\d+)".+"uri":"([^"]+)".+"ruleId":"(\d+)"</regex>
|
||||
<order>srcip,url,id</order>
|
||||
</decoder>
|
||||
|
||||
<!-- Trafic passant sans règle matchée (fallback) -->
|
||||
<decoder name="docker-waf-modsec-pass">
|
||||
<parent>docker-waf-modsec</parent>
|
||||
<regex>"client_ip":"(\d+\.\d+\.\d+\.\d+)".+"uri":"([^"]+)"</regex>
|
||||
<order>srcip,url</order>
|
||||
</decoder>
|
||||
@@ -1,37 +0,0 @@
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
Règles ModSecurity — WAF container (gestion-waf)
|
||||
Source : logs JSON audit libmodsecurity3 via docker-waf-modsec*
|
||||
srcip = client_ip, url = uri, id = ruleId
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<group name="web,modsecurity,">
|
||||
|
||||
<!-- Trafic passant sans règle déclenchée — supprimé (niveau 0) -->
|
||||
<rule id="100100" level="0">
|
||||
<decoded_as>docker-waf-modsec-pass</decoded_as>
|
||||
<description>ModSecurity: trafic légitime (supprimé).</description>
|
||||
</rule>
|
||||
|
||||
<!-- Règle WAF déclenchée sans blocage (warning / anomaly scoring) -->
|
||||
<rule id="100101" level="6">
|
||||
<decoded_as>docker-waf-modsec-rule</decoded_as>
|
||||
<description>ModSecurity: règle $(id) — $(srcip) → $(url)</description>
|
||||
<group>web,modsecurity,attack,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Accès bloqué (HTTP 403) -->
|
||||
<rule id="100102" level="10">
|
||||
<decoded_as>docker-waf-modsec-blocked</decoded_as>
|
||||
<description>ModSecurity: accès bloqué (403) — $(srcip) → $(url) [règle $(id)]</description>
|
||||
<group>web,modsecurity,attack,blocked,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Blocages répétés depuis la même IP → scan ou attaque -->
|
||||
<rule id="100103" level="12" frequency="5" timeframe="60">
|
||||
<if_matched_sid>100102</if_matched_sid>
|
||||
<same_source_ip />
|
||||
<description>ModSecurity: blocages répétés depuis $(srcip) — scan ou attaque</description>
|
||||
<group>web,modsecurity,attack,blocked,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
@@ -1,94 +0,0 @@
|
||||
<group name="web,modsecurity,attack,">
|
||||
|
||||
<!-- ─────────────────────────────────────────────────────────
|
||||
Règles de base (décodeurs modsecurity-block / warning)
|
||||
───────────────────────────────────────────────────────── -->
|
||||
|
||||
<!-- Bloc générique ModSecurity (403) -->
|
||||
<rule id="100200" level="8">
|
||||
<decoded_as>modsecurity-block</decoded_as>
|
||||
<description>ModSecurity: requête bloquée ($(extra_data)) sur $(url)</description>
|
||||
<group>modsecurity_block,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Warning générique ModSecurity (non-bloquant) -->
|
||||
<rule id="100201" level="5">
|
||||
<decoded_as>modsecurity-warning</decoded_as>
|
||||
<description>ModSecurity: alerte $(extra_data) sur $(url)</description>
|
||||
<group>modsecurity_warning,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ─────────────────────────────────────────────────────────
|
||||
Règles spécialisées par type d'attaque
|
||||
(parentes : 100200 — blocs déjà détectés)
|
||||
───────────────────────────────────────────────────────── -->
|
||||
|
||||
<!-- SQL Injection -->
|
||||
<rule id="100202" level="12">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>SQL Injection</match>
|
||||
<description>ModSecurity: SQL Injection détecté depuis $(srcip) sur $(url)</description>
|
||||
<group>modsecurity_sqli,sql_injection,</group>
|
||||
</rule>
|
||||
|
||||
<!-- XSS -->
|
||||
<rule id="100203" level="12">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>XSS</match>
|
||||
<description>ModSecurity: XSS détecté depuis $(srcip) sur $(url)</description>
|
||||
<group>modsecurity_xss,xss,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Remote Code Execution -->
|
||||
<rule id="100204" level="14">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>RCE</match>
|
||||
<description>ModSecurity: tentative RCE depuis $(srcip) sur $(url)</description>
|
||||
<group>modsecurity_rce,rce,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Local File Inclusion -->
|
||||
<rule id="100205" level="12">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>LFI</match>
|
||||
<description>ModSecurity: LFI détecté depuis $(srcip) sur $(url)</description>
|
||||
<group>modsecurity_lfi,lfi,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Score d'anomalie critique -->
|
||||
<rule id="100206" level="13">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>Critical anomaly score\|anomaly score</match>
|
||||
<description>ModSecurity: score d'anomalie critique depuis $(srcip)</description>
|
||||
<group>modsecurity_anomaly,</group>
|
||||
</rule>
|
||||
|
||||
<!-- IP bannie par ModSecurity (règle 100000) -->
|
||||
<rule id="100207" level="10">
|
||||
<if_sid>100200</if_sid>
|
||||
<match>IP is banned\|ip.banned</match>
|
||||
<description>ModSecurity: IP bannie $(srcip) tente un accès</description>
|
||||
<group>modsecurity_banned,</group>
|
||||
</rule>
|
||||
|
||||
<!-- Trop de requêtes (rate-limit 429) -->
|
||||
<rule id="100208" level="6">
|
||||
<decoded_as>modsecurity-block</decoded_as>
|
||||
<field name="status">429</field>
|
||||
<description>ModSecurity: rate-limit déclenché depuis $(srcip)</description>
|
||||
<group>modsecurity_ratelimit,</group>
|
||||
</rule>
|
||||
|
||||
<!-- ─────────────────────────────────────────────────────────
|
||||
Règle de fréquence : blocages répétés → niveau critique
|
||||
Déclenche active-response firewall-drop 24h
|
||||
───────────────────────────────────────────────────────── -->
|
||||
|
||||
<rule id="100210" level="14" frequency="5" timeframe="120">
|
||||
<if_matched_sid>100200</if_matched_sid>
|
||||
<same_srcip />
|
||||
<description>ModSecurity: $(srcip) bloqué 5 fois en 2 min — attaque soutenue</description>
|
||||
<group>modsecurity_repeated,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
Reference in New Issue
Block a user