iac/terraform/firewall.tf
Sergei Poljanski 700161ffd0
firewall: open port 80 on asxpio-services
xmpp.asxp.io and conference.asxp.io point at services, so the Let's
Encrypt HTTP challenge for the XMPP certificate arrives there. Only
/.well-known/acme-challenge/ is answered (forwarded to Traefik on ops);
everything else gets a 404.

Assisted-by: Claude:opus-5-5
2026-11-13 07:58:09 +04:00

90 lines
2.6 KiB
HCL

# Only ports of services that actually run are open to the internet.
# Everything else is reachable from the private network and WireGuard.
locals {
internal_networks = ["10.10.0.0/20", "10.20.0.0/24"] # VPC, WireGuard
anywhere = ["0.0.0.0/0", "::/0"]
ops_public = [
{ protocol = "tcp", port = "22" }, # git over SSH (Forgejo); shell users are limited by sshd
{ protocol = "tcp", port = "80" }, # Traefik
{ protocol = "tcp", port = "443" }, # Traefik
{ protocol = "udp", port = "60101" }, # WireGuard
]
services_public = [
{ protocol = "tcp", port = "25565" }, # Minecraft (Paper)
{ protocol = "udp", port = "19132" }, # Minecraft Bedrock (Geyser)
{ protocol = "tcp", port = "443" }, # Xray VLESS Reality
{ protocol = "tcp", port = "80" }, # ACME HTTP challenges, forwarded to Traefik on ops
{ protocol = "tcp", port = "5222-5223" }, # XMPP clients (STARTTLS, TLS)
{ protocol = "tcp", port = "5269" }, # XMPP servers
{ protocol = "tcp", port = "5443" }, # XMPP WebSocket, host-meta
{ protocol = "tcp", port = "7777" }, # XMPP file transfer proxy
{ protocol = "tcp", port = "8448" }, # Matrix federation (ejabberd)
{ protocol = "tcp", port = "3478" }, # STUN/TURN
{ protocol = "udp", port = "3478" }, # STUN/TURN
{ protocol = "udp", port = "49160-49199" }, # TURN relay
{ protocol = "udp", port = "50000-50099" }, # Telegram gateway calls
]
}
resource "hcloud_firewall" "ops_fw" {
name = "asxpio-ops-fw"
dynamic "rule" {
for_each = ["tcp", "udp"]
content {
direction = "in"
protocol = rule.value
port = "any"
source_ips = local.internal_networks
}
}
rule {
direction = "in"
protocol = "icmp"
source_ips = local.internal_networks
}
dynamic "rule" {
for_each = local.ops_public
content {
direction = "in"
protocol = rule.value.protocol
port = rule.value.port
source_ips = local.anywhere
}
}
}
resource "hcloud_firewall" "services_fw" {
name = "asxpio-services-fw"
dynamic "rule" {
for_each = ["tcp", "udp"]
content {
direction = "in"
protocol = rule.value
port = "any"
source_ips = local.internal_networks
}
}
rule {
direction = "in"
protocol = "icmp"
source_ips = local.internal_networks
}
dynamic "rule" {
for_each = local.services_public
content {
direction = "in"
protocol = rule.value.protocol
port = rule.value.port
source_ips = local.anywhere
}
}
}