An OpenTofu module that boots a tiny EC2 instance which acts as both SSH Socks proxy and Wireguard VPN https://a.l3x.in/blog/throwaway-vpn
  • HCL 95.1%
  • Just 4.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-22 08:41:00 +07:00
.gitignore First draft 2026-09-21 19:31:11 +07:00
.terraform.lock.hcl chore(deps): update terraform aws to ~> 6.66.0 2026-09-21 22:02:34 +00:00
cloud-init.yaml.tftpl First draft 2026-09-21 19:31:11 +07:00
justfile First draft 2026-09-21 19:31:11 +07:00
lefthook.yml First draft 2026-09-21 19:31:11 +07:00
main.tf fix: remove warning about base64 2026-09-21 21:10:39 +07:00
outputs.tf chore: update ssh output, update lock with latest provider 2026-09-21 21:02:49 +07:00
README.md chore: update readme 2026-09-22 08:41:00 +07:00
renovate.json First draft 2026-09-21 19:31:11 +07:00
state.tf chore(deps): update terraform aws to ~> 6.66.0 2026-09-21 22:02:34 +00:00
variables.tf chore: update default CIDR, add version for AWS provider 2026-09-21 20:47:43 +07:00

AWS disposable Ec2 VPN instance

An OpenTofu module that boots a tiny disposable EC2 instance (by default AL2023 on t4g.nano, arm64) which acts as both:

  • a SOCKS proxy over SSH (ssh -D 9999), and
  • a full-tunnel WireGuard VPN

Requirements

  • an AWS account with an Ec2 SSH key resource present. Its name must be set as var.key_name and its public key content to be passed as var.public_key value
  • OpenTofu: brew install opentofu
  • WireGuard: brew install wireguard-tools
  • Just (optional, you can simply use justfile as command reference if you don't want to install): brew install just

What it provisions

  • EC2 instance — Amazon Linux 2023 (arm64), AMI resolved via the official SSM parameter (/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64), so no flaky most_recent AMI lookups forcing surprise replacements.
  • Security group — inbound SSH (22/tcp) and WireGuard (51820/udp) from anywhere, unrestricted egress.
  • WireGuard (cloud-init) — installs wireguard-tools + iptables-nft, writes /etc/wireguard/wg0.conf with keys supplied via tfvars, enables IP forwarding, applies MASQUERADE for full-tunnel NAT, and starts wg-quick@wg0 (enabled across reboots).
  • Optional DNS record — if njalla_domain is set, a CNAME record (vpn.<domain> by default) pointing to the EC2 public DNS is created via the Njalla API. Leave it empty and the feature is off.

Usage

Generate the keypairs locally (no server-side setup needed):

wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee client.key | wg pubkey > client.pub

Fill in terraform.tfvars (see the variable descriptions in variables.tf for the full list): region, SSH key, the required WireGuard keys, and optionally the Njalla ones.

just init apply

Then grab the client config and import it into e.g. the macOS WireGuard app:

just wireguard-conf > wg0.conf
chmod 600 wg0.conf

or use it as SOCKS proxy in the browser, e.g:

ssh -D 9999 ec2-user@ec2-15-160-209-62.eu-south-1.compute.amazonaws.com

To dispose of all the resources:

just destroy

Networking

One CIDR controls the whole tunnel (wireguard_cidr, default 10.100.100.0/24):

Host Address
Server .1 (e.g. 10.100.100.1)
Client .2 (e.g. 10.100.100.2)

Notes

  • WireGuard private keys live in plaintext in terraform.tfvars and terraform.tfstate — both are gitignored; treat state as sensitive.
  • First boot takes a few minutes (package upgrade + reboot-if-required). cloud-init status --wait on the box tells you when it's ready.