Network Security & LAN Isolation
This document details the Cilium network policy that isolates Kubernetes pods from the local network, preventing lateral movement attacks while allowing legitimate traffic.
Overview
Section titled “Overview”The cluster uses a CiliumClusterwideNetworkPolicy to implement a “default deny” stance for LAN access. This provides an 80/20 security solution - one policy that protects all pods without requiring per-app network policies.
The Threat Model
Section titled “The Threat Model”When hosting public-facing applications (via Cloudflare Tunnel), an attacker who exploits a vulnerability could:
- Gain shell access inside a pod
- Scan the internal network
- Pivot to attack other LAN devices (router, NAS, other servers)
graph LR subgraph "Internet" Attacker[Attacker] end
subgraph "Cloudflare" CF[Cloudflare Tunnel] end
subgraph "Kubernetes Cluster" VulnPod[Vulnerable Pod] end
subgraph "LAN (192.168.10.0/24)" Router[Router .1] NAS[TrueNAS .133] Other[Other Devices] end
Attacker -->|1. Exploit| CF CF -->|2. RCE| VulnPod VulnPod -.->|3. Pivot BLOCKED| Router VulnPod -.->|3. Pivot BLOCKED| Other
style VulnPod fill:#f96,stroke:#333,stroke-width:2px style Router fill:#f66,stroke:#333,stroke-width:2pxThe Solution: CiliumClusterwideNetworkPolicy
Section titled “The Solution: CiliumClusterwideNetworkPolicy”Located at: infrastructure/networking/cilium/policies/block-lan-access.yaml
What Gets Blocked
Section titled “What Gets Blocked”| Traffic | Status | Reason |
|---|---|---|
| RFC1918 ranges (10.x, 172.16.x, 192.168.x) | BLOCKED | Prevents LAN scanning |
| Router (192.168.10.1) | BLOCKED | Prevents admin/SSH access |
| Random LAN devices | BLOCKED | No lateral movement |
What Gets Allowed
Section titled “What Gets Allowed”| Traffic | Status | Reason |
|---|---|---|
| Internet (public IPs) | ALLOWED | Apps need external APIs |
| Pod-to-Pod (cluster) | ALLOWED | Inter-service communication |
| Kube-apiserver | ALLOWED | Kubernetes operations |
| DNS (CoreDNS) | ALLOWED | Name resolution |
| TrueNAS (specific ports) | ALLOWED | NFS/SMB/RustFS storage |
| LoadBalancer IPs | ALLOWED | Cilium L2 announcements |
Policy Architecture
Section titled “Policy Architecture”graph TD subgraph "Egress Rules" Internet[Internet<br/>0.0.0.0/0 EXCEPT RFC1918] Cluster[Cluster Entities<br/>pods, nodes, apiserver] Storage[Whitelisted Storage<br/>TrueNAS: NFS,SMB,RustFS] LB[LoadBalancer Pool<br/>192.168.10.32/27] end
subgraph "All Pods" Pod[Any Pod] end
subgraph "Blocked" LAN[LAN Devices<br/>192.168.10.x] Router[Router<br/>192.168.10.1] end
Pod -->|ALLOWED| Internet Pod -->|ALLOWED| Cluster Pod -->|ALLOWED| Storage Pod -->|ALLOWED| LB Pod -.->|BLOCKED| LAN Pod -.->|BLOCKED| Router
style LAN fill:#f66,stroke:#333 style Router fill:#f66,stroke:#333 style Internet fill:#6f6,stroke:#333 style Cluster fill:#6f6,stroke:#333Whitelisted LAN Resources
Section titled “Whitelisted LAN Resources”These specific IPs are allowed on specific ports only:
| IP | Hostname | Allowed Ports | Purpose |
|---|---|---|---|
| 192.168.10.133 | TrueNAS | 2049 (NFS), 111 (RPC), 445 (SMB), 9000, 30292-30293 (RustFS S3) | Storage backend (10G) |
| 192.168.10.46 | Wyze Bridge | 8554 (RTSP) | Camera streams for Frigate |
| 192.168.10.14 | Proxmox | 8006 (API) | Omni/Terraform integration |
| 192.168.10.32/27 | LB Pool | All | Cilium L2 LoadBalancer IPs |
Why Lateral Movement Fails
Section titled “Why Lateral Movement Fails”The policy uses endpointSelector: {} which matches ALL pods in the cluster:
spec: endpointSelector: {} # <-- Applies to EVERY podThis means:
- DVWA pod cannot reach LAN
- n8n pod cannot reach LAN
- If attacker pivots from DVWA → n8n, n8n STILL cannot reach LAN
sequenceDiagram participant Attacker participant DVWA as DVWA Pod participant N8N as n8n Pod participant Router as Router (192.168.10.1)
Attacker->>DVWA: Exploit vulnerability Note over DVWA: Shell access gained
DVWA->>Router: ping 192.168.10.1 Router--xDVWA: BLOCKED (100% packet loss)
DVWA->>N8N: Pivot to n8n pod Note over N8N: Lateral movement works
N8N->>Router: ping 192.168.10.1 Router--xN8N: STILL BLOCKED
Note over Attacker,Router: No matter which pod,<br/>LAN is unreachableTesting the Policy
Section titled “Testing the Policy”Quick Test (from any pod)
Section titled “Quick Test (from any pod)”# Test LAN access (should fail)kubectl exec -n <namespace> <pod> -- ping -c 1 -W 2 192.168.10.1
# Test internet access (should work)kubectl exec -n <namespace> <pod> -- ping -c 2 8.8.8.8Full Pentest Simulation
Section titled “Full Pentest Simulation”Deploy DVWA (Damn Vulnerable Web Application) for realistic testing:
- Access
https://dvwa.vanillax.me - Login:
admin/password - Set security to “Low”
- Navigate to Command Injection
- Try:
; ping -c 1 -W 2 192.168.10.1
Expected Result: 100% packet loss (LAN blocked)
Verify from Multiple Pods
Section titled “Verify from Multiple Pods”# Test from different namespacesfor ns in dvwa n8n immich; do echo "=== Testing from $ns ===" kubectl exec -n $ns deploy/${ns} -- ping -c 1 -W 2 192.168.10.1 2>&1 | grep -E "packet loss|PING"doneHubble Observability
Section titled “Hubble Observability”Use Hubble to see policy enforcement in real-time:
# Watch for dropped traffichubble observe --verdict DROPPED --to-ip 192.168.10.0/24
# Watch specific podhubble observe --pod dvwa/dvwa --verdict DROPPEDTroubleshooting
Section titled “Troubleshooting”App Can’t Reach Required LAN Resource
Section titled “App Can’t Reach Required LAN Resource”Add a specific whitelist rule:
- toCIDR: - 192.168.10.X/32 # The IP you need toPorts: - ports: - port: "XXXX" # Only the required port protocol: TCPPolicy Not Taking Effect
Section titled “Policy Not Taking Effect”- Check Cilium agent is running:
kubectl get pods -n kube-system -l k8s-app=cilium - Verify policy is applied:
kubectl get ciliumclusterwidenetworkpolicies - Check Hubble for verdicts:
hubble observe --pod <your-pod>
Internet Stopped Working
Section titled “Internet Stopped Working”Ensure toEntities: host is present - this allows traffic to reach the node which then NATs to the internet.
Security Considerations
Section titled “Security Considerations”- Minimize Whitelists: Only add LAN IPs that are absolutely necessary
- Port Restrict: Always specify ports, never allow all ports to a LAN IP
- No Router Access: Never whitelist 192.168.10.1 (your gateway)
- Regular Audits: Review whitelisted IPs periodically