238 lines
7.8 KiB
Terraform
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"
|
|
},
|
|
]
|
|
}
|