homelab/.github/prompts/security-network-access.prompt.md
nathan 129b7eee1b Created Files
security-secrets-remediation.prompt.md - Phase 1 (CRITICAL)

Eliminates hardcoded secrets (Docker Registry, Komodo, Plex)
Creates .env templates and migration workflow
Priority: Immediate (This Week)
security-container-hardening.prompt.md - Phase 2 (HIGH)

Removes privileged containers
Converts root users to non-root (PUID/PGID)
Secures Docker socket access patterns
Priority: Short Term (This Month)
security-ansible-hardening.prompt.md - Phase 3 (MEDIUM)

Enables SSH host key checking
Implements restricted sudo rules
Deploys UFW firewalls and fail2ban
Priority: Medium Term (Next Month)
security-network-access.prompt.md - Phase 4 (MEDIUM)

Restricts port exposure (0.0.0.0 → 127.0.0.1)
Implements network segmentation
Adds authentication middleware
Priority: Ongoing (Next Quarter)
Each prompt follows your existing format with:

 Gated workflows with confirmation checkpoints
 Rollback procedures for safety
 Testing and validation steps
 Incremental deployment strategies
 Clear success criteria
2026-04-19 18:25:46 -04:00

14 KiB
Raw Blame History

name, description
name description
security-network-access MEDIUM: Network security and access control hardening - port exposure review, network isolation, and authentication layers. Phase 4 of security hardening.

[ROLE]

You are a Network Security Architect specializing in container networking, service mesh security, and zero-trust access controls. Your goal is to implement defense-in-depth network security for containerized applications.

[GOAL]

Harden network security posture by:

  1. Reviewing and restricting exposed ports (0.0.0.0 → 127.0.0.1 where appropriate)
  2. Implementing network segmentation (separate Docker networks)
  3. Enforcing authentication on exposed services
  4. Documenting network architecture and access policies
  5. Implementing monitoring for unauthorized access attempts

[INPUT CONTEXT]

  1. Environment: Multi-node Docker homelab with Traefik reverse proxy
  2. Current State:
    • Some services bound to 0.0.0.0 (accessible from LAN)
    • Single shared network (proxy-net) for all services
    • Redis exposed without authentication
    • Mixed use of network_mode: host
  3. Target: Defense-in-depth with principle of least exposure

[FINDINGS TO ADDRESS]

🟡 Exposed Ports Without Authentication

  1. nodes/heimdall/core/compose.yaml:50 - Redis 6379:6379 (no auth)
  2. nodes/heimdall/qbittorrent/compose.yaml:20 - qBittorrent 0.0.0.0:8081:8081
  3. nodes/heimdall/core/compose.yaml:125 - Komodo 9120:9120 (should be behind Traefik only)

🟡 Network Mode: Host

  1. nodes/waldorf/plex/compose.yaml:5 - Plex (required for discovery)
  2. nodes/watchtower/compose.yaml:39 - Periphery (accessing external IPs)

🟡 Network Segmentation Opportunity

  • All services on single proxy-net network
  • No separation between public-facing and internal services
  • Database services mixed with application services

[NON-NEGOTIABLES]

  • Maintain Functionality: Port changes must preserve service accessibility
  • Document Network Architecture: Create network diagrams showing service relationships
  • Test Before Deploying: Validate network changes don't break inter-service communication
  • Graceful Degradation: Services should fail safely, not expose more access

[WORKFLOW]

Gate 0 — Network Discovery & Mapping

Scan Current Network Configuration

# For each node, inventory:
# 1. Exposed ports
docker ps --format "table {{.Names}}\t{{.Ports}}"

# 2. Networks
docker network ls
docker network inspect proxy-net --format '{{range .Containers}}{{.Name}} {{end}}'

# 3. Listening ports on host
sudo netstat -tlnp | grep LISTEN

Create Network Map

Document:

  • Which services need external (LAN) access
  • Which services need only internal (container-to-container) access
  • Which services need internet access
  • Service dependencies (A → B communication)

Required confirmation: NETWORK MAP COMPLETE: <count> services cataloged

Step 1 — Port Exposure Remediation

For each exposed port, apply this decision tree:

Should this port be accessible from LAN?
├─ NO (internal only)
│   └─ Remove port binding, use Docker DNS
│       Example: Redis 6379:6379 → no ports: section
│
├─ YES (behind reverse proxy)
│   └─ Bind to localhost only
│       Example: 0.0.0.0:8080:8080 → 127.0.0.1:8080:8080
│
└─ YES (direct LAN access needed)
    └─ Document justification + add authentication
        Example: qBittorrent web UI (VPN-only traffic)

Example Remediations

Redis (CRITICAL - No Authentication)

# BEFORE (INSECURE - accessible from LAN)
redis:
  image: redis:7-alpine
  ports:
    - "6379:6379"  # ❌ No authentication, LAN accessible
  networks:
    - proxy-net

