Files
nuc/docs/security.md
Alejandro Gutiérrez 8b503a549c 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>
2026-02-18 15:17:18 +01:00

7.7 KiB

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

# 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)
# 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

# 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

# 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

# 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
# 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

# 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)

# 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
# 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

  • SSH password auth disabled
  • LuCI not exposed on WAN
  • WAN input policy: REJECT
  • CrowdSec bouncer active
  • Only WireGuard port open (51820)
  • UPnP disabled

NUC

  • SSH password auth disabled
  • fail2ban protecting SSH
  • CrowdSec running (Docker)
  • Unattended upgrades enabled
  • No services exposed to WAN directly

Network

  • Tailscale for remote access
  • WireGuard as backup VPN
  • DuckDNS for dynamic IP

Incident Response

If Brute Force Detected

# 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

# 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