Security & Penetration Testing Guide¶
This document covers the homelab's attack surfaces, threat vectors, security controls, and pentesting methodology. Use this for security audits, hardening verification, and educational reference.
Architecture Security Overview¶
INTERNET
│
▼
┌─────────────────────┐
│ Cloudflare DNS │
│ (DDoS protection) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Hetzner VPS │
│ 5.161.45.147 │
│ ───────────── │
│ Caddy (TLS) │
│ WireGuard Client │
└─────────┬───────────┘
│ WireGuard Tunnel
│ (encrypted)
▼
┌─────────────────────┐
│ OPNsense Firewall │
│ 10.22.95.1 │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ K8s Cluster │
│ 10.89.97.0/24 │
│ ───────────── │
│ nginx-ingress │
│ Authentik SSO │
│ Application Pods │
└─────────────────────┘
Attack Surface Inventory¶
External Attack Surface (Internet-Facing)¶
| Component | Exposed Port | Purpose | Protection |
|---|---|---|---|
| VPS Caddy | 443 (HTTPS) | Reverse proxy | TLS 1.3, rate limiting |
| VPS Caddy | 80 (HTTP) | Redirect to HTTPS | Auto-redirect |
| VPS WireGuard | 51820 (UDP) | VPN tunnel | Key-based auth |
| VPS SSH | 22 | Admin access | Key-only, fail2ban |
Services Exposed via VPS (*.bogocat.com)¶
| Service | URL | Auth Type | Risk Level |
|---|---|---|---|
| Authentik | auth.bogocat.com | Native (MFA required) | HIGH (SSO = keys to kingdom) |
| Home Portal | portal.bogocat.com | Authentik OAuth | Medium |
| Money Tracker | money.bogocat.com | Authentik OAuth | Medium |
| Trip Planner | travel.bogocat.com | Authentik OAuth | Medium |
| Immich | photos.bogocat.com | Authentik OIDC (native) | Medium |
| Jellyfin | jellyfin.bogocat.com | LDAP + OAuth (SSO plugin) | Medium |
| Radarr | radarr.bogocat.com | Authentik Forward Auth | Low |
| Sonarr | sonarr.bogocat.com | Authentik Forward Auth | Low |
| (other arr services) | *.bogocat.com | Authentik Forward Auth | Low |
Auth Type Legend: - Authentik OAuth: App uses NextAuth with Authentik provider (MFA enforced) - Authentik OIDC: App has native OIDC support, configured with Authentik (MFA enforced) - Authentik Forward Auth: nginx-ingress checks auth before proxying (MFA enforced) - LDAP + OAuth: Dual auth paths - LDAP for devices (no MFA), OAuth for browsers (MFA)
Internal Attack Surface (Requires VPN/Physical Access)¶
| Component | IP/Port | Notes |
|---|---|---|
| Proxmox Host | 10.89.97.11:8006 | Web UI + SSH |
| K8s API | 10.89.97.201:6443 | kubectl access |
| PostgreSQL (Supabase) | 10.89.97.219:5432 | Database |
| LDAP Outpost | 10.89.97.218:389 | Authentik LDAP |
Threat Model¶
Threat Actors¶
| Actor | Capability | Motivation | Likelihood |
|---|---|---|---|
| Script Kiddie | Automated scans, known exploits | Curiosity, botnets | HIGH |
| Credential Stuffing Bot | Breached password lists | Account takeover | HIGH |
| Targeted Attacker | Custom exploits, persistence | Data theft | LOW |
| Insider (Friend) | Valid credentials | Curiosity, accident | LOW |
Attack Vectors¶
1. Authentication Attacks¶
| Vector | Description | Current Mitigation |
|---|---|---|
| Password Spraying | Try common passwords across accounts | Rate limiting (5 attempts = lockout) |
| Credential Stuffing | Use breached credentials | Unique passwords + MFA |
| MFA Bypass | Phishing for TOTP codes | WebAuthn (phishing-resistant) |
| Session Hijacking | Steal session cookies | HTTPS-only, secure cookies |
| OAuth Token Theft | Intercept authorization codes | Short-lived tokens, PKCE |
2. Network Attacks¶
| Vector | Description | Current Mitigation |
|---|---|---|
| DDoS | Flood VPS with traffic | Cloudflare, VPS isolation |
| WireGuard Key Theft | Compromise VPN access | Key rotation, limited peers |
| Man-in-the-Middle | Intercept traffic | TLS everywhere, WireGuard |
| DNS Hijacking | Redirect *.bogocat.com | Cloudflare DNS security |
3. Application Attacks¶
| Vector | Description | Current Mitigation |
|---|---|---|
| XSS | Inject malicious scripts | CSP headers, input sanitization |
| SQL Injection | Database manipulation | Parameterized queries, RLS |
| SSRF | Server-side request forgery | Internal network isolation |
| Path Traversal | Access unauthorized files | Containerization, read-only FS |
4. Infrastructure Attacks¶
| Vector | Description | Current Mitigation |
|---|---|---|
| Container Escape | Break out of K8s pod | SecurityContext, no privileged |
| Supply Chain | Compromised dependencies | Image scanning, pinned versions |
| Secrets Exposure | Leaked credentials | SealedSecrets, gitignored .env |
Authentication Flow Security¶
Current Authentication Chain¶
User Request → Caddy (VPS) → nginx-ingress (K8s) → Authentik → Application
│ │ │
│ │ └─ MFA Validation
│ └─ Forward Auth Check
└─ TLS Termination
MFA Configuration¶
Current Setup:
default-authentication-flow:
Order 10: identification-stage (username/email)
Order 20: password-stage
Order 30: mfa-validation (TOTP + WebAuthn)
└─ Not configured action: Configure (FORCES MFA SETUP)
Key Security Properties: - MFA is required for all users - Users cannot skip MFA setup on first login - WebAuthn (passkeys) preferred over TOTP - 5 failed attempts = temporary account lockout
User Onboarding Security Gap¶
Scenario: Admin creates new user account
Timeline:
┌─────────────────────────────────────────────────────────────────┐
│ T+0 Admin creates user, sets initial password │
│ T+? Admin sends password to user (email, chat, etc.) │
│ T+?? User logs in for first time │
│ └─> FORCED to configure MFA before accessing any app │
│ T+??? User is now protected by MFA │
└─────────────────────────────────────────────────────────────────┘
Risk Window: Between T+0 and T+?? (user's first login)
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Password intercepted in transit | Low | High | Use secure channel (Signal, in-person) |
| Admin account compromised | Low | Critical | Admin uses MFA, separate admin account |
| Brute force before user logs in | Very Low | Medium | Rate limiting, strong initial password |
Best Practices for User Onboarding: 1. Generate strong random initial password (20+ chars) 2. Send via secure channel (Signal, in-person, NOT email) 3. Set password expiry (force change on first login) 4. Monitor for unusual login attempts 5. User must configure MFA before accessing any application
Penetration Testing Methodology¶
Phase 1: Reconnaissance¶
# DNS enumeration
dig +short bogocat.com
dig +short ANY bogocat.com
nslookup -type=any bogocat.com
# Subdomain discovery (passive)
curl -s "https://crt.sh/?q=%.bogocat.com&output=json" | jq -r '.[].name_value' | sort -u
# Port scanning (from authorized location)
nmap -sV -sC -p- 5.161.45.147
# SSL/TLS analysis
testssl.sh auth.bogocat.com
Phase 2: Authentication Testing¶
# Test for default credentials
curl -X POST https://auth.bogocat.com/api/v3/core/users/ \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# Test rate limiting
for i in {1..10}; do
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST https://auth.bogocat.com/api/v3/flows/executor/default-authentication-flow/ \
-d "uid_field=test&password=wrong$i"
done
# Test MFA bypass (should fail)
# Attempt to access protected resource without completing MFA flow
curl -v https://portal.bogocat.com/ -H "Cookie: authentik_session=..."
# Test API endpoint protection
curl -s -o /dev/null -w "%{http_code}" \
-H "Host: radarr.bogocat.com" \
https://radarr.bogocat.com/api/v3/system/status
# Expected: 302 (redirect to auth)
Phase 3: Forward Auth Testing¶
# Test that forward auth is enforced
for service in sonarr radarr lidarr prowlarr; do
echo -n "$service: "
curl -s -o /dev/null -w "%{http_code}" "https://$service.bogocat.com/"
done
# Expected: All return 302 (redirect to Authentik)
# Test header injection (should be blocked)
curl -v https://sonarr.bogocat.com/ \
-H "X-Authentik-Username: admin" \
-H "X-Authentik-Groups: admins"
# Expected: 302 (headers ignored, still requires auth)
Phase 4: Application Testing¶
# Test for information disclosure
curl -s https://portal.bogocat.com/ | grep -i "version\|powered by\|server"
# Test error handling (no stack traces)
curl -s "https://portal.bogocat.com/api/nonexistent" | head -20
# Test CORS configuration
curl -v -X OPTIONS https://portal.bogocat.com/api/ \
-H "Origin: https://evil.com" \
-H "Access-Control-Request-Method: POST"
Phase 5: Infrastructure Testing¶
# From VPS (if compromised, what's reachable?)
ssh root@5.161.45.147
# Test WireGuard tunnel isolation
ping 10.89.97.220 # K8s ingress - should work
ping 10.89.97.11 # Proxmox host - should work (evaluate if needed)
# Test what ports are accessible through tunnel
for port in 22 5432 6443 8006; do
nc -zv 10.89.97.11 $port 2>&1 | grep -q succeeded && echo "Port $port OPEN"
done
Security Controls Checklist¶
Authentication & Authorization¶
- [x] MFA required for all users
- [x] MFA forced on first login (not optional)
- [x] WebAuthn (phishing-resistant) available
- [x] Rate limiting on login attempts
- [x] Session timeout configured
- [x] Forward auth on all arr-stack services
- [ ] Password policy enforcement (min length, complexity)
- [ ] Account lockout notification to admin
Network Security¶
- [x] TLS on all external endpoints
- [x] WireGuard for VPS-to-homelab tunnel
- [x] No direct port forwarding from home IP
- [x] Firewall rules on OPNsense
- [ ] Network segmentation (arr-stack isolated from apps)
- [ ] VPN access logging/alerting
Application Security¶
- [x] HTTPS-only (HTTP redirects)
- [x] Secure cookie flags (HttpOnly, Secure, SameSite)
- [x] Containerized workloads
- [ ] Security headers (CSP, X-Frame-Options, etc.)
- [ ] Regular dependency updates
- [ ] Container image scanning
Secrets Management¶
- [x] SealedSecrets for K8s
- [x] .env files gitignored
- [x] Secrets not logged
- [ ] Secret rotation schedule
- [ ] Vault/external secrets manager
Monitoring & Alerting¶
- [x] Authentik event logs
- [ ] Failed login alerting
- [ ] Suspicious activity detection
- [ ] Uptime monitoring
- [ ] Log aggregation (Loki/ELK)
Incident Response¶
If VPS is Compromised¶
-
Contain: Disable WireGuard tunnel immediately
-
Assess: Check what was accessed
-
Recover:
- Rebuild VPS from scratch (assume compromised)
- Rotate WireGuard keys
- Review Authentik sessions/tokens
- Change any secrets that were accessible
If Authentik is Compromised¶
-
Contain: Take Authentik offline
-
Assess:
- Check Authentik event logs
- Review user sessions
-
Check for new users/applications/providers
-
Recover:
- Invalidate all sessions
- Force password reset for all users
- Review and re-enroll MFA devices
- Audit application access
If User Credentials Leaked¶
-
Contain: Disable user account
-
Assess: Check user's recent activity in Authentik logs
-
Recover:
- Reset password
- Remove all MFA devices
- Re-enroll user with new credentials
Regular Security Tasks¶
Weekly¶
- [ ] Review Authentik event logs for anomalies
- [ ] Check for failed login attempts
Monthly¶
- [ ] Update container images
- [ ] Review user accounts (remove unused)
- [ ] Test backup restoration
Quarterly¶
- [ ] Full penetration test (this checklist)
- [ ] Review and update this document
- [ ] Rotate long-lived secrets
- [ ] Review firewall rules
Tools Reference¶
| Tool | Purpose | Installation |
|---|---|---|
nmap |
Port scanning | apt install nmap |
testssl.sh |
TLS analysis | git clone https://github.com/drwetter/testssl.sh |
nikto |
Web vulnerability scanner | apt install nikto |
nuclei |
Template-based scanner | go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest |
ffuf |
Web fuzzer | go install github.com/ffuf/ffuf/v2@latest |
burpsuite |
HTTP proxy/scanner | Download from PortSwigger |