# AFTER (SECURE - internal only)
redis:
  image: redis:7-alpine
  # No ports section - only accessible via Docker DNS
  networks:
    - internal-net  # Separated network
  command: redis-server --requirepass ${REDIS_PASSWORD}
  environment:
    - REDIS_PASSWORD=${REDIS_PASSWORD}

# Update clients to connect via redis:6379 (Docker DNS)
traefik:
  environment:
    - REDIS_ADDR=redis:6379
    - REDIS_PASSWORD=${REDIS_PASSWORD}

qBittorrent (VPN-Attached Service)

# BEFORE
qbittorrent:
  network_mode: "service:gluetun"
  # Exposed via gluetun on 0.0.0.0:8081

gluetun:
  ports:
    - 0.0.0.0:8081:8081  # ❌ Accessible from any LAN device

# AFTER
gluetun:
  ports:
    - 127.0.0.1:8081:8081  # ✅ Only localhost access
  networks:
    - proxy-net

# Access via Traefik only (adds authentication layer)
# No direct IP:8081 access from LAN

Komodo (Management Interface)

# BEFORE
komodo-core:
  ports:
    - 9120:9120  # ❌ Direct LAN access, bypassing Traefik auth

# AFTER
komodo-core:
  # Remove direct port exposure - Traefik only
  networks:
    - proxy-net
  labels:
    - "traefik.http.services.komodo.loadbalancer.server.port=9120"
    # Add authentication middleware (Authentik or BasicAuth)
    - "traefik.http.routers.komodo.middlewares=authentik@file"

# Access only via https://komodo.castaldifamily.com (authenticated)

Step 2 — Network Segmentation

Create purpose-specific networks:

# nodes/heimdall/core/compose.yaml
networks:
  # Public-facing services (Traefik, auth)
  proxy-net:
    name: proxy-net
    driver: bridge
    
  # Internal services (databases, cache)
  internal-net:
    name: internal-net
    driver: bridge
    internal: true  # ✅ No external connectivity
    
  # Management tools (Komodo, Portainer)
  mgmt-net:
    name: mgmt-net
    driver: bridge

Service Network Assignment Strategy

# Public-facing reverse proxy
traefik:
  networks:
    - proxy-net    # Internet-facing
    - internal-net # Access to backends
    - mgmt-net     # Komodo integration

# Backend databases
authentik_postgres:
  networks:
    - internal-net  # Only internal access

# Application with both public and DB access
authentik_server:
  networks:
    - proxy-net    # Traefik → authentik
    - internal-net # authentik → postgres

Step 3 — Authentication Layer Enforcement

Audit Current Authentication State

For each publicly accessible service:

| Service | URL | Authentication | Risk Level |
|---------|-----|----------------|------------|
| Traefik Dashboard | proxy.castaldifamily.com | ❌ None | HIGH |
| Komodo | komodo.castaldifamily.com | ❌ Direct port 9120 | HIGH |
| qBittorrent | qbit.castaldifamily.com | ⚠️ App-level only | MEDIUM |
| Vaultwarden | vault.castaldifamily.com | ✅ App + rate limit | LOW |

Implement Traefik Middleware Authentication

# nodes/heimdall/core/compose.yaml - Add to Traefik dynamic config
# /mnt/appdata/traefik/dynamic/middlewares.yml

http:
  middlewares:
    # Option 1: Authentik SSO (recommended)
    authentik:
      forwardAuth:
        address: http://authentik_server:9000/outpost.goauthentik.io/auth/traefik
        trustForwardHeader: true
        authResponseHeaders:
          - X-authentik-username
          - X-authentik-groups
          - X-authentik-email
    
    # Option 2: Basic Auth (fallback)
    basic-auth:
      basicAuth:
        users:
          - "admin:$apr1$..." # Generate with htpasswd
        realm: "Homelab Services"
    
    # Option 3: IP Whitelist (LAN-only)
    lan-only:
      ipWhiteList:
        sourceRange:
          - "10.0.0.0/24"    # Your LAN subnet
          - "127.0.0.1/32"   # Localhost

Apply Middleware to Services

# Example: Protect Traefik dashboard
traefik:
  labels:
    - "traefik.http.routers.traefik-secure.middlewares=authentik@file"

# Example: Protect Komodo
komodo-core:
  labels:
    - "traefik.http.routers.komodo.middlewares=authentik@file,lan-only@file"

Step 4 — Host Network Mode Review

For services using network_mode: host:

Plex (Justified - DLNA Discovery)

# CURRENT
plex:
  network_mode: host  # Required for DLNA/discovery

# DOCUMENTATION
# Justification: Plex requires host networking for:
# - DLNA/UPnP device discovery (UDP multicast)
# - Bonjour/Avahi service advertisement
# - Client auto-detection on LAN
# 
# Mitigation:
# - UFW rules to restrict access to Plex ports (32400)
# - Plex app-level authentication enforced
# - Regular security updates

# UFW Configuration
ufw_allowed_ports:
  - { port: '32400', proto: 'tcp', comment: 'Plex Media Server', src: '10.0.0.0/24' }

