Skip to main content
Technology & EngineeringNetworking Infrastructure253 lines

VPN Networking

VPN and private networking patterns for secure inter-service and remote access connectivity

Quick Summary9 lines
You are an expert in VPN and private networking for building reliable networked systems.

## Key Points

- **Use WireGuard over OpenVPN for new deployments** — it has a smaller attack surface (~4,000 lines of code vs ~100,000), better performance, and simpler configuration.
- **Segment networks with separate subnets and security groups** — databases should never be in public subnets, and application tiers should only communicate on required ports.
- **Consider zero-trust alternatives** (Tailscale, Cloudflare Tunnel, BeyondCorp) instead of traditional VPNs — they authenticate per-request rather than granting full network access.
skilldb get networking-infrastructure-skills/VPN NetworkingFull skill: 253 lines
Paste into your CLAUDE.md or agent config

VPN & Private Networking — Networking & Infrastructure

You are an expert in VPN and private networking for building reliable networked systems.

Core Philosophy

Overview

VPNs and private networks create encrypted tunnels and isolated network segments to secure communication between services, offices, and remote users. This skill covers VPN protocols (WireGuard, IPSec, OpenVPN), cloud private networking (VPC peering, Transit Gateway), zero-trust alternatives, and site-to-site connectivity patterns.

Core Concepts

VPN Types

Site-to-Site VPN                          Remote Access VPN
┌──────────┐     Encrypted     ┌──────────┐     ┌──────────┐   Encrypted   ┌──────────┐
│ Office A │◄═══ Tunnel ══════►│ Office B │     │  Laptop  │◄══ Tunnel ══►│ VPN GW   │
│ 10.1.0/24│     (IPSec)       │10.2.0/24 │     │          │   (WireGuard) │ Corp Net │
└──────────┘                   └──────────┘     └──────────┘              └──────────┘

Cloud-to-Cloud VPN                        Mesh VPN
┌──────────┐     VPC Peering   ┌──────────┐     ┌──Node A──┐
│  AWS VPC │◄════════════════►│  GCP VPC │     │    ↕     │
│ 10.0.0/16│                   │172.16.0/16│    ┌┤    ↕     ├┐
└──────────┘                   └──────────┘    │└─────────┘│
                                               │     ↕      │
                                          ┌─Node B─┐  ┌─Node C─┐

VPN Protocol Comparison

ProtocolSpeedSecuritySimplicityUse Case
WireGuardExcellentStrong (modern crypto)Very simpleDefault choice for new setups
IPSec/IKEv2GoodStrong (industry standard)ComplexSite-to-site, enterprise
OpenVPNModerateStrongModerateLegacy, broad compatibility

Cloud Private Networking

VPC / VNet Architecture:
┌─── VPC (10.0.0.0/16) ──────────────────────┐
│                                              │
│  ┌─ Public Subnet (10.0.1.0/24) ──┐        │
│  │  Load Balancer, NAT Gateway     │        │
│  └──────────────────────────────────┘        │
│                                              │
│  ┌─ Private Subnet (10.0.10.0/24) ─┐       │
│  │  App servers (no public IPs)     │       │
│  └──────────────────────────────────┘        │
│                                              │
│  ┌─ Private Subnet (10.0.20.0/24) ─┐       │
│  │  Database servers (isolated)     │       │
│  └──────────────────────────────────┘        │
│                                              │
└──────────────────────────────────────────────┘

Implementation Patterns

WireGuard Setup

# /etc/wireguard/wg0.conf — Server
[Interface]
PrivateKey = <server-private-key>
Address = 10.100.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Client 1
[Peer]
PublicKey = <client1-public-key>
AllowedIPs = 10.100.0.2/32

# Client 2
[Peer]
PublicKey = <client2-public-key>
AllowedIPs = 10.100.0.3/32
# /etc/wireguard/wg0.conf — Client
[Interface]
PrivateKey = <client-private-key>
Address = 10.100.0.2/24
DNS = 1.1.1.1, 8.8.8.8

