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%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitignore | ||
| .terraform.lock.hcl | ||
| cloud-init.yaml.tftpl | ||
| justfile | ||
| lefthook.yml | ||
| main.tf | ||
| outputs.tf | ||
| README.md | ||
| renovate.json | ||
| state.tf | ||
| variables.tf | ||
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_nameand its public key content to be passed asvar.public_keyvalue - OpenTofu:
brew install opentofu - WireGuard:
brew install wireguard-tools - Just (optional, you can simply use
justfileas 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 flakymost_recentAMI 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.confwith keys supplied via tfvars, enables IP forwarding, applies MASQUERADE for full-tunnel NAT, and startswg-quick@wg0(enabled across reboots). - Optional DNS record — if
njalla_domainis 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.tfvarsandterraform.tfstate— both are gitignored; treat state as sensitive. - First boot takes a few minutes (package upgrade + reboot-if-required).
cloud-init status --waiton the box tells you when it's ready.