Add operational documentation
CloudBeaver database manager guide, Ecija intranet deployment, Gitea-Coolify auto-deploy and integration docs, monitoring setup with presentation, remote access guide, security architecture, and Turbostarter deployment procedure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
329
docs/security.md
Normal file
329
docs/security.md
Normal file
@@ -0,0 +1,329 @@
|
||||
# Security Configuration
|
||||
|
||||
Comprehensive security hardening for NUC server and OpenWrt router.
|
||||
|
||||
## Security Architecture
|
||||
|
||||
```
|
||||
Internet
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ OpenWrt Router (192.168.1.1) │
|
||||
│ ├─ CrowdSec Bouncer (threat intel) │
|
||||
│ ├─ Firewall (WAN: REJECT default) │
|
||||
│ └─ SSH: key-only authentication │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
│ Only allowed: WireGuard (51820/udp)
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ NUC Server (192.168.1.3) │
|
||||
│ ├─ CrowdSec (threat intelligence) │
|
||||
│ ├─ fail2ban (brute force protect) │
|
||||
│ ├─ SSH: key-only + 24h ban │
|
||||
│ ├─ Unattended upgrades (auto) │
|
||||
│ └─ Tailscale Funnel (HTTPS only) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## External Attack Surface
|
||||
|
||||
| Port | Service | Protection |
|
||||
|------|---------|------------|
|
||||
| 51820/udp | WireGuard VPN | Cryptographic auth only |
|
||||
| Tailscale Funnel | HTTPS services | Tailscale auth + TLS |
|
||||
| Everything else | Blocked | Router firewall DROP |
|
||||
|
||||
**Not exposed to internet:**
|
||||
- SSH (22)
|
||||
- Router admin (80/443)
|
||||
- Coolify (8000)
|
||||
- All Docker services
|
||||
|
||||
---
|
||||
|
||||
## Router Security (OpenWrt)
|
||||
|
||||
### SSH Configuration
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Password auth | Disabled |
|
||||
| Root password auth | Disabled |
|
||||
| Auth method | SSH key only |
|
||||
| Port | 22 (LAN only) |
|
||||
|
||||
**Config:** `/etc/config/dropbear`
|
||||
|
||||
```bash
|
||||
# Verify settings
|
||||
uci get dropbear.@dropbear[0].PasswordAuth # off
|
||||
uci get dropbear.@dropbear[0].RootPasswordAuth # off
|
||||
```
|
||||
|
||||
### Firewall (fw4/nftables)
|
||||
|
||||
**WAN Zone Policy:**
|
||||
- Input: REJECT
|
||||
- Forward: REJECT
|
||||
- Output: ACCEPT
|
||||
|
||||
**Allowed WAN Input:**
|
||||
- DHCP (port 68)
|
||||
- ICMPv6 (limited)
|
||||
- WireGuard (51820/udp)
|
||||
|
||||
```bash
|
||||
# View WAN input rules
|
||||
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft list chain inet fw4 input_wan"
|
||||
```
|
||||
|
||||
### CrowdSec Firewall Bouncer
|
||||
|
||||
Blocks malicious IPs using threat intelligence from NUC CrowdSec.
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| API URL | http://192.168.1.3:8083/ |
|
||||
| Update frequency | 10s |
|
||||
| Action | DROP + log |
|
||||
| Interfaces | wan, wan6 |
|
||||
|
||||
**Config:** `/etc/config/crowdsec`
|
||||
|
||||
```bash
|
||||
# Check bouncer status
|
||||
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "/etc/init.d/crowdsec-firewall-bouncer status"
|
||||
|
||||
# View blocked IPs
|
||||
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft list set ip crowdsec crowdsec_blocklist"
|
||||
|
||||
# Check logs
|
||||
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "logread | grep crowdsec"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NUC Security
|
||||
|
||||
### SSH Configuration
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Password auth | Disabled |
|
||||
| Auth method | SSH key only |
|
||||
| Port | 22 |
|
||||
|
||||
**Config:** `/etc/ssh/sshd_config`
|
||||
|
||||
```bash
|
||||
# Verify
|
||||
grep "PasswordAuthentication" /etc/ssh/sshd_config
|
||||
# PasswordAuthentication no
|
||||
```
|
||||
|
||||
### fail2ban
|
||||
|
||||
Protects SSH from brute force attacks.
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Max retries | 3 |
|
||||
| Ban time | 24 hours |
|
||||
| Find time | 10 minutes |
|
||||
| Ignored IPs | LAN (192.168.1.0/24), Tailscale (100.0.0.0/8) |
|
||||
|
||||
**Config:** `/etc/fail2ban/jail.local`
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
sudo fail2ban-client status sshd
|
||||
|
||||
# View banned IPs
|
||||
sudo fail2ban-client status sshd | grep "Banned IP"
|
||||
|
||||
# Unban an IP
|
||||
sudo fail2ban-client set sshd unbanip <IP>
|
||||
```
|
||||
|
||||
### CrowdSec (Docker)
|
||||
|
||||
Central threat intelligence hub.
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Container | crowdsec-mwc4ocock400goww8s4k44o8 |
|
||||
| API Port | 8083 |
|
||||
| Dashboard | http://192.168.1.3:8083 |
|
||||
|
||||
```bash
|
||||
# List registered bouncers
|
||||
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli bouncers list
|
||||
|
||||
# View decisions (blocked IPs)
|
||||
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli decisions list
|
||||
|
||||
# View alerts
|
||||
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli alerts list
|
||||
```
|
||||
|
||||
### Unattended Upgrades
|
||||
|
||||
Automatic security and system updates.
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Security updates | Enabled |
|
||||
| Regular updates | Enabled |
|
||||
| Auto-reboot | 4:00 AM if needed |
|
||||
| Cleanup unused | Enabled |
|
||||
|
||||
**Config:** `/etc/apt/apt.conf.d/50unattended-upgrades-local`
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
sudo systemctl status unattended-upgrades
|
||||
|
||||
# View logs
|
||||
cat /var/log/unattended-upgrades/unattended-upgrades.log
|
||||
|
||||
# Manual dry-run
|
||||
sudo unattended-upgrade --dry-run --debug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Access Methods
|
||||
|
||||
### From LAN (Home Network)
|
||||
|
||||
| Service | Access |
|
||||
|---------|--------|
|
||||
| NUC SSH | `ssh nuc` or `ssh 192.168.1.3` |
|
||||
| Router SSH | `ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1` |
|
||||
| Router Admin | http://192.168.1.1 |
|
||||
| Coolify | http://192.168.1.3:8000 |
|
||||
|
||||
### From Remote (Via Tailscale)
|
||||
|
||||
| Service | Access |
|
||||
|---------|--------|
|
||||
| NUC SSH | `ssh nuc-tailscale` |
|
||||
| Full LAN | Via subnet router (192.168.1.0/24) |
|
||||
| Grafana | https://nuc-tailscale.tail58f5ad.ts.net:3002 |
|
||||
|
||||
### From Remote (Via WireGuard)
|
||||
|
||||
```bash
|
||||
# Connect
|
||||
sudo wg-quick up ~/wireguard/home-vpn.conf
|
||||
|
||||
# Then access LAN normally
|
||||
ssh 192.168.1.3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SSH Keys
|
||||
|
||||
| Key | Location | Used For |
|
||||
|-----|----------|----------|
|
||||
| NUC/Router key | `~/.ssh/id_ed25519_nuc` | SSH to NUC and OpenWrt |
|
||||
|
||||
```bash
|
||||
# Test NUC key auth
|
||||
ssh -i ~/.ssh/id_ed25519_nuc -o BatchMode=yes alezmad@192.168.1.3 "echo OK"
|
||||
|
||||
# Test router key auth
|
||||
ssh -i ~/.ssh/id_ed25519_nuc -o BatchMode=yes root@192.168.1.1 "echo OK"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Checklist
|
||||
|
||||
### Router
|
||||
- [x] SSH password auth disabled
|
||||
- [x] LuCI not exposed on WAN
|
||||
- [x] WAN input policy: REJECT
|
||||
- [x] CrowdSec bouncer active
|
||||
- [x] Only WireGuard port open (51820)
|
||||
- [x] UPnP disabled
|
||||
|
||||
### NUC
|
||||
- [x] SSH password auth disabled
|
||||
- [x] fail2ban protecting SSH
|
||||
- [x] CrowdSec running (Docker)
|
||||
- [x] Unattended upgrades enabled
|
||||
- [x] No services exposed to WAN directly
|
||||
|
||||
### Network
|
||||
- [x] Tailscale for remote access
|
||||
- [x] WireGuard as backup VPN
|
||||
- [x] DuckDNS for dynamic IP
|
||||
|
||||
---
|
||||
|
||||
## Incident Response
|
||||
|
||||
### If Brute Force Detected
|
||||
|
||||
```bash
|
||||
# Check fail2ban bans
|
||||
sudo fail2ban-client status sshd
|
||||
|
||||
# Check CrowdSec alerts
|
||||
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli alerts list
|
||||
|
||||
# View auth logs
|
||||
sudo tail -100 /var/log/auth.log | grep -i fail
|
||||
```
|
||||
|
||||
### If Compromised IP Needs Blocking
|
||||
|
||||
```bash
|
||||
# Add manual ban in CrowdSec (blocks on router too)
|
||||
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli decisions add --ip <IP> --duration 24h --reason "manual block"
|
||||
|
||||
# Or block directly on router
|
||||
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft add element ip crowdsec crowdsec_blocklist { <IP> }"
|
||||
```
|
||||
|
||||
### If Locked Out
|
||||
|
||||
1. **Physical access to NUC:** Connect monitor/keyboard
|
||||
2. **Router:** Reset button (hold 10s) restores defaults
|
||||
3. **Tailscale:** Still works if NUC is running
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
| What | How |
|
||||
|------|-----|
|
||||
| SSH attempts | `sudo tail -f /var/log/auth.log` |
|
||||
| fail2ban activity | `sudo fail2ban-client status sshd` |
|
||||
| CrowdSec decisions | `docker exec crowdsec-... cscli decisions list` |
|
||||
| Router firewall logs | `ssh root@192.168.1.1 "logread \| grep crowdsec"` |
|
||||
| Blocked connections | `ssh root@192.168.1.1 "nft list set ip crowdsec crowdsec_blocklist"` |
|
||||
|
||||
---
|
||||
|
||||
## Regular Maintenance
|
||||
|
||||
### Weekly
|
||||
- Check fail2ban status: `sudo fail2ban-client status`
|
||||
- Review CrowdSec alerts: `docker exec crowdsec-... cscli alerts list`
|
||||
|
||||
### Monthly
|
||||
- Verify unattended-upgrades working: `cat /var/log/unattended-upgrades/*.log`
|
||||
- Check for OpenWrt updates: `opkg update && opkg list-upgradable`
|
||||
- Review SSH auth logs for anomalies
|
||||
|
||||
### After Security Incident
|
||||
1. Check all logs (auth, CrowdSec, fail2ban)
|
||||
2. Rotate SSH keys if needed
|
||||
3. Update CrowdSec scenarios
|
||||
4. Review firewall rules
|
||||
Reference in New Issue
Block a user