关于 vpn-setup
vpn-setup 是用于配置安全 VPN 隧道的技能,面向远程访问、站点互联和分布式基础设施连接。它提供 WireGuard、OpenVPN、Tailscale 和 AWS Site-to-Site VPN 的配置示例与排障建议。
主要功能
- 01配置 WireGuard 服务端与客户端
- 02配置 OpenVPN 证书和隧道
- 03设置 Tailscale 子网路由
- 04配置 AWS 站点到站点 VPN
- 05排查连接、DNS 与性能问题
适用场景
- 01为员工或承包商设置远程访问
- 02连接本地网络与云环境
- 03在不公开服务的情况下访问内网
- 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 连接的故障转移
相关技能
- 零信任 - 现代访问模式
- SSL/TLS 管理 - 证书管理
- 防火墙配置 - 网络访问控制
评论
支持 Markdown