[Peer]
PublicKey = <server-public-key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.100.0.0/24, 10.0.0.0/16  # VPN subnet + private network
PersistentKeepalive = 25
# Key generation
wg genkey | tee privatekey | wg pubkey > publickey

# Start/stop
sudo wg-quick up wg0
sudo wg-quick down wg0

# Enable on boot
sudo systemctl enable wg-quick@wg0

# Check status
sudo wg show

Terraform AWS VPC with Private Subnets

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = { Name = "main-vpc" }
}

resource "aws_subnet" "public" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet("10.0.0.0/16", 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  map_public_ip_on_launch = true
  tags = { Name = "public-${count.index}" }
}

resource "aws_subnet" "private" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet("10.0.0.0/16", 8, count.index + 10)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = { Name = "private-${count.index}" }
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }
}

# VPC Peering to another VPC
resource "aws_vpc_peering_connection" "peer" {
  vpc_id        = aws_vpc.main.id
  peer_vpc_id   = aws_vpc.services.id
  auto_accept   = true
}

resource "aws_route" "peer_route" {
  route_table_id            = aws_route_table.private.id
  destination_cidr_block    = "10.1.0.0/16"
  vpc_peering_connection_id = aws_vpc_peering_connection.peer.id
}

Site-to-Site VPN with AWS

resource "aws_vpn_gateway" "main" {
  vpc_id = aws_vpc.main.id
}

resource "aws_customer_gateway" "office" {
  bgp_asn    = 65000
  ip_address = "203.0.113.1"  # Office public IP
  type       = "ipsec.1"
}

resource "aws_vpn_connection" "office" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.office.id
  type                = "ipsec.1"
  static_routes_only  = true
}

resource "aws_vpn_connection_route" "office_network" {
  vpn_connection_id      = aws_vpn_connection.office.id
  destination_cidr_block = "192.168.1.0/24"  # Office private network
}

Tailscale (Managed WireGuard Mesh)

# Install and connect
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --advertise-routes=10.0.0.0/16 --accept-dns=false

# Access control policy (tailscale ACL)
# Defined in Tailscale admin console as JSON:
{
  "acls": [
    {"action": "accept", "src": ["group:engineers"], "dst": ["tag:servers:*"]},
    {"action": "accept", "src": ["group:devops"], "dst": ["*:*"]},
    {"action": "accept", "src": ["tag:servers"], "dst": ["tag:databases:5432"]}
  ],
  "groups": {
    "group:engineers": ["user1@example.com", "user2@example.com"],
    "group:devops": ["admin@example.com"]
  },
  "tagOwners": {
    "tag:servers": ["group:devops"],
    "tag:databases": ["group:devops"]
  }
}

Best Practices

  • Use WireGuard over OpenVPN for new deployments — it has a smaller attack surface (~4,000 lines of code vs ~100,000), better performance, and simpler configuration.
  • Segment networks with separate subnets and security groups — databases should never be in public subnets, and application tiers should only communicate on required ports.
  • Consider zero-trust alternatives (Tailscale, Cloudflare Tunnel, BeyondCorp) instead of traditional VPNs — they authenticate per-request rather than granting full network access.

Common Pitfalls

  • Overlapping CIDR ranges: When connecting two networks (VPC peering, site-to-site VPN), overlapping IP ranges cause routing conflicts. Plan your IP addressing scheme across all environments before building.
  • Split tunneling misconfiguration: Routing all traffic through a VPN (full tunnel) adds latency and bandwidth costs. Route only private network traffic through the VPN (AllowedIPs in WireGuard) unless you specifically need to inspect all traffic.

Anti-Patterns

Over-engineering for hypothetical requirements. Building for scenarios that may never materialize adds complexity without value. Solve the problem in front of you first.

Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide wastes time and introduces risk.

Premature abstraction. Creating elaborate frameworks before having enough concrete cases to know what the abstraction should look like produces the wrong abstraction.

Neglecting error handling at system boundaries. Internal code can trust its inputs, but boundaries with external systems require defensive validation.

Skipping documentation. What is obvious to you today will not be obvious to your colleague next month or to you next year.

Install this skill directly: skilldb add networking-infrastructure-skills

Get CLI access →