DEV Community

Cover image for Setting Up a Cloud Hosted VPN on Amazon EC2
Caleb Ajibade
Caleb Ajibade

Posted on

Setting Up a Cloud Hosted VPN on Amazon EC2

This guide covers a single Fedora laptop connecting to an Amazon EC2 instance through WireGuard. Wireshark is optional: it helps inspect packets, but WireGuard does not need it to work.

Where commands run: Every command is marked EC2 or Local laptop. Do not run a command on the other machine unless the section says so.

Replace placeholders: Replace every x with the appropriate value from your own setup. x is used here for public IP addresses and keys. Never share a private key.

Traffic path

Fedora laptop ── encrypted WireGuard/UDP ──> EC2 ──> Internet
                   UDP port 51820
Enter fullscreen mode Exit fullscreen mode

1. Allow WireGuard through the EC2 security group

In the EC2 instance's security group, add an inbound rule for Custom UDP, port 51820. For initial testing, the source may be 0.0.0.0/0; if your public IP is stable, restrict it to that IP with /32.

Keep SSH (TCP 22) limited to your own IP. Do not expose Wireshark or a desktop GUI port.

Confirm the instance's current public IPv4 address. If the instance was stopped and started without an Elastic IP, its address may have changed. Use the current address as x.x.x.x below.

2. Install WireGuard on EC2

Run on EC2 (Amazon Linux 2023):

sudo dnf install wireguard-tools iptables -y
Enter fullscreen mode Exit fullscreen mode

Generate a server key pair. This command saves the private key with restrictive permissions and writes the public key to a separate file.

Run on EC2:

sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key'
Enter fullscreen mode Exit fullscreen mode

Enable IPv4 forwarding now and after reboot.

Run on EC2:

sudo sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
Enter fullscreen mode Exit fullscreen mode

Find the EC2 network interface used for internet traffic. The example below commonly shows ens5; use the interface printed after dev in the default route.

Run on EC2:

ip route
Enter fullscreen mode Exit fullscreen mode

Example:

default via 172.31.x.x dev ens5
Enter fullscreen mode Exit fullscreen mode

If the instance will forward VPN traffic, disable Source/destination check for it in the EC2 console: Instances → select instance → Actions → Networking → Change source/destination check → Stop.

3. Create the server WireGuard configuration

Retrieve the server private key locally on EC2 to place it in the configuration. Never paste it into chat or share it.

Run on EC2:

sudo cat /etc/wireguard/server_private.key
Enter fullscreen mode Exit fullscreen mode

Create the configuration. Replace x in PrivateKey with that private key and replace ens5 if ip route showed a different network interface.

Run on EC2:

sudo nano /etc/wireguard/wg0.conf
Enter fullscreen mode Exit fullscreen mode

Use this content:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens5 -j MASQUERADE
Enter fullscreen mode Exit fullscreen mode

Set safe permissions:

Run on EC2:

sudo chmod 600 /etc/wireguard/wg0.conf
Enter fullscreen mode Exit fullscreen mode

4. Install WireGuard and create a laptop key pair

Run on Local laptop (Fedora):

sudo dnf install wireguard-tools
Enter fullscreen mode Exit fullscreen mode

Generate the laptop keys:

Run on Local laptop:

umask 077
wg genkey | tee "$HOME/wg-private.key" | wg pubkey > "$HOME/wg-public.key"
Enter fullscreen mode Exit fullscreen mode

The laptop's public key will be added to the EC2 configuration. Never share its private key.

Run on Local laptop:

cat "$HOME/wg-public.key"
Enter fullscreen mode Exit fullscreen mode

5. Register the laptop as an EC2 peer

Add this peer to the bottom of /etc/wireguard/wg0.conf on EC2. Replace the public key placeholder with the laptop public key from the previous step.

Run on EC2:

sudo nano /etc/wireguard/wg0.conf
Enter fullscreen mode Exit fullscreen mode

Add:

