| name | vpn-setup |
| description | Configure WireGuard, OpenVPN, and cloud VPNs. Implement secure remote access and site-to-site connectivity. Use when setting up secure network tunnels. |
| license | MIT |
| metadata | {"author":"devops-skills","version":"1.0"} |
VPN Setup
Configure secure VPN tunnels for remote access and site connectivity.
When to Use This Skill
Use this skill when:
- Setting up secure remote access for employees or contractors
- Connecting on-premises networks to cloud environments (site-to-site)
- Encrypting traffic between data centers or regions
- Implementing a mesh VPN for distributed infrastructure
- Providing secure access to internal services without exposing them publicly
Prerequisites
- Linux server with a public IP for VPN endpoint
- Root/sudo access on the VPN server
- Firewall rules allowing VPN traffic (UDP 51820 for WireGuard, UDP 1194 for OpenVPN)
- DNS configured for VPN hostname (optional but recommended)
- Understanding of IP subnetting and routing
WireGuard
Server Setup
apt update && apt install -y wireguard
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
wg genpsk > /etc/wireguard/psk.key
chmod 600 /etc/wireguard/psk.key
Server Configuration
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
DNS = 10.0.0.1
[Peer]
PublicKey = <alice-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.2/32
[Peer]
PublicKey = <bob-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.3/32
[Peer]
PublicKey = <office-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.4/32, 192.168.1.0/24
Endpoint = office.example.com:
=
Client Configuration
[Interface]
Address = 10.0.0.2/24
PrivateKey = <alice-private-key>
DNS = 10.0.0.1
[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Split Tunneling Configuration
[Interface]
Address = 10.0.0.2/24
PrivateKey = <alice-private-key>
[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.0.0.0/24, 172.16.0.0/16, 192.168.1.0/24
PersistentKeepalive = 25
WireGuard Management Commands
wg-quick up wg0
wg-quick down wg0
systemctl enable wg-quick@wg0
wg show
wg show wg0
wg set wg0 peer <new-public-key> allowed-ips 10.0.0.5/32
wg set wg0 peer <public-key> remove
wg show wg0 transfer
apt install -y qr-encode
qrencode -t ansiutf8 < alice-mobile.conf
Peer Management Script
#!/bin/bash
set -euo pipefail
PEER_NAME="${1:?Usage: $0 <peer-name>}"
SERVER_CONF="/etc/wireguard/wg0.conf"
CLIENTS_DIR="/etc/wireguard/clients"
SERVER_PUBKEY=$(cat /etc/wireguard/server_public.key)
SERVER_ENDPOINT="vpn.example.com:51820"
PSK=$(cat /etc/wireguard/psk.key)
LAST_IP=$(grep -oP 'AllowedIPs = 10\.0\.0\.\K[0-9]+' "$SERVER_CONF" | sort -n | tail -1)
NEXT_IP=$((LAST_IP + 1))
mkdir -p "$CLIENTS_DIR"
wg genkey | tee "$CLIENTS_DIR/${PEER_NAME}_private.key" | wg pubkey > "$CLIENTS_DIR/${PEER_NAME}_public.key"
chmod 600 "$CLIENTS_DIR/${PEER_NAME}_private.key"
CLIENT_PRIVKEY=$(cat "$CLIENTS_DIR/${PEER_NAME}_private.key")
CLIENT_PUBKEY=$(cat "$CLIENTS_DIR/${PEER_NAME}_public.key")
cat >> "$SERVER_CONF" << EOF
# Peer: ${PEER_NAME}
[Peer]
PublicKey = ${CLIENT_PUBKEY}
PresharedKey = ${PSK}
AllowedIPs = 10.0.0.${NEXT_IP}/32
EOF
> <<
wg syncconf wg0 <(wg-quick strip wg0)
OpenVPN
Server Setup
apt install -y openvpn easy-rsa
make-cadir /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
openvpn --genkey secret /etc/openvpn/ta.key
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
Server Configuration
port 1194
proto udp
dev tun
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
tls-auth /etc/openvpn/ta.key 0
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
cipher AES-256-GCM
auth SHA256
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3
max-clients 100
client-to-client
Client Configuration
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client1.crt
key client1.key
tls-auth ta.key 1
cipher AES-256-GCM
auth SHA256
verb 3
Tailscale (Managed WireGuard)
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up
tailscale up --advertise-routes=192.168.1.0/24,172.16.0.0/16
tailscale up --advertise-exit-node
tailscale up --exit-node=<exit-node-ip>
tailscale status
cat << 'EOF'
{
"acls": [
{"action": "accept", "src": ["group:engineering"], "dst": ["tag:servers:*"]},
{"action": "accept", "src": ["group:devops"], "dst": ["*:*"]},
{"action": "accept", "src": ["tag:monitoring"], "dst": ["tag:servers:9100"]}
],
"tagOwners": {
"tag:servers": ["group:devops"],
"tag:monitoring": ["group:devops"]
},
"groups": {
"group:engineering": ["alice@example.com", "bob@example.com"],
"group:devops": ["charlie@example.com"]
}
}
EOF
tailscale up --accept-dns
tailscale up --ssh
AWS Site-to-Site VPN
VGW_ID=$(aws ec2 create-vpn-gateway --type ipsec.1 --query 'VpnGateway.VpnGatewayId' --output text)
aws ec2 attach-vpn-gateway --vpn-gateway-id "$VGW_ID" --vpc-id vpc-0abc123
CGW_ID=$(aws ec2 create-customer-gateway \
--type ipsec.1 \
--bgp-asn 65000 \
--public-ip 203.0.113.10 \
--query 'CustomerGateway.CustomerGatewayId' --output text)
VPN_ID=$(aws ec2 create-vpn-connection \
--type ipsec.1 \
--customer-gateway-id "$CGW_ID" \
--vpn-gateway-id "$VGW_ID" \
--options '{"StaticRoutesOnly":false}' \
--query 'VpnConnection.VpnConnectionId' --output text)
aws ec2 describe-vpn-connections --vpn-connection-ids "$VPN_ID"
aws ec2 enable-vgw-route-propagation \
--gateway-id "$VGW_ID" \
--route-table-id rtb-0abc123
aws ec2 describe-vpn-connections \
--vpn-connection-ids "$VPN_ID" \
--query 'VpnConnections[0].VgwTelemetry'
Troubleshooting
| Problem | Cause | Solution |
|---|
| WireGuard handshake never completes | Firewall blocking UDP 51820 | Open UDP 51820 on server firewall and any intermediate firewalls |
| No internet through VPN | IP forwarding disabled or NAT missing | Enable net.ipv4.ip_forward=1; verify PostUp iptables rules |
| DNS not resolving over VPN | DNS not pushed or local DNS conflicts | Set DNS = in client config; check /etc/resolv.conf |
| OpenVPN TLS handshake fails | Certificate mismatch or expired | Verify CA cert matches; check certificate dates with openssl x509 -dates |
| Split tunnel leaks traffic | AllowedIPs too broad | Set only specific subnets in AllowedIPs; verify with traceroute |
| Tailscale node unreachable | ACL blocking traffic | Check Tailscale admin ACL policy; verify node is online with tailscale status |
| AWS VPN tunnel flapping | Idle timeout or DPD misconfigured | Enable DPD on customer gateway; send periodic keep-alive traffic |
| Slow VPN performance | MTU issues causing fragmentation | Set MTU = 1420 in WireGuard config; test with ping -M do -s 1400 |
Best Practices
- Use WireGuard for modern deployments (simpler, faster, smaller attack surface)
- Implement MFA for VPN access where possible
- Rotate keys regularly (quarterly for WireGuard, annual for OpenVPN certs)
- Monitor VPN connections and alert on anomalies
- Segment VPN access by role using split tunneling or ACLs
- Use pre-shared keys with WireGuard for post-quantum resistance
- Keep VPN software updated to patch security vulnerabilities
- Log all VPN connection events for audit purposes
- Disable VPN access immediately when employees leave
- Test failover for site-to-site VPN connections
Related Skills