Files
terraform-binarylane/modules/binarylane/main.tf
T
unkin-agent 6a0b6989ae
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Number the DMZ VPCs 198.18.30.0/24 (syd) and 198.18.31.0/24 (mel)
2026-10-13 21:29:07 +11:00

238 lines
7.8 KiB
Terraform

locals {
# home WAN address of prodnxsr0020, which terminates one wg link per vpn host
router_endpoint = "103.216.191.185"
wg_port = 51820
domain = "main.unkin.net"
# lab destinations reached through each region's vpn host; SMTP stays on the public internet
lab_routes = [
"198.18.0.0/16",
"10.10.12.200/32", # management ssh host
]
# ospf hellos over the p2p links; wg has one peer per interface so this routes to it
ospf_allspf = "224.0.0.5/32"
vpcs = {
syd = "198.18.30.0/24"
mel = "198.18.31.0/24"
}
vpns = {
ausyd2nxvm2131 = { region = "syd", vpc_ip = "198.18.30.11", router_port = 51821, router_address = "198.18.2.176", wg_address = "198.18.2.177", loopback = "198.18.2.161" }
aumel1nxvm2133 = { region = "mel", vpc_ip = "198.18.31.11", router_port = 51822, router_address = "198.18.2.178", wg_address = "198.18.2.179", loopback = "198.18.2.162" }
}
edges = {
ausyd2nxvm2130 = { region = "syd", vpc_ip = "198.18.30.10", vpn = "ausyd2nxvm2131", ptr = "mta1.edge.unkin.net" }
aumel1nxvm2132 = { region = "mel", vpc_ip = "198.18.31.10", vpn = "aumel1nxvm2133", ptr = "mta2.edge.unkin.net" }
}
}
resource "binarylane_vpc" "dmz" {
for_each = local.vpcs
name = "dmz-${each.key}"
ip_range = each.value
}
resource "binarylane_vpc_route_entries" "dmz" {
for_each = local.vpns
vpc_id = binarylane_vpc.dmz[each.value.region].id
route_entries = [for dst in local.lab_routes : {
description = "lab via ${each.key}"
destination = dst
router = binarylane_server.vpn[each.key].private_ipv4_addresses[0]
}]
}
resource "wireguard_asymmetric_key" "router" {
for_each = local.vpns
}
resource "wireguard_asymmetric_key" "vpn" {
for_each = local.vpns
}
resource "vault_kv_secret_v2" "router" {
for_each = local.vpns
mount = "kv"
name = "service/wireguard/binarylane/prodnxsr0020-${each.value.region}"
data_json = jsonencode({
private_key = wireguard_asymmetric_key.router[each.key].private_key
public_key = wireguard_asymmetric_key.router[each.key].public_key
address = "${each.value.router_address}/31"
listen_port = each.value.router_port
})
}
resource "vault_kv_secret_v2" "vpn" {
for_each = local.vpns
mount = "kv"
name = "service/wireguard/binarylane/${each.key}"
data_json = jsonencode({
private_key = wireguard_asymmetric_key.vpn[each.key].private_key
public_key = wireguard_asymmetric_key.vpn[each.key].public_key
address = "${each.value.wg_address}/31"
listen_port = local.wg_port
})
}
resource "binarylane_server" "vpn" {
for_each = local.vpns
name = "${each.key}.${local.domain}"
region = each.value.region
image = "alma-9"
size = "std-min"
public_ipv4_count = 1
vpc_id = binarylane_vpc.dmz[each.value.region].id
vpc_ipv4_address = each.value.vpc_ip
source_and_destination_check = false
backups = false
ipv6 = false
user_data = templatefile("${path.module}/cloud-init.yaml.tftpl", {
hostname = each.key
fqdn = "${each.key}.${local.domain}"
vpn = {
address = "${each.value.wg_address}/31"
loopback = "${each.value.loopback}/32"
routes = local.lab_routes
src = each.value.wg_address
port = local.wg_port
private_key = wireguard_asymmetric_key.vpn[each.key].private_key
router_key = wireguard_asymmetric_key.router[each.key].public_key
router = "${local.router_endpoint}:${each.value.router_port}"
allowed_ips = join(", ", concat(local.lab_routes, [local.ospf_allspf]))
}
routes = null
})
# user_data/image changes reinstall the server in place, wiping its disk
lifecycle {
ignore_changes = [user_data, image]
prevent_destroy = true
}
}
resource "binarylane_server" "edge" {
for_each = local.edges
name = "${each.key}.${local.domain}"
region = each.value.region
image = "alma-9"
size = "std-min"
public_ipv4_count = 1
vpc_id = binarylane_vpc.dmz[each.value.region].id
vpc_ipv4_address = each.value.vpc_ip
port_blocking = false
backups = false
ipv6 = false
user_data = templatefile("${path.module}/cloud-init.yaml.tftpl", {
hostname = each.key
fqdn = "${each.key}.${local.domain}"
vpn = null
routes = {
vpc = local.vpcs[each.value.region]
list = join(", ", [
for dst in local.lab_routes : "${dst} ${local.vpns[each.value.vpn].vpc_ip} src=${each.value.vpc_ip}"
])
}
})
# user_data/image changes reinstall the server in place, wiping its disk
lifecycle {
ignore_changes = [user_data, image]
prevent_destroy = true
}
}
resource "binarylane_server_reverse_name" "edge" {
for_each = local.edges
server_id = binarylane_server.edge[each.key].id
ipv4_address = binarylane_server.edge[each.key].public_ipv4_addresses[0]
reverse_name = each.value.ptr
}
resource "binarylane_server_firewall_rules" "edge" {
for_each = local.edges
server_id = binarylane_server.edge[each.key].id
firewall_rules = [
{
description = "smtp"
protocol = "tcp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.edge[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
destination_ports = ["25"]
action = "accept"
},
{
description = "ssh from the lab via ${each.value.vpn}"
protocol = "tcp"
source_addresses = ["${local.vpns[each.value.vpn].vpc_ip}/32", "10.10.12.200/32"]
destination_addresses = [each.value.vpc_ip]
destination_ports = ["22"]
action = "accept"
},
{
description = "icmp"
protocol = "icmp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.edge[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
action = "accept"
},
{
description = "default deny"
protocol = "all"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.edge[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
action = "drop"
},
]
}
# SSH has no rule: management reaches sshd through wg0, which this firewall never sees.
resource "binarylane_server_firewall_rules" "vpn" {
for_each = local.vpns
server_id = binarylane_server.vpn[each.key].id
firewall_rules = [
{
description = "wireguard from prodnxsr0020"
protocol = "udp"
source_addresses = ["${local.router_endpoint}/32"]
destination_addresses = [binarylane_server.vpn[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
destination_ports = [tostring(local.wg_port)]
action = "accept"
},
{
description = "forward dmz to lab"
protocol = "all"
source_addresses = [local.vpcs[each.value.region]]
destination_addresses = local.lab_routes
action = "accept"
},
{
description = "icmp"
protocol = "icmp"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.vpn[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
action = "accept"
},
{
description = "default deny"
protocol = "all"
source_addresses = ["0.0.0.0/0"]
destination_addresses = [binarylane_server.vpn[each.key].public_ipv4_addresses[0], each.value.vpc_ip]
action = "drop"
},
]
}