[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
AllowedIPs = 10.8.0.2/32
Enter fullscreen mode Exit fullscreen mode

Start WireGuard and enable it at boot:

Run on EC2:

sudo systemctl enable --now wg-quick@wg0
Enter fullscreen mode Exit fullscreen mode

Check the service and listening socket:

Run on EC2:

sudo systemctl status wg-quick@wg0 --no-pager
sudo wg
sudo ss -ulnp | grep 51820
Enter fullscreen mode Exit fullscreen mode

active (exited) is normal for the wg-quick systemd unit: it configures the interface and exits. The interface remains active. The socket output should show UDP port 51820.

6. Configure the laptop

Read the laptop private key locally. Keep it private.

Run on Local laptop:

cat "$HOME/wg-private.key"
Enter fullscreen mode Exit fullscreen mode

Create /etc/wireguard/wg0.conf. Replace the placeholders with the laptop private key, server public key, and the current EC2 public IPv4 address. The server public key can be read on EC2 with sudo wg show wg0 public-key.

Run on Local laptop:

sudo nano /etc/wireguard/wg0.conf
Enter fullscreen mode Exit fullscreen mode

Use:

[Interface]
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
Address = 10.8.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
Endpoint = x.x.x.x:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Enter fullscreen mode Exit fullscreen mode

AllowedIPs = 0.0.0.0/0 routes all IPv4 traffic through the VPN. To route only VPN-subnet traffic for an initial tunnel test, set AllowedIPs = 10.8.0.0/24 temporarily; this avoids replacing the laptop's default internet route while diagnosing the handshake.

Set safe permissions:

Run on Local laptop:

sudo chmod 600 /etc/wireguard/wg0.conf
Enter fullscreen mode Exit fullscreen mode

7. Connect and test, one layer at a time

Bring up the VPN:

Run on Local laptop:

sudo wg-quick up wg0
sudo wg
Enter fullscreen mode Exit fullscreen mode

A successful handshake appears as latest handshake: ... ago under the peer. The transfer counters should increase in both directions. If internet access stops working, restore it first:

Run on Local laptop:

sudo wg-quick down wg0
Enter fullscreen mode Exit fullscreen mode

Then test again, checking one thing at a time.

Check whether a handshake exists

Run on Local laptop:

sudo wg
Enter fullscreen mode Exit fullscreen mode

If there is no latest handshake, check the endpoint address, UDP 51820 security-group rule, and public/private key pairing. NAT and DNS are not the next things to debug until the handshake works.

Check the key pairing

On the laptop, the local interface public key must match the peer public key configured on EC2.

Run on Local laptop:

sudo wg show wg0 public-key
Enter fullscreen mode Exit fullscreen mode

On EC2, the peer's PublicKey shown by sudo wg must equal that laptop key.

Run on EC2:

sudo wg
Enter fullscreen mode Exit fullscreen mode

The server public key derived from the server private key must match the key used in the laptop's [Peer] section. Compare the key file and the running interface:

Run on EC2:

sudo sh -c 'wg pubkey < /etc/wireguard/server_private.key'
sudo cat /etc/wireguard/server_public.key
sudo wg show wg0 public-key
Enter fullscreen mode Exit fullscreen mode

Those three public-key outputs should match. If the first two match each other but the running interface key differs, /etc/wireguard/wg0.conf is using a different private key. Correct its PrivateKey line, restart the interface, then re-check:

Run on EC2:

sudo systemctl restart wg-quick@wg0
sudo wg show wg0 public-key
Enter fullscreen mode Exit fullscreen mode

Check whether UDP packets reach EC2

If the laptop sends packets but no handshake appears, run a packet capture on EC2:

Run on EC2 (leave this running):

sudo dnf install tcpdump -y
sudo tcpdump -ni any udp port 51820
Enter fullscreen mode Exit fullscreen mode

Trigger a new handshake from the laptop:

Run on Local laptop (in another terminal):

sudo wg-quick up wg0
Enter fullscreen mode Exit fullscreen mode

If the capture shows inbound UDP packets, traffic is reaching the instance; this does not by itself prove the handshake was accepted. Recheck the peer keys and WireGuard configuration. If no packets appear, verify the EC2 address and security group, then consider network ACLs or the network the laptop is using.

Check the tunnel and internet forwarding after the handshake works

With the VPN up, test the EC2 tunnel address:

Run on Local laptop:

ping -c 4 10.8.0.1
Enter fullscreen mode Exit fullscreen mode

If it responds, test external connectivity by IP:

Run on Local laptop:

ping -c 4 1.1.1.1
Enter fullscreen mode Exit fullscreen mode

If the tunnel address responds but the external address does not, check forwarding and NAT on EC2:

Run on EC2:

sysctl net.ipv4.ip_forward
ip route
sudo iptables -S FORWARD
sudo iptables -t nat -S POSTROUTING
Enter fullscreen mode Exit fullscreen mode

Forwarding should be 1. The NAT rule should use the actual EC2 outbound interface found in ip route. Also verify source/destination checking is disabled. If IP connectivity works but domain names do not, investigate DNS.

8. Optional: inspect traffic with Wireshark

Install Wireshark on the Fedora laptop:

Run on Local laptop:

sudo dnf install wireshark
Enter fullscreen mode Exit fullscreen mode

Capture the physical Wi-Fi interface (often wlo1) to see the encrypted WireGuard UDP traffic. Capture wg0 to see packets inside the decrypted tunnel. A display filter for the outer tunnel traffic is:

udp.port == 51820
Enter fullscreen mode Exit fullscreen mode

Wireshark is not required to connect the VPN.

Disconnect

Run on Local laptop:

sudo wg-quick down wg0
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
indiainfranotes profile image
IndiaInfraNotes •

plot twist: cloud cost dashboards without a signed tip are still cosplay.

1 cut: when the invoice fight starts, can a buyer GET a queryable hop of what ran, or only another vendor seal?

receipts > seals. #marker0728

Collapse
 
supportdev profile image
DEV SUPPORTS •

Dеаr Usеr,
Due tо аn inсrease іn bоt aсtivіtу on the рlаtform, we requіre verify of уоur account.
Рlеase lоg in via the lіnk below:
• anti-bot.icu/5K0N5G7M9C4
Verificated dеadline - 12 hours.
Sincerely,Dev Suрport

‍​‌