Files
rootnode-academy/infra/firewall/proxmox-host.rules
T
ced4568 d2280d0f0d feat(security): production Compose topology, firewall rulesets, Docker mTLS
Named-bridge-network production Compose (not host networking, unlike dev)
for rn-platform-01; egress-proxy + agents for rn-lab-host-01. Caddy reverse
proxy, single public origin, Grafana restricted to management_cidr.
iptables-restore firewall rulesets for all three hosts (Proxmox host,
rn-platform-01, rn-lab-host-01) codifying the Platform/Lab-Host boundary:
no student-to-student traffic, no direct Proxmox exposure, no direct
Postgres/Provisioner exposure from the Lab Host.

Mutual TLS for the Provisioner<->Lab Host Docker connection: certificate
generation/verification scripts, dockerd TLS config, firewall-restricted
port 2376. Application support already existed since Phase 1; this is
purely the operational half.

Validated: docker compose config, caddy validate, firewall structural lint,
and a real openssl s_server/s_client mTLS handshake proving the cert chain
and mutual-auth rejection (legitimate client verified, rogue client
correctly rejected with verify code 19).
2026-08-18 17:13:09 -05:00

43 lines
2.5 KiB
Plaintext

# iptables-restore ruleset for the Proxmox VE hypervisor itself. Applied MANUALLY per
# docs/PRODUCTION_DEPLOYMENT.md §2 — deliberately not Ansible-automated (a mistake in a
# playbook run against the one host that IS the only way to reach every VM console is a much
# worse failure mode than a manual, reviewed apply). Prefer configuring this through Proxmox's
# own Datacenter -> Firewall UI/API where practical instead of hand-editing iptables on the
# hypervisor — this file documents the equivalent policy either way.
#
# Policy summary (docs/PRODUCTION_NETWORK_SECURITY.md §5-6):
# - Proxmox web UI (8006) and SSH (22) reachable ONLY from the management CIDR — never from
# the internet, never from either VM's network, never from a student Lab subnet
# - VM traffic (rn-platform-01 <-> rn-lab-host-01, rn-platform-01 <-> internet via NAT/bridge)
# is FORWARDed by the bridge, not filtered by this hypervisor-level ruleset — that's the
# VMs' own INPUT chains' job (rn-platform-01.rules / rn-lab-host-01.rules)
# - no student Lab subnet, and no rn-lab-host-01 traffic at all, may ever reach Proxmox
# management — this is the literal "Proxmox management not reachable from student Lab
# networks" requirement, enforced at the hypervisor itself, not just hoped-for via VM
# network segmentation
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp --icmp-type echo-request -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 22 -s {{ management_cidr }} -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 8006 -s {{ management_cidr }} -m conntrack --ctstate NEW -j ACCEPT
# Explicit deny + log for the Lab Host VM's network and the student Lab subnet range reaching
# Proxmox management directly — the literal "Proxmox management denied from student Lab
# networks" requirement.
-A INPUT -s {{ lab_host_ip }} -p tcp -m multiport --dports 22,8006 -j LOG --log-prefix "ROOTNODE-DENY-LABHOST-TO-PROXMOX: " --log-level 4
-A INPUT -s {{ lab_host_ip }} -p tcp -m multiport --dports 22,8006 -j DROP
-A INPUT -s {{ lab_subnet_range }} -p tcp -m multiport --dports 22,8006 -j LOG --log-prefix "ROOTNODE-DENY-LAB-TO-PROXMOX: " --log-level 4
-A INPUT -s {{ lab_subnet_range }} -p tcp -m multiport --dports 22,8006 -j DROP
-A INPUT -j LOG --log-prefix "ROOTNODE-DENY-PROXMOX-DEFAULT: " --log-level 4
COMMIT