mcpField
V
vpn-setup

vpn-setup

github.com/bagelhole云与 DevOps1.2k402 次安装23 周前更新
代码仓库

关于 vpn-setup

vpn-setup 是用于配置安全 VPN 隧道的技能,面向远程访问、站点互联和分布式基础设施连接。它提供 WireGuard、OpenVPN、Tailscale 和 AWS Site-to-Site VPN 的配置示例与排障建议。

主要功能

  1. 01配置 WireGuard 服务端与客户端
  2. 02配置 OpenVPN 证书和隧道
  3. 03设置 Tailscale 子网路由
  4. 04配置 AWS 站点到站点 VPN
  5. 05排查连接、DNS 与性能问题

适用场景

  1. 01为员工或承包商设置远程访问
  2. 02连接本地网络与云环境
  3. 03在不公开服务的情况下访问内网
  4. 04连接不同数据中心或区域

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill vpn-setup

安装后在 Claude Code 中输入/vpn-setup确认已加载。

详细介绍

VPN 设置

配置安全的 VPN 隧道,以实现远程访问和站点连接。

何时使用此技能

在以下情况下使用此技能:

  • 为员工或承包商设置安全的远程访问
  • 将本地网络连接到云环境(站点到站点)
  • 加密数据中心或区域之间的流量
  • 为分布式基础设施实施网状 VPN
  • 在不向公众暴露内部服务的情况下提供安全访问

前提条件

  • 用作 VPN 端点的 Linux 服务器,且具有公共 IP
  • 对 VPN 服务器具有 root/sudo 访问权限
  • 防火墙规则允许 VPN 流量(WireGuard 使用 UDP 51820,OpenVPN 使用 UDP 1194)
  • 已为 VPN 主机名配置 DNS(可选,但建议配置)
  • 了解 IP 子网划分和路由

WireGuard

服务器设置
# Install WireGuard (Ubuntu/Debian)
apt update && apt install -y wireguard

# Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key

# Generate pre-shared key (optional, adds post-quantum resistance)
wg genpsk > /etc/wireguard/psk.key
chmod 600 /etc/wireguard/psk.key
服务器配置
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>

# Enable IP forwarding and NAT on startup
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 for clients
DNS = 10.0.0.1

# Peer: Alice (laptop)
[Peer]
PublicKey = <alice-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.2/32

# Peer: Bob (mobile)
[Peer]
PublicKey = <bob-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.3/32

# Peer: Office network (site-to-site)
[Peer]
PublicKey = <office-public-key>
PresharedKey = <preshared-key>
AllowedIPs = 10.0.0.4/32, 192.168.1.0/24
Endpoint = office.example.com:51820
PersistentKeepalive = 25
客户端配置
# Client config: alice.conf
[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
分割隧道配置
# Client config with split tunnel (only route internal traffic through VPN)
[Interface]
Address = 10.0.0.2/24
PrivateKey = <alice-private-key>
# No DNS override for split tunnel

[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
Endpoint = vpn.example.com:51820
# Only route specific subnets through VPN
AllowedIPs = 10.0.0.0/24, 172.16.0.0/16, 192.168.1.0/24
PersistentKeepalive = 25
WireGuard 管理命令
# Start/stop interface
wg-quick up wg0
wg-quick down wg0

# Enable on boot
systemctl enable wg-quick@wg0

# Show connection status
wg show
wg show wg0

# Add a new peer dynamically
wg set wg0 peer <new-public-key> allowed-ips 10.0.0.5/32

# Remove a peer
wg set wg0 peer <public-key> remove

# Show transfer statistics
wg show wg0 transfer

# Generate QR code for mobile clients
apt install -y qr-encode
qrencode -t ansiutf8 < alice-mobile.conf
对等端管理脚本
#!/bin/bash
# wg-add-peer.sh - Add a new WireGuard peer
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)

# Find next available IP
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"

# Generate client keys
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")

# Add peer to server config
cat >> "$SERVER_CONF" << EOF

# Peer: ${PEER_NAME}
[Peer]
PublicKey = ${CLIENT_PUBKEY}
PresharedKey = ${PSK}
AllowedIPs = 10.0.0.${NEXT_IP}/32
EOF

# Generate client config
cat > "$CLIENTS_DIR/${PEER_NAME}.conf" << EOF
[Interface]
Address = 10.0.0.${NEXT_IP}/24
PrivateKey = ${CLIENT_PRIVKEY}
DNS = 10.0.0.1

[Peer]
PublicKey = ${SERVER_PUBKEY}
PresharedKey = ${PSK}
Endpoint = ${SERVER_ENDPOINT}
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

# Reload WireGuard
wg syncconf wg0 <(wg-quick strip wg0)

echo "Peer ${PEER_NAME} added with IP 10.0.0.${NEXT_IP}"
echo "Client config: ${CLIENTS_DIR}/${PEER_NAME}.conf"

OpenVPN

服务器设置
# Install OpenVPN and Easy-RSA
apt install -y openvpn easy-rsa

# Initialize PKI
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

# Generate client certificate
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
服务器配置
# /etc/openvpn/server.conf
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

# Route client traffic through VPN
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# Split tunnel: push specific routes instead
# push "route 172.16.0.0 255.255.0.0"
# push "route 192.168.1.0 255.255.255.0"

keepalive 10 120

# Cipher and auth
cipher AES-256-GCM
auth SHA256
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305

# Hardening
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384

user nobody
group nogroup
persist-key
persist-tun

# Logging
status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3

# Max clients
max-clients 100

# Client isolation (clients cannot see each other)
client-to-client
客户端配置
# client1.ovpn
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(托管式 WireGuard)

# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Authenticate and connect
tailscale up

# Advertise subnet routes (act as a gateway)
tailscale up --advertise-routes=192.168.1.0/24,172.16.0.0/16

# Enable as exit node (route all traffic)
tailscale up --advertise-exit-node

# Use an exit node
tailscale up --exit-node=<exit-node-ip>

# Check status
tailscale status

# Access control: tailscale ACL policy (in admin console)
# Example ACL policy
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": ["[email protected]", "[email protected]"],
    "group:devops": ["[email protected]"]
  }
}
EOF

