diff --git a/01-variables.tf b/01-variables.tf index c6983ec..087d62e 100644 --- a/01-variables.tf +++ b/01-variables.tf @@ -1,7 +1,13 @@ -variable "stackit_project_id" { - type = string - /*default = "XXXXX-XXXX-XXXX-XXXX-XXXXXXX"*/ - default = "d75e6aab-b616-4b42-ae3b-aaf161ad626d" +variable "stackit_project_id_machine01" { + description = "Project ID for machine01" + default = "d75e6aab-b616-4b42-ae3b-aaf161ad626d" + type = string +} + +variable "stackit_project_id_machine02" { + description = "Project ID for machine02" + default = "c30f0bc4-1b8c-430e-adff-9e862d3b2cd0" + type = string } variable "stackit_region" { diff --git a/02-main.tf b/02-main.tf index ce21d07..1e945da 100644 --- a/02-main.tf +++ b/02-main.tf @@ -6,14 +6,14 @@ resource "stackit_key_pair" "admin_keypair" { } resource "stackit_network" "machine01" { - project_id = var.stackit_project_id + project_id = var.stackit_project_id_machine01 ipv4_prefix = "10.1.1.0/24" name = "network-machine01" ipv4_nameservers = ["9.9.9.9", "1.1.1.1"] } resource "stackit_network" "machine02" { - project_id = var.stackit_project_id + project_id = var.stackit_project_id_machine02 ipv4_prefix = "10.2.2.0/24" name = "network-machine02" ipv4_nameservers = ["9.9.9.9", "1.1.1.1"] @@ -24,39 +24,65 @@ resource "stackit_network_interface" "machines" { machine01 = { network_id = stackit_network.machine01.network_id ipv4 = "10.1.1.10" + project_id = var.stackit_project_id_machine01 } machine02 = { network_id = stackit_network.machine02.network_id ipv4 = "10.2.2.10" + project_id = var.stackit_project_id_machine02 } } - project_id = var.stackit_project_id + project_id = each.value.project_id network_id = each.value.network_id ipv4 = each.value.ipv4 security = false } resource "stackit_public_ip" "wan_ips" { - for_each = stackit_network_interface.machines + for_each = { + machine01 = { + network_interface_id = stackit_network_interface.machines["machine01"].network_interface_id + project_id = var.stackit_project_id_machine01 + } + machine02 = { + network_interface_id = stackit_network_interface.machines["machine02"].network_interface_id + project_id = var.stackit_project_id_machine02 + } + } - project_id = var.stackit_project_id + project_id = each.value.project_id network_interface_id = each.value.network_interface_id } locals { - vpn_config = { + machine_ips = { machine01 = { - local_ip = "10.1.1.10" - remote_ip = stackit_public_ip.wan_ips["machine02"].ip - local_subnet = "10.1.1.0/24" - remote_subnet = "10.2.2.0/24" + local_ip = "10.1.1.10" + local_subnet = "10.1.1.0/24" } machine02 = { - local_ip = "10.2.2.10" + local_ip = "10.2.2.10" + local_subnet = "10.2.2.0/24" + } + } + + vpn_config = { + machine01 = { + local_ip = local.machine_ips.machine01.local_ip + remote_ip = stackit_public_ip.wan_ips["machine02"].ip + local_subnet = local.machine_ips.machine01.local_subnet + remote_subnet = local.machine_ips.machine02.local_subnet + leftid = stackit_public_ip.wan_ips["machine01"].ip + rightid = stackit_public_ip.wan_ips["machine02"].ip + } + machine02 = { + local_ip = local.machine_ips.machine02.local_ip remote_ip = stackit_public_ip.wan_ips["machine01"].ip - local_subnet = "10.2.2.0/24" - remote_subnet = "10.1.1.0/24" + local_subnet = local.machine_ips.machine02.local_subnet + remote_subnet = local.machine_ips.machine01.local_subnet + leftid = stackit_public_ip.wan_ips["machine02"].ip + rightid = stackit_public_ip.wan_ips["machine01"].ip } } @@ -71,14 +97,24 @@ locals { } resource "stackit_server" "machines" { - for_each = toset(["machine01", "machine02"]) + for_each = { + machine01 = { + project_id = var.stackit_project_id_machine01 + availability_zone = "eu01-1" + } + machine02 = { + project_id = var.stackit_project_id_machine02 + availability_zone = "eu01-2" + } + } - project_id = var.stackit_project_id + project_id = each.value.project_id name = each.key - availability_zone = "eu01-1" + availability_zone = each.value.availability_zone machine_type = "c1.4" keypair_name = stackit_key_pair.admin_keypair.name - user_data = local.init_config[each.key] + + user_data = local.init_config[each.key] boot_volume = { size = 64 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5dd879 --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# StrongSwan VPN Verification Guide + +This guide helps verify that an IPsec VPN tunnel using StrongSwan is properly established between the following machines +provisioned via Terraform and configured with cloud-init: + +- `machine01` โ†’ IP: `10.1.1.10` +- `machine02` โ†’ IP: `10.2.2.10` + +The VPN uses IKEv2 and a Pre-Shared Key (PSK) to create a site-to-site tunnel automatically on boot. + +--- + +## 1. Check the StrongSwan Service + +SSH into both machines: + +```sh +ssh -i ~/.ssh/id_rsa debian@ +``` + +Once logged in on each peer, run: + +```sh +sudo ipsec statusall +``` + +You should see output like the following: + +``` +Status of IKE charon daemon (strongSwan 5.9.8, Linux ...): + uptime: ... + worker threads: ... +Connections: + net-net: 10.1.1.10...10.2.2.10 IKEv2, dpddelay=30s + net-net: local: [10.1.1.10] uses pre-shared key authentication + net-net: remote: [10.2.2.10] uses pre-shared key authentication + net-net: child: 10.1.1.0/24 === 10.2.2.0/24 TUNNEL +Security Associations (SAs) (0 up, 0 connecting): + none +``` + +At this point, the configuration is loaded but the tunnel might not be up yet. + +--- + +## 2. Bring Up and Verify the VPN Tunnel + +If the VPN does not connect automatically, you can initiate it manually from either peer: + +```sh +sudo ipsec up net-net +``` + +Then recheck the status: + +```sh +sudo ipsec statusall +``` + +You should see something like: + +``` +Connections: + net-net[1]: ESTABLISHED 15s ago, 10.1.1.10...10.2.2.10 + net-net{1}: INSTALLED, TUNNEL, ESP SPIs: ... + net-net{1}: 10.1.1.0/24 === 10.2.2.0/24 +``` + +โœ… Look for the following: +- `ESTABLISHED` โ€” the tunnel is active. +- Correct subnets in `===`, e.g., `10.1.1.0/24 === 10.2.2.0/24`. + +--- + +## ๐Ÿงช 3. Test Connectivity Through the VPN + +Ping from one internal IP to the other (inside each VM): + +```sh +# On machine01 +ping 10.2.2.10 + +# On machine02 +ping 10.1.1.10 +``` + +Expect responses showing that packets are routed through the tunnel. + +--- + +## 4. Optional: Check Routing Table + +Although not strictly necessary, you can confirm local routing with: + +```sh +ip route +``` \ No newline at end of file diff --git a/cloud-init.yaml b/cloud-init.yaml index aa28043..56fe93f 100644 --- a/cloud-init.yaml +++ b/cloud-init.yaml @@ -3,21 +3,24 @@ package_update: true packages: - strongswan - iptables + - net-tools write_files: - path: /etc/ipsec.conf + permissions: '0644' content: | config setup - charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2" + charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2" conn net-net - auto=start + auto=add keyexchange=ikev2 authby=psk - left=%any - leftid=${local_ip} + left=${local_ip} + leftid=${leftid} leftsubnet=${local_subnet} right=${remote_ip} + rightid=${rightid} rightsubnet=${remote_subnet} ike=aes256-sha1-modp1024! esp=aes256-sha1! @@ -26,9 +29,13 @@ write_files: dpdtimeout=120s - path: /etc/ipsec.secrets + permissions: '0600' content: | - ${local_ip} ${remote_ip} : PSK "${psk}" + ${leftid} ${rightid} : PSK "${psk}" runcmd: - sysctl -w net.ipv4.ip_forward=1 - - systemctl enable --now strongswan \ No newline at end of file + - sed -i '/^#net.ipv4.ip_forward=1/c\net.ipv4.ip_forward=1' /etc/sysctl.conf + - sysctl -p + - ipsec start + - ipsec up net-net