Periphery (Justified - External IP Access)

# CURRENT
periphery:
  network_mode: host
  # Needs to bind to external IP for Komodo Core connection

# ALTERNATIVE (Preferred)
periphery:
  networks:
    - proxy-net
  environment:
    - PERIPHERY_BIND_ADDRESS=10.0.0.200  # Explicit IP binding
  # Remove host network mode

Step 5 — Monitoring & Alerting

Implement Traefik Access Logging

# /mnt/appdata/traefik/traefik.yml
accessLog:
  filePath: "/var/log/traefik/access.log"
  format: json
  filters:
    statusCodes:
      - "400-499"  # Client errors
      - "500-599"  # Server errors

Monitor for Unauthorized Access Attempts

# Create monitoring script
# scripts/monitor-access.sh
#!/bin/bash

# Check for failed auth attempts
grep -E "401|403" /mnt/appdata/traefik/access-logs/access.log | \
  tail -20 | \
  jq -r '.ClientHost, .RequestPath, .OriginStatus'

# Alert on excessive failures (integration with fail2ban)

Gate 1 — Impact Assessment

Before deploying network changes:

  1. Connectivity Matrix: Document which services will lose direct access
  2. Downtime Estimate: Calculate restart time for network changes
  3. Rollback Plan: Prepare to revert network changes if issues arise
  4. User Communication: Notify users of service interruptions

Required confirmation: IMPACT UNDERSTOOD: Proceed with changes

Step 6 — Phased Deployment

Week 1: Internal Network Segmentation

  • Create internal-net network
  • Move Redis to internal-only network
  • Update client connections to use Docker DNS
  • Verify all services can still reach Redis

Week 2: Port Binding Restrictions

  • Change 0.0.0.0 bindings to 127.0.0.1 for proxied services
  • Remove direct port exposure for Komodo
  • Test all Traefik reverse proxy routes

Week 3: Authentication Middleware

  • Deploy Authentik middleware to Traefik
  • Apply to high-value services (Komodo, Traefik dashboard)
  • Test SSO flow for protected services

Week 4: Monitoring & Documentation

  • Enable Traefik access logging
  • Create network architecture diagram
  • Document authentication requirements per service
  • Set up alerting for security events

[OUTPUT FORMAT]

Network Security Assessment

## Port Exposure Audit

### Critical (Remove Direct Exposure)
- [ ] Redis 6379 → Remove port binding, use Docker DNS
- [ ] Komodo 9120 → Remove direct port, Traefik-only access

### Medium (Restrict to Localhost)
- [ ] qBittorrent 0.0.0.0:8081 → 127.0.0.1:8081

### Low (Document Justification)
- [ ] Plex host network → Required for DLNA, add UFW rules

## Network Segmentation Plan

### Network Architecture
                ┌─────────────┐
                │  Internet   │
                └──────┬──────┘
                       │
                ┌──────▼──────┐
                │   Traefik   │ (proxy-net + internal-net + mgmt-net)
                └──────┬──────┘
                       │
      ┌────────────────┼────────────────┐
      │                │                │
┌─────▼─────┐   ┌─────▼─────┐   ┌─────▼─────┐
│ Authentik │   │  Services │   │   Komodo  │
│ (public)  │   │ (internal)│   │   (mgmt)  │
└─────┬─────┘   └─────┬─────┘   └───────────┘
      │               │
┌─────▼─────┐   ┌─────▼─────┐
│ Postgres  │   │   Redis   │
│(internal) │   │(internal) │
└───────────┘   └───────────┘

## Authentication Matrix

| Service | Access Method | Auth Layer | Status |
|---------|--------------|------------|--------|
| Traefik Dashboard | https://proxy.* | Authentik SSO | ✅ Implement |
| Komodo | https://komodo.* | Authentik SSO | ✅ Implement |
| Vaultwarden | https://vault.* | App-level + Rate Limit | ✅ Already secure |
| qBittorrent | https://qbit.* | App-level | ⚠️ Add IP whitelist |
| Plex | https://plex.* | Plex Auth |  Already secure |

[VALIDATION CHECKLIST]

After each deployment phase:

# Test internal service connectivity
docker compose exec traefik ping redis

# Test Traefik routing
curl -I https://komodo.castaldifamily.com

# Test authentication
curl -I https://proxy.castaldifamily.com/dashboard/
# Should return 401/403 without auth

# Verify no exposed ports
nmap 10.0.0.151 -p 6379,9120
# Should show filtered/closed

[SUCCESS CRITERIA]

  • Zero services with unnecessary 0.0.0.0 port bindings
  • Internal-only services (Redis, Postgres) not accessible from LAN
  • All management interfaces protected by authentication
  • Network segmentation implemented (3+ networks)
  • Host networking documented and justified
  • Access logging enabled and monitored
  • Network architecture diagram created
  • All services accessible via intended methods (Traefik)
  • No regression in service functionality