# Enable MagicDNS and set DNS
tailscale up --accept-dns

# SSH via Tailscale (no SSH keys needed)
tailscale up --ssh

AWS 站点到站点 VPN

# Create Virtual Private Gateway
VGW_ID=$(aws ec2 create-vpn-gateway --type ipsec.1 --query 'VpnGateway.VpnGatewayId' --output text)

# Attach to VPC
aws ec2 attach-vpn-gateway --vpn-gateway-id "$VGW_ID" --vpc-id vpc-0abc123

# Create Customer Gateway (your on-prem device)
CGW_ID=$(aws ec2 create-customer-gateway \
  --type ipsec.1 \
  --bgp-asn 65000 \
  --public-ip 203.0.113.10 \
  --query 'CustomerGateway.CustomerGatewayId' --output text)

# Create VPN connection
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)

# Download configuration for your device
aws ec2 describe-vpn-connections --vpn-connection-ids "$VPN_ID"

# Enable route propagation
aws ec2 enable-vgw-route-propagation \
  --gateway-id "$VGW_ID" \
  --route-table-id rtb-0abc123

# Monitor VPN tunnel status
aws ec2 describe-vpn-connections \
  --vpn-connection-ids "$VPN_ID" \
  --query 'VpnConnections[0].VgwTelemetry'

故障排除

问题原因解决方案
WireGuard 握手始终无法完成防火墙阻止了 UDP 51820在服务器防火墙和所有中间防火墙上开放 UDP 51820
无法通过 VPN 访问互联网IP 转发已禁用或缺少 NAT启用 net.ipv4.ip_forward=1;检查 PostUp iptables 规则
DNS 无法通过 VPN 解析未推送 DNS 或本地 DNS 冲突在客户端配置中设置 DNS = ;检查 /etc/resolv.conf
OpenVPN TLS 握手失败证书不匹配或已过期验证 CA 证书是否匹配;使用 openssl x509 -dates 检查证书日期
分割隧道泄漏流量AllowedIPs 范围过宽仅在 AllowedIPs 中设置特定子网;使用 traceroute 验证
无法访问 Tailscale 节点ACL 阻止了流量检查 Tailscale 管理后台的 ACL 策略;使用 tailscale status 确认节点在线
AWS VPN 隧道频繁断开空闲超时或 DPD 配置错误在客户网关上启用 DPD;定期发送 keep-alive 流量
VPN 性能缓慢MTU 问题导致分片在 WireGuard 配置中设置 MTU = 1420;使用 ping -M do -s 1400 测试

最佳实践

  • 在现代部署中使用 WireGuard(更简单、更快速、攻击面更小)
  • 尽可能为 VPN 访问启用 MFA
  • 定期轮换密钥(WireGuard 每季度轮换一次,OpenVPN 证书每年轮换一次)
  • 监控 VPN 连接,并在出现异常时发出警报
  • 使用分割隧道或 ACL 按角色划分 VPN 访问权限
  • 在 WireGuard 中使用预共享密钥,以增强抗量子能力
  • 更新 VPN 软件,以修补安全漏洞
  • 记录所有 VPN 连接事件,以供审计
  • 员工离职时立即禁用其 VPN 访问权限
  • 测试站点到站点 VPN 连接的故障转移

相关技能

评论

支持 Markdown