Address vpn wg links and loopbacks from 198.18.2.160/27 for ospf
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful

This commit is contained in:
2026-10-12 22:39:17 +11:00
parent 29f3a53143
commit 04f6fd69d3
4 changed files with 40 additions and 7 deletions
+3 -1
View File
@@ -27,7 +27,9 @@ Each DMZ VPC (`syd`, `mel`) holds a postfix edge host and a vpn host. The vpn
host runs wg0 as a /31 point-to-point link to its own prodnxsr0020 interface
(`wg-syd` on 51821, `wg-mel` on 51822; `router_links` output) and forwards the
lab routes for its VPC; the edge host reaches the lab through it and has no
WireGuard. Router keys live at `kv/service/wireguard/binarylane/prodnxsr0020-<region>`.
WireGuard. Link /31s and vpn loopbacks (dum0) come from 198.18.2.160/27. Lab
traffic is sourced from the /31 until Puppet brings up FRR, which peers OSPF
over wg0 and advertises the loopback and VPC to the router. Router keys live at `kv/service/wireguard/binarylane/prodnxsr0020-<region>`.
wg0 is bootstrapped from a key in `user_data` (readable via the BinaryLane
API); Puppet then manages it from Vault, so rotate by replacing
`wireguard_asymmetric_key.vpn` here and letting Puppet roll it out.
+21
View File
@@ -12,12 +12,31 @@ write_files:
Address = ${vpn.address}
ListenPort = ${vpn.port}
PrivateKey = ${vpn.private_key}
# source lab traffic from the /31: the router only learns the loopback and vpc once ospf is up
Table = off
%{ for r in vpn.routes ~}
PostUp = ip route replace ${r} dev wg0 src ${vpn.src}
%{ endfor ~}
[Peer]
PublicKey = ${vpn.router_key}
Endpoint = ${vpn.router}
AllowedIPs = ${vpn.allowed_ips}
PersistentKeepalive = 25
- path: /etc/NetworkManager/system-connections/dum0.nmconnection
permissions: "0600"
content: |
[connection]
id=dum0
type=dummy
interface-name=dum0
[ipv4]
method=manual
address1=${vpn.loopback}
[ipv6]
method=disabled
- path: /etc/sysctl.d/90-ip-forward.conf
content: |
net.ipv4.ip_forward = 1
@@ -39,6 +58,8 @@ write_files:
%{ if vpn != null ~}
rpm -q wireguard-tools >/dev/null || dnf install -y wireguard-tools
sysctl -p /etc/sysctl.d/90-ip-forward.conf
nmcli connection reload
nmcli connection up dum0
systemctl enable --now wg-quick@wg0
wg show wg0 latest-handshakes | awk '$2 > 0 { ok = 1 } END { exit !ok }'
%{ endif ~}
+9 -3
View File
@@ -10,14 +10,17 @@ locals {
"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 = "10.10.14.0/24"
mel = "10.10.15.0/24"
}
vpns = {
ausyd2nxvm2131 = { region = "syd", vpc_ip = "10.10.14.11", router_port = 51821, router_address = "10.10.13.0", wg_address = "10.10.13.1" }
aumel1nxvm2133 = { region = "mel", vpc_ip = "10.10.15.11", router_port = 51822, router_address = "10.10.13.2", wg_address = "10.10.13.3" }
ausyd2nxvm2131 = { region = "syd", vpc_ip = "10.10.14.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 = "10.10.15.11", router_port = 51822, router_address = "198.18.2.178", wg_address = "198.18.2.179", loopback = "198.18.2.162" }
}
edges = {
@@ -97,11 +100,14 @@ resource "binarylane_server" "vpn" {
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, ["${each.value.router_address}/32"]))
allowed_ips = join(", ", concat(local.lab_routes, [local.ospf_allspf]))
}
routes = null
})
+7 -3
View File
@@ -1,5 +1,5 @@
output "hosts" {
description = "Hostname, public IPv4, VPC IPv4 and (vpn hosts) WireGuard public key per host."
description = "Hostname, public IPv4, VPC IPv4 and (vpn hosts) wg address, loopback and public key per host."
value = merge(
{ for k, v in binarylane_server.edge : k => {
hostname = v.name
@@ -11,21 +11,25 @@ output "hosts" {
public_ipv4 = v.public_ipv4_addresses[0]
vpc_ipv4 = local.vpns[k].vpc_ip
wg_address = local.vpns[k].wg_address
loopback = local.vpns[k].loopback
wg_pubkey = wireguard_asymmetric_key.vpn[k].public_key
} },
)
}
output "router_links" {
description = "Per-region p2p wg link as prodnxsr0020 sees it; consumed by its Puppet config."
description = "Per-region p2p wg/ospf link as prodnxsr0020 sees it; vpc_cidr arrives via ospf. Consumed by its Puppet config."
value = { for k, v in local.vpns : v.region => {
interface = "wg-${v.region}"
listen_port = v.router_port
router_address = "${v.router_address}/31"
peer_address = v.wg_address
peer_address = "${v.wg_address}/31"
peer_loopback = "${v.loopback}/32"
allowed_ips = ["${v.wg_address}/32", "${v.loopback}/32", local.vpcs[v.region], local.ospf_allspf]
peer_public_key = wireguard_asymmetric_key.vpn[k].public_key
peer_endpoint = "${binarylane_server.vpn[k].public_ipv4_addresses[0]}:${local.wg_port}"
vpc_cidr = local.vpcs[v.region]
private_key_vault_path = "kv/${vault_kv_secret_v2.router[k].name}"
peer_key_vault_path = "kv/${vault_kv_secret_v2.vpn[k].name}"
} }
}