terraform: match the servers; open only ports in use
Checked against the Hetzner project: - Both servers have daily backups and delete and rebuild protection switched on, while the code said backups = false and set no protection. An apply would have turned all three off and discarded the existing backups. Record them as they are. - The firewalls had drifted both ways. Live, asxpio-ops also accepts XMPP ports and tcp/5000, and asxpio-services accepts 80, 443, XMPP, TURN, Valheim and Factorio ports; none of those services run. The code in turn missed tcp/25566, where the second Minecraft server listens. Describe the firewalls as they should be: internal networks, plus the public ports of services that run. Public SSH to asxpio-services goes too; sshd and iptables already refuse it from outside the VPN. This is not applied. The next plan will show the stale ports being closed and nothing else. Assisted-by: Claude:fable-5-2
This commit is contained in:
parent
f00505a27d
commit
dc0f732d0f
3 changed files with 68 additions and 261 deletions
|
|
@ -4,9 +4,11 @@ Hetzner Cloud infrastructure managed via Terraform.
|
||||||
|
|
||||||
## Servers
|
## Servers
|
||||||
|
|
||||||
- **asxpio-ops** (2 vCPU, 4GB) - Traefik, Forgejo, app stacks
|
- **asxpio-ops** (CX23: 2 vCPU, 4GB) - Traefik, Forgejo, app stacks
|
||||||
- **asxpio-services** (CX43: 8 vCPU, 16GB) - CI runner, game servers, SillyTavern
|
- **asxpio-services** (CX43: 8 vCPU, 16GB) - CI runner, game servers, SillyTavern
|
||||||
|
|
||||||
|
Both have Hetzner daily backups plus delete and rebuild protection.
|
||||||
|
|
||||||
Both servers carry `prevent_destroy` and ignore changes to `user_data`,
|
Both servers carry `prevent_destroy` and ignore changes to `user_data`,
|
||||||
`image` and `ssh_keys`: cloud-init only runs at first boot, and hcloud
|
`image` and `ssh_keys`: cloud-init only runs at first boot, and hcloud
|
||||||
would otherwise replace a running server when those change. Edits to
|
would otherwise replace a running server when those change. Edits to
|
||||||
|
|
@ -37,7 +39,7 @@ day-to-day configuration is in `../ansible`.
|
||||||
|
|
||||||
| Item | Monthly |
|
| Item | Monthly |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| ops | €3.71 |
|
| ops CX23 | €3.71 |
|
||||||
| services CX43 | €11.15 |
|
| services CX43 | €11.15 |
|
||||||
| IPv4 (2x) | €1.24 |
|
| IPv4 (2x) | €1.24 |
|
||||||
| S3 (1TB) | €6.19 |
|
| S3 (1TB) | €6.19 |
|
||||||
|
|
|
||||||
|
|
@ -1,278 +1,79 @@
|
||||||
|
# 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-25566" }, # Minecraft (Paper, Fossils)
|
||||||
|
{ protocol = "udp", port = "19132" }, # Minecraft Bedrock (Geyser)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
resource "hcloud_firewall" "ops_fw" {
|
resource "hcloud_firewall" "ops_fw" {
|
||||||
name = "asxpio-ops-fw"
|
name = "asxpio-ops-fw"
|
||||||
|
|
||||||
# VPC
|
dynamic "rule" {
|
||||||
rule {
|
for_each = ["tcp", "udp"]
|
||||||
|
content {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "tcp"
|
protocol = rule.value
|
||||||
port = "any"
|
port = "any"
|
||||||
source_ips = [
|
source_ips = local.internal_networks
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "any"
|
|
||||||
source_ips = [
|
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
rule {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "icmp"
|
protocol = "icmp"
|
||||||
source_ips = [
|
source_ips = local.internal_networks
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# WireGuard
|
dynamic "rule" {
|
||||||
rule {
|
for_each = local.ops_public
|
||||||
|
content {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "tcp"
|
protocol = rule.value.protocol
|
||||||
port = "any"
|
port = rule.value.port
|
||||||
source_ips = [
|
source_ips = local.anywhere
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "any"
|
|
||||||
source_ips = [
|
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "icmp"
|
|
||||||
source_ips = [
|
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# SSH TODO: Remove
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "22"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "80"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "443"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# WireGuard VPN
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "60101"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "hcloud_firewall" "services_fw" {
|
resource "hcloud_firewall" "services_fw" {
|
||||||
name = "asxpio-services-fw"
|
name = "asxpio-services-fw"
|
||||||
|
|
||||||
# VPC
|
dynamic "rule" {
|
||||||
rule {
|
for_each = ["tcp", "udp"]
|
||||||
|
content {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "tcp"
|
protocol = rule.value
|
||||||
port = "any"
|
port = "any"
|
||||||
source_ips = [
|
source_ips = local.internal_networks
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "any"
|
|
||||||
source_ips = [
|
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
rule {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "icmp"
|
protocol = "icmp"
|
||||||
source_ips = [
|
source_ips = local.internal_networks
|
||||||
"10.10.0.0/20"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# WireGuard
|
dynamic "rule" {
|
||||||
rule {
|
for_each = local.services_public
|
||||||
|
content {
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "tcp"
|
protocol = rule.value.protocol
|
||||||
port = "any"
|
port = rule.value.port
|
||||||
source_ips = [
|
source_ips = local.anywhere
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "any"
|
|
||||||
source_ips = [
|
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "icmp"
|
|
||||||
source_ips = [
|
|
||||||
"10.20.0.0/24"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# SSH TODO:Remove
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "22"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Minecraft Server
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "25565"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Minecraft Geyser
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "19132"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Valheim Server (UDP port range)
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "2456-2458"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Factorio Server
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "34197"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prosody XMPP - Client connections
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "5222"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prosody XMPP - Server-to-server
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "5269"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prosody XMPP - HTTP/BOSH
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "5280"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prosody XMPP - HTTPS
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "5281"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# TURN/STUN Server (UDP)
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "udp"
|
|
||||||
port = "3478"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# TURN/STUN Server (TCP)
|
|
||||||
rule {
|
|
||||||
direction = "in"
|
|
||||||
protocol = "tcp"
|
|
||||||
port = "3478"
|
|
||||||
source_ips = [
|
|
||||||
"0.0.0.0/0",
|
|
||||||
"::/0"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ resource "hcloud_server" "ops" {
|
||||||
hcloud_ssh_key.deploy.id
|
hcloud_ssh_key.deploy.id
|
||||||
]
|
]
|
||||||
|
|
||||||
backups = false
|
backups = true
|
||||||
|
delete_protection = true
|
||||||
|
rebuild_protection = true
|
||||||
|
|
||||||
public_net {
|
public_net {
|
||||||
ipv4_enabled = true
|
ipv4_enabled = true
|
||||||
|
|
@ -54,7 +56,9 @@ resource "hcloud_server" "services" {
|
||||||
hcloud_ssh_key.deploy.id
|
hcloud_ssh_key.deploy.id
|
||||||
]
|
]
|
||||||
|
|
||||||
backups = false
|
backups = true
|
||||||
|
delete_protection = true
|
||||||
|
rebuild_protection = true
|
||||||
|
|
||||||
public_net {
|
public_net {
|
||||||
ipv4_enabled = true
|
ipv4_enabled = true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue