I began this project with the idea that it would be pretty cool if I could just setup one AWS ec2 instance and route my kali linux VM's traffic through that instance using wireguard. I began setting it up while taking detailed notes throughout the process and was able to get it up and running successfully. I realized that even though setting everything up by hand taught me a lot, it also felt a bit tedious. That’s when I decided this whole setup would be way more useful if I could automate it. Since I already had detailed notes to work with, I started digging into ways I could turn those steps into a repeatable process. That way, instead of just being a one-off project, it could be something I can spin up quickly whenever I need it.
"""David Enfinger: 08-6-25"""
import boto3
ec2 = boto3.resource('ec2', region_name='us-east-1')
instances = ec2.create_instances(
ImageId='[Insert AMI ID]',
InstanceType='t2.micro',
MinCount=1,
MaxCount=1,
KeyName='[Insert Priv key name]',
SecurityGroupIds=['Insert Security group ID'] # NOTE: Make sure SG ID allows inbound traffic on 51820/UDP for WG
)
instance = instances[0]
print(f"Launching instance {instance.id}...")
instance.wait_until_running()
instance.load()
print(f"Instance running: {instance.public_ip_address}")
# saves to Ansible inventory
with open('ec2_inventory.ini', 'w') as f:
f.write(f"[wireguard]\n{instance.public_ip_address} ansible_user=ubuntu ansible_ssh_private_key_file='/hle='[PATH TO PRIV KEY]'\n")
- name: Setup WireGuard VPN server
hosts: wireguard
become: yes
vars:
wg_port: 51820
server_private_key_path: /etc/wireguard/server_private.key
client_temp_path: /tmp/wg0-client.conf
client_local_path: ~/Desktop/wg0-client.conf
tasks:
- name: Install WireGuard
apt:
name: wireguard
state: present
update_cache: yes
- name: Enable IP forwarding
sysctl:
name: net.ipv4.ip_forward
value: '1'
state: present
reload: yes
- name: Generate server private key
command: wg genkey
register: server_private
changed_when: false
- name: Save server private key
copy:
content: "{{ server_private.stdout }}"
dest: "{{ server_private_key_path }}"
owner: root
group: root
mode: '600'
- name: Generate server public key
shell: echo {{ server_private.stdout }} | wg pubkey
register: server_public
changed_when: false
- name: Generate client private key
command: wg genkey
register: client_private
changed_when: false
- name: Generate client public key
shell: echo {{ client_private.stdout }} | wg pubkey
register: client_public
changed_when: false
- name: Create server config
copy:
dest: /etc/wireguard/wg0.conf
content: |
[Interface]
Address = 10.0.0.1/24
ListenPort = {{ wg_port }}
PrivateKey = {{ server_private.stdout }}
[Peer]
PublicKey = {{ client_public.stdout }}
AllowedIPs = 10.0.0.2/32
- name: Start WireGuard server
shell: wg-quick down wg0 || true && wg-quick up wg0
- name: Create client config on EC2
copy:
dest: "{{ client_temp_path }}"
content: |
[Interface]
Address = 10.0.0.2/24
PrivateKey = {{ client_private.stdout }}
DNS = 1.1.1.1
[Peer]
PublicKey = {{ server_public.stdout }}
Endpoint = {{ ansible_host }}:{{ wg_port }}
AllowedIPs = 0.0.0.0/0
owner: ubuntu
group: ubuntu
mode: '600'
- name: Fetch client config to local Kali Desktop
fetch:
src: "{{ client_temp_path }}"
dest: "{{ client_local_path }}"
flat: yes