Skip to content

Instantly share code, notes, and snippets.

@bruceoutdoors
Last active December 30, 2023 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bruceoutdoors/1194470fed8b00d71eeeed0e2e476c61 to your computer and use it in GitHub Desktop.
Save bruceoutdoors/1194470fed8b00d71eeeed0e2e476c61 to your computer and use it in GitHub Desktop.
Quick Wireguard VPN setup for AWS. Just run the CloudFormation stack, access the VM via SSM, and execute `wg-addclient` to add a client. See https://bruceoutdoors.wordpress.com/2023/02/01/how-to-build-a-wireguard-vpn/
#!/bin/bash
# Note: Must run as root!
cd /etc/wireguard/
# Get next available internal IP address
IP=$((`tac wg0.conf | grep -m1 -oP "[0-9]+(?=/32)" || echo 1` + 1))
# Generate client key
CLIENT_PRIVATE=`wg genkey`
CLIENT_PUBLIC=`wg pubkey <<< $CLIENT_PRIVATE`
# Append to server config
cat <<EOF >> wg0.conf
[Peer]
PublicKey = $CLIENT_PUBLIC
AllowedIPs = 10.10.0.$IP/32, fd86:ea04:1111::$IP/128
EOF
# Output client config and render QR
CONF=`mktemp`
trap "rm $CONF" EXIT
cat <<EOF | tee $CONF
[Interface]
PrivateKey = $CLIENT_PRIVATE
Address = 10.10.0.$IP/32
DNS = 8.8.8.8
[Peer]
PublicKey = `cat public.key`
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = `curl -s ifconfig.me`:51820
EOF
cat $CONF | qrencode -t ansiutf8
# Reload the Wireguard service
systemctl reload wg-quick@wg0
#!/bin/bash
apt update
apt install -y wireguard qrencode
cd /etc/wireguard/
# Generate server keys
wg genkey | tee private.key | wg pubkey > public.key
# Write config
NET=`lshw -C network | grep -oP '(?<=logical name: )\w+'`
cat <<EOF > wg0.conf
[Interface]
Address = 10.10.0.1/24
Address = fd86:ea04:1111::1/64
ListenPort = 51820
PostUp = sysctl -q -w net.ipv4.ip_forward=1
PostUp = sysctl -q -w net.ipv6.conf.all.forwarding=1
PostDown = sysctl -q -w net.ipv4.ip_forward=0
PostDown = sysctl -q -w net.ipv6.conf.all.forwarding=0
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o $NET -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o $NET -j MASQUERADE
PrivateKey = `cat private.key`
EOF
# Start Wireguard service on boot
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
AWSTemplateFormatVersion: '2010-09-09'
Description: Set up a wireguard VPN
Parameters:
LatestAmiId:
Description: Grab the latest Ubuntu AMI (see https://ubuntu.com/tutorials/build-your-cloudformation-templates-with-the-latest-ubuntu-ami#2-lets-start)
Default: /aws/service/canonical/ubuntu/server/jammy/stable/current/amd64/hvm/ebs-gp2/ami-id
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
InstanceType:
Default: t2.micro
Description: Instance type
Type: String
Resources:
VpnSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: VPN security group created by cloudformation
SecurityGroupIngress:
- IpProtocol: udp
FromPort: 51820
ToPort: 51820
CidrIp: '0.0.0.0/0'
VpnInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref 'LatestAmiId'
InstanceType: !Ref 'InstanceType'
IamInstanceProfile: !Ref 'WgEc2IamProfile'
UserData: !Base64 |
#!/bin/bash
apt update
apt install -y wireguard qrencode
cd /etc/wireguard/
# Generate server keys
wg genkey | tee private.key | wg pubkey > public.key
# Write config
NET=`lshw -C network | grep -oP '(?<=logical name: )\w+'`
cat <<EOF > wg0.conf
[Interface]
Address = 10.10.0.1/24
Address = fd86:ea04:1111::1/64
ListenPort = 51820
PostUp = sysctl -q -w net.ipv4.ip_forward=1
PostUp = sysctl -q -w net.ipv6.conf.all.forwarding=1
PostDown = sysctl -q -w net.ipv4.ip_forward=0
PostDown = sysctl -q -w net.ipv6.conf.all.forwarding=0
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o $NET -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o $NET -j MASQUERADE
PrivateKey = `cat private.key`
EOF
# Start Wireguard service on boot
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
# Write wg-addclient executable
cat <<'WGADD' > /usr/bin/wg-addclient
#!/bin/bash
# Note: Must run as root!
cd /etc/wireguard/
# Get next available internal IP address
IP=$((`tac wg0.conf | grep -m1 -oP "[0-9]+(?=/32)" || echo 1` + 1))
# Generate client key
CLIENT_PRIVATE=`wg genkey`
CLIENT_PUBLIC=`wg pubkey <<< $CLIENT_PRIVATE`
# Append to server config
cat <<EOF >> wg0.conf
[Peer]
PublicKey = $CLIENT_PUBLIC
AllowedIPs = 10.10.0.$IP/32, fd86:ea04:1111::$IP/128
EOF
# Output client config and render QR
CONF=`mktemp`
trap "rm $CONF" EXIT
cat <<EOF | tee $CONF
[Interface]
PrivateKey = $CLIENT_PRIVATE
Address = 10.10.0.$IP/32
DNS = 8.8.8.8
[Peer]
PublicKey = `cat public.key`
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = `curl -s ifconfig.me`:51820
EOF
cat $CONF | qrencode -t ansiutf8
# Reload the Wireguard service
systemctl reload wg-quick@wg0
WGADD
chmod 755 /usr/bin/wg-addclient
SecurityGroups:
- !Ref 'VpnSecurityGroup'
WireguardEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
WireguardVpnEipAsso:
Type: AWS::EC2::EIPAssociation
Properties:
EIP: !Ref 'WireguardEIP'
InstanceId: !Ref 'VpnInstance'
WgEc2IamRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
WgEc2IamProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref 'WgEc2IamRole'
Outputs:
SSMURL:
Description: Session manager URL. Inside instance, execute `wg-addclient` as root to add client
Value: !Join
- ''
- - https://
- !Ref 'AWS::Region'
- .console.aws.amazon.com/systems-manager/session-manager/
- !Ref 'VpnInstance'
- '?region='
- !Ref 'AWS::Region'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment