First egress rule in matrix, authentik and monitoring. It allows DNS, the cluster ranges and the whole internet, and denies only 169.254.0.0/16 - link-local, where Hetzner serves instance metadata unauthenticated to any pod. Deliberately narrow. The textbook cut, 0.0.0.0/0 except RFC1918, would have severed two things here, both over 10.0.0.3 on the private Hetzner network: Alloy writes metrics and logs there, and the TURN rotation reaches Gitea through a hostAlias to that address. Private ranges therefore stay open. The payoff is modest and should be stated as such: measured from a pod, the service answers with instance-id, hostname, region, MAC and network config, while userdata and public-keys are empty. No credentials are exposed here, unlike the AWS case this hardening usually targets. It costs nothing though, and it closes the class. Two preconditions checked rather than assumed, because both are the usual way this breaks: kube-system carries kubernetes.io/metadata.name so the DNS rule actually matches, and the cluster is IPv4-only so 0.0.0.0/0 really does cover everything. Rollback is deleting the one policy per namespace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
2.0 KiB
YAML
54 lines
2.0 KiB
YAML
---
|
|
# Egress: alles bleibt erlaubt AUSSER dem Metadaten-Dienst (management #0088).
|
|
#
|
|
# Warum so schmal? Der Lehrbuch-Schnitt (0.0.0.0/0 except RFC1918) haette hier zwei
|
|
# Dinge zerrissen, beide ueber 10.0.0.3 (CFGMON im privaten Hetzner-Netz): Alloy
|
|
# schreibt Metriken und Logs dorthin, und der TURN-Rotations-CronJob erreicht Gitea
|
|
# ueber einen hostAlias auf dieselbe Adresse. Private Netze bleiben deshalb offen.
|
|
#
|
|
# 169.254.0.0/16 ist Link-Local; darin liegt bei Hetzner unter 169.254.169.254 der
|
|
# Metadaten-Dienst, aus jedem Pod unauthentifiziert abfragbar (nachgemessen 2026-08-19:
|
|
# HTTP 200 mit instance-id, hostname, region, MAC, Netzkonfiguration). userdata und
|
|
# public-keys waren LEER - es liegen hier also keine Zugangsdaten offen. Der Gewinn ist
|
|
# entsprechend bescheiden; der Schnitt kostet aber nichts und schliesst die Klasse.
|
|
#
|
|
# ACHTUNG beim Erweitern: Sobald eine Egress-Regel fuer einen Pod existiert, gilt fuer
|
|
# ihn Default-Deny fuer alles NICHT Aufgefuehrte. Die drei Bloecke unten sind daher
|
|
# Pflicht, nicht Bequemlichkeit - insbesondere DNS: fehlt es, steht alles, und der
|
|
# Fehler sieht wie ein Anwendungsproblem aus, nicht wie eine Firewall.
|
|
#
|
|
# Rollback: diese eine Policy im Namespace loeschen.
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: egress-block-metadata
|
|
namespace: monitoring
|
|
spec:
|
|
podSelector: {}
|
|
policyTypes:
|
|
- Egress
|
|
egress:
|
|
# 1. DNS - zuerst, weil ohne DNS nichts geht.
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: kube-system
|
|
ports:
|
|
- protocol: UDP
|
|
port: 53
|
|
- protocol: TCP
|
|
port: 53
|
|
# 2. Cluster-intern: Pods und Services (inkl. API-Server 10.43.0.1).
|
|
- to:
|
|
- ipBlock:
|
|
cidr: 10.42.0.0/16
|
|
- ipBlock:
|
|
cidr: 10.43.0.0/16
|
|
# 3. Alles uebrige - Foederation, ACME, SMTP, Registries, privates Netz -
|
|
# ausser Link-Local.
|
|
- to:
|
|
- ipBlock:
|
|
cidr: 0.0.0.0/0
|
|
except:
|
|
- 169.254.0.0/16
|