跳转至正文内容

独立技术知识论坛 主机玩家与运维交流社区 • 与德国 netcup GmbH 无官方隶属关系。

NETCUP GUIDE
知识论坛 · 实时优惠码池
运维教程 难度:中级进阶 耗时:35 分钟 // 阅读约 17 分钟 • 核验于

如何在 Netcup 上搭建双栈 (IPv4 + IPv6) WireGuard VPN 服务器与 Unbound 本地递归 DNS

由于每一台 Netcup VPS 与 Root Server 均采用硬件辅助的 KVM 完全虚拟化架构,具备完整的原生 Linux 内核、最高达 2.5 Gbit/s 的高速网络接口、原生路由的 /64 IPv6 子网,以及遍布德国纽伦堡、奥地利维也纳、荷兰阿姆斯特丹、美国马纳萨斯和新加坡机房的充足流量配额,即便是一台配备 1 GB 内存的入门级 KVM 实例也能轻松承载数百兆比特的加密隧道流量。本系统工程指南将带您从零构建一套加固的双栈(IPv4 + IPv6)WireGuard VPN 安全网关:精确计算并设定 MTU 1420 封装字节数,注入 TCP MSS 钳制规则以避免 PMTU 路径黑洞,部署绑定在隧道内网的本地 Unbound 递归 DNS 解析器实现零 DNS 泄露,并编写集成抗量子计算 PresharedKey 预共享密钥的自动化客户端配置与二维码签发脚本。

楼主 (OP) // 实测发起人 Elena Rostova 首席云基础设施架构师(欧洲 KVM 与网络工程)
版主复核 // 共同维护 Marcus Vance 高级 Linux 系统与安全审计工程师
帖子状态 // 最后修订 社区核查规范 →
版主按语 // 实测环境与社区透明说明 已在位于纽伦堡机房(AS197540)、配备 IPv4 /32 与 IPv6 /64 双栈路由的 Netcup KVM 实例上,基于 Linux 6.8+ 内核树内置 WireGuard 模块、wireguard-tools 以及 unbound 1.19 完成全流程验证。

环境要求 // 前置条件清单

检查清单
  • ✓ 任意一台运行 Ubuntu 24.04 LTS 或 Debian 12 的 Netcup KVM VPS(哪怕是配备 1 GB 内存的 VPS pico G11.5s 或 2 GB 内存的 VPS nano G11.5s)或 Root Server
  • ✓ 已在宿主机 UFW 防火墙与 Netcup SCP 云防火墙中放行入站 UDP 51820 端口
  • ✓ 具备 root 或 sudo 权限的 SSH 访问能力

核心技术结论 (Key Takeaways)

核心摘要
  • 01 WireGuard 直接运行在 Netcup KVM 服务器的 Linux 6.8+ 内核空间中,利用现代处理器 SIMD 指令集加速 ChaCha20-Poly1305 加解密,即便在 2 vCore 的入门级 VPS 上也能轻松实现 800+ Mbps 的加密吞吐量。
  • 02 在服务端与客户端接口上显式计算并设置 MTU = 1420,以便在标准的 1500 字节 virtio-net 以太网帧内完整容纳外层 IPv6 报头(40 字节)+ UDP 报头(8 字节)+ WireGuard 协议头与认证标签(32 字节)。
  • 03 在 PostUp 钩子中配置双栈 TCP MSS 钳制规则(--clamp-mss-to-pmtu),确保移动 5G 网络或家庭 PPPoE 宽带下的客户端在进行 HTTPS TLS 握手时绝不会因 ICMP 分片阻断而卡死。
  • 04 在所有全流量客户端配置文件中必须同时接管 IPv4(0.0.0.0/0)与 IPv6(::/0)路由;若遗漏 IPv6,双栈手机与 Wi-Fi 网络会直接绕过 VPN 隧道通过运营商原生 IPv6 泄露真实 IP。
  • 05 部署仅监听 wg0 隧道网关地址(10.66.66.1 与 fd42:66:66::1)的本地 Unbound 递归 DNS 解析器,并启用 DNSSEC 签名校验与 QNAME 最小化隐私保护。
📑 本文目录导航(共 5 节) ▼
§ 01

第 1 步:深入理解 Netcup virtio-net MTU 封装数学原理并开启内核双栈转发

在自建 WireGuard VPN 服务器的工程实践中,导致客户端连接后“能 ping 通但部分 HTTPS 网页一直转圈加载不出来”的常见根源,就是最大传输单元(MTU)计算错误以及缺失 TCP 最大报文段长度(MSS)钳制。在 Netcup KVM 实例上,主虚拟网卡(通常命名为 eth0 或 ens3,底层驱动为 virtio_net)工作在标准的 1500 字节以太网 MTU 下。

当外部客户端通过 IPv6(或 IPv4)连接到您的 Netcup WireGuard 端点时,每一个内层隧道数据包都会被额外封装上一层外层传输报头:外层 IPv6 报头占 40 字节(IPv4 占 20 字节)、UDP 报头占 8 字节、WireGuard 消息类型与计数器占 16 字节、Poly1305 消息认证标签(MAC)占 16 字节——在 IPv6 传输下总计产生 80 字节的封装开销(IPv4 为 60 字节)。如果我们没有将内层 WireGuard 虚拟网卡(wg0)的 MTU 至少缩减 80 字节(即 1500 - 80 = 1420),封装后的外层 UDP 数据包总长度就会超过物理网卡的 1500 字节上限。

当客户端处于家庭 PPPoE 光纤宽带(PPPoE 帧头额外占用 8 字节,外层链路 MTU 仅为 1492)或移动 4G/5G 蜂窝网络(外层 MTU 常在 1380 至 1428 字节之间)时,路径 MTU 发现(PMTUD)黑洞尤为突出。一旦路径上的某个运营商路由器丢弃了 ICMP Fragmentation Needed(Type 3 Code 4)或 ICMPv6 Packet Too Big(Type 2)差错报文,小包(如 ping 与 DNS 请求)依然畅通无阻,而包含大型 X.509 证书链的 TLS ServerHello 数据包则会被静默丢弃。因此,除设定 MTU = 1420 外,我们还在 /etc/sysctl.d/99-wireguard-router.conf 中开启宽松反向路径过滤(rp_filter = 2)与 Google BBR 拥塞控制算法。

Netcup KVM (virtio-net 1500 MTU) 上的 WireGuard 数据包封装字节开销拆解表
协议层 / 报头组件外层 IPv4 传输开销外层 IPv6 传输开销工程计算说明
物理 / KVM virtio-net 链路层 MTU1500 字节1500 字节可在 Netcup 虚拟机内通过 ip -br link show 核验
外层 IP 协议报头-20 字节 (IPv4)-40 字节 (IPv6)IPv6 固定报头比 IPv4 标准报头大 20 字节
外层 UDP 报头 (端口 51820)-8 字节-8 字节标准 8 字节 UDP 数据报头
WireGuard 消息类型 + 密钥索引 + Nonce-16 字节-16 字节4 字节类型 + 4 字节接收方索引 + 8 字节计数器
Poly1305 加密消息认证码 (MAC)-16 字节-16 字节128 位密码学完整性校验标签
wg0 接口最大安全 MTU 上限1440 字节1420 字节建议全局统一设为 1420(若客户端处于 PPPoE 环境可进一步设为 1412)
自动识别主网卡名称并开启持久化双栈内核数据包转发与 BBR
bash
# 1. 自动识别您的 Netcup 主网卡名称(通常为 eth0 或 ens3)
PRIMARY_IF=$(ip -4 route show default | awk '{print $5; exit}')
echo "Detected Primary Netcup Interface: ${PRIMARY_IF}"

# 2. 配置持久化双栈 IP 转发、宽松反向路径过滤与 BBR 拥塞控制算法
sudo tee /etc/sysctl.d/99-wireguard-router.conf > /dev/null <<'EOF'
# 开启跨网卡的 IPv4 与 IPv6 数据包路由转发
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1

# 开启宽松模式反向路径过滤 (Loose RPF),防止非对称 VPN 回程包被内核丢弃
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2

# 启用 BBR TCP 拥塞控制算法以提升跨国高延迟链路的 VPN 吞吐量
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
EOF

sudo sysctl --system

命令与参数详解: 自动检测您的 Netcup 虚拟机使用的是 eth0 还是 ens3,并开启持久化的 IPv4/IPv6 双栈内核转发、宽松反向路径过滤(rp_filter = 2)以及 TCP BBR 拥塞控制算法。

预期终端输出
Detected Primary Netcup Interface: eth0
* Applying /etc/sysctl.d/99-wireguard-router.conf ...
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
§ 02

第 2 步:安装 wireguard-tools 并初始化高安全性的密码学密钥层级

自 Linux 内核 5.6 版本起,WireGuard 的高性能数据平面模块(wireguard.ko)已直接编译进 Ubuntu 与 Debian 的主线内核中。与传统的 OpenVPN 或 IPsec 用户态守护进程不同,WireGuard 无需在内核态与用户态之间通过 /dev/net/tun 频繁拷贝每一个网络数据包,而是直接在内核软中断(softirq)上下文中调用 Netcup AMD EPYC 处理器的 AVX2/AVX-512 SIMD 指令集完成 ChaCha20-Poly1305 加解密。我们只需安装用户态配置工具集(wireguard-tools)、终端二维码生成工具(qrencode)以及本地递归 DNS 服务器 unbound 与根信任锚点(dns-root-data)。

安装完成后,我们在 /etc/wireguard/{keys,clients} 下构建结构化的目录树,并通过 chmod 0700 与 umask 077 子 Shell 将目录及密钥文件的访问权限严格锁定为仅 root 可读写(0600),确保私钥从写入磁盘块的第一刻起就对非特权用户不可见。

安装 WireGuard 工具集与 Unbound 并生成服务端 Curve25519 密钥对
bash
sudo apt update
sudo apt install -y wireguard wireguard-tools qrencode iptables unbound dns-root-data

# 创建权限锁定的密钥与客户端配置存储目录
sudo mkdir -p /etc/wireguard/{keys,clients}
sudo chmod -R 0700 /etc/wireguard

# 在严格的 umask 077 下生成服务端 Curve25519 私钥与公钥
sudo sh -c 'umask 077; wg genkey | tee /etc/wireguard/keys/server_private.key | wg pubkey > /etc/wireguard/keys/server_public.key'

# 核验密钥文件权限
sudo ls -la /etc/wireguard/keys/

命令与参数详解: 安装 WireGuard 用户态工具、qrencode 与 unbound,随后在 umask 077 保护下于 /etc/wireguard/keys/ 目录内生成权限为 0600 (-rw-------) 的服务端 Curve25519 公私钥对。

预期终端输出
drwx------ 2 root root 4096 Oct 29 11:15 .
-rw------- 1 root root   45 Oct 29 11:15 server_private.key
-rw------- 1 root root   45 Oct 29 11:15 server_public.key
§ 03

第 3 步:配置零泄露的本地 Unbound 递归 DNS 解析器

许多基础 WireGuard 教程会在客户端配置文件中直接写入 DNS = 1.1.1.1 或 8.8.8.8,这种配置会将您所有连接设备的完整域名访问时间线同步发送给外部第三方公共 DNS 服务商。通过在您的 Netcup 服务器本地部署一台直接监听 WireGuard 隧道网关地址(10.66.66.1 与 fd42:66:66::1)的 Unbound 递归解析器,所有接入 VPN 的终端设备都将通过加密隧道直接向全球 13 组根域名服务器(/usr/share/dns/root.key)及顶级权威域名服务器发起迭代查询,不再依赖任何上游转发器。

我们的 Unbound 配置启用了两项关键的隐私与完整性保护机制:一是 RFC 9156 QNAME 最小化(qname-minimisation: yes),在逐级向根服务器和 .com 顶级域服务器查询时仅发送当前层级必需的最短标签,避免向中间层暴露完整子域名;二是强制 DNSSEC 数字签名验证(harden-dnssec-stripped: yes),自动拦截任何被篡改或伪造的 DNS 响应。

当 Unbound 绑定在虚拟隧道地址(10.66.66.1 与 fd42:66:66::1)上时,如果宿主机重启期间 unbound.service 比 wg-quick@wg0.service 早启动几百毫秒,默认情况下会因网卡尚未创建而报错退出。在配置中启用 ip-freebind: yes(对应 Linux 内核 IP_FREEBIND 套接字选项)可允许 Unbound 在 wg0 接口尚未激活前预先绑定这两个 IP 地址,从而避免开机启动竞态故障。

/etc/unbound/unbound.conf.d/wg-vpn.conf
text
server:
    num-threads: 2
    interface: 127.0.0.1
    interface: 10.66.66.1
    interface: fd42:66:66::1
    port: 53

    do-ip4: yes
    do-ip6: yes
    do-udp: yes
    do-tcp: yes

    # 严格限制仅允许本地回环与 WireGuard 隧道子网发起递归查询
    access-control: 0.0.0.0/0 refuse
    access-control: ::0/0 refuse
    access-control: 127.0.0.0/8 allow
    access-control: 10.66.66.0/24 allow
    access-control: fd42:66:66::/64 allow

    # 隐私与 DNSSEC 安全加固
    hide-identity: yes
    hide-version: yes
    qname-minimisation: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes
    prefetch: yes

    # 内存缓存配额调优(整体内存占用仅约 64MB)
    msg-cache-size: 16m
    rrset-cache-size: 32m
    neg-cache-size: 4m
    so-rcvbuf: 4m
    so-sndbuf: 4m

命令与参数详解: 配置 Unbound 监听本地回环以及 WireGuard 的 IPv4 (10.66.66.1) 与 IPv6 (fd42:66:66::1) 网关地址,同时通过 access-control 严格拒绝来自公网的一切未授权查询请求(0.0.0.0/0 refuse),防止服务器被利用为 DNS 放大攻击反射源。

安全与生产运维提示: 由于 Unbound 需要绑定到 10.66.66.1 与 fd42:66:66::1,为了防止宿主机开机时 unbound.service 先于 wg-quick@wg0.service 启动而导致绑定 IP 失败,我们需要在 server: 块中注入 ip-freebind: yes 选项,允许 Unbound 在 wg0 网卡尚未就绪时预先绑定该套接字。

启用 ip-freebind: yes 并校验 Unbound DNSSEC 解析功能
bash
sudo sed -i '/port: 53/a \    ip-freebind: yes' /etc/unbound/unbound.conf.d/wg-vpn.conf
sudo unbound-checkconf
sudo systemctl enable --now unbound
dig @127.0.0.1 netcup.com +dnssec +short

命令与参数详解: 插入 ip-freebind: yes 确保开机启动顺序无忧,使用 unbound-checkconf 校验配置文件语法,启动 Unbound 服务并测试本地 DNSSEC 解析输出。

预期终端输出
unbound-checkconf: no errors in /etc/unbound/unbound.conf
46.38.224.21
§ 04

第 4 步:构建包含双栈 NAT 与 TCP MSS 钳制规则的 /etc/wireguard/wg0.conf

在为 wg0 配置 IPv6 之前,需要先了解 Netcup AS197540 网络对 /64 IPv6 子网的路由机制。Netcup 的宿主机网关(fe80::1)并非通过 DHCPv6-PD(前缀委派)将整个 /64 路由表无条件指向您的虚拟机 MAC 地址,而是在 eth0 网桥上对每一个目标 IPv6 地址发起邻居发现协议(NDP Neighbor Solicitation)广播查询。如果您直接从公网 /64 中切分出一个 /80 子网分配给 wg0,当外部回程数据包到达 fe80::1 时,由于 eth0 默认不会响应属于 wg0 接口的 NDP 请求,回程包会被直接丢弃——除非您在宿主机上额外运行并维护 ndppd(NDP 代理守护进程)。

为了构建一套在所有 Netcup VPS 与 Root Server 上均能零维护稳定工作的双栈方案,我们在 wg0 上分配符合 RFC 4193 规范的唯一本地地址(ULA fd42:66:66::/64)配合 IPv4 内网段(10.66.66.0/24),并在出站时通过 ip6tables 的 MASQUERADE(NAT66)将数据包源地址转换为主网卡的公网 IPv6 地址。这样既无需维护脆弱的 ndppd 守护进程,又能隐藏各个客户端设备的接口标识符。

除了双栈 MASQUERADE 规则外,我们的 PostUp 钩子还在 mangle 表的 FORWARD 链中为 IPv4 和 IPv6 同时注入了 --clamp-mss-to-pmtu 规则。当客户端发起 TCP 三次握手(SYN 包)时,内核 netfilter 会动态将报文头中的最大报文段长度(MSS)重写为匹配隧道路径 MTU 的安全值(IPv4 下自动钳制为 1380 字节,IPv6 下自动钳制为 1360 字节),从而解决了访问部分阻断 ICMP 分片通知的企业网站时出现的 TLS 握手卡死问题。

自动绑定主网卡并生成 /etc/wireguard/wg0.conf 服务端配置
bash
PRIMARY_IF=$(ip -4 route show default | awk '{print $5; exit}')
SERVER_PRIVKEY=$(sudo cat /etc/wireguard/keys/server_private.key)

sudo tee /etc/wireguard/wg0.conf > /dev/null <<EOF
[Interface]
Address = 10.66.66.1/24, fd42:66:66::1/64
ListenPort = 51820
PrivateKey = ${SERVER_PRIVKEY}
MTU = 1420
SaveConfig = false

# 开启转发、双栈 TCP MSS 自动钳制与 NAT 源地址伪装
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostUp = iptables -t mangle -A FORWARD -i wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostUp = iptables -t mangle -A FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostUp = iptables -t nat -A POSTROUTING -s 10.66.66.0/24 -o ${PRIMARY_IF} -j MASQUERADE
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT
PostUp = ip6tables -t mangle -A FORWARD -i wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostUp = ip6tables -t mangle -A FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostUp = ip6tables -t nat -A POSTROUTING -s fd42:66:66::/64 -o ${PRIMARY_IF} -j MASQUERADE

# 当 wg0 停止时干净移除对应防火墙规则
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t mangle -D FORWARD -i wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -t mangle -D FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -t nat -D POSTROUTING -s 10.66.66.0/24 -o ${PRIMARY_IF} -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT
PostDown = ip6tables -t mangle -D FORWARD -i wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = ip6tables -t mangle -D FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = ip6tables -t nat -D POSTROUTING -s fd42:66:66::/64 -o ${PRIMARY_IF} -j MASQUERADE
EOF

sudo chmod 0600 /etc/wireguard/wg0.conf
sudo ufw allow 51820/udp comment 'WireGuard VPN'
sudo systemctl enable --now wg-quick@wg0
sudo wg show wg0

命令与参数详解: 利用自动检测到的主网卡名称生成 /etc/wireguard/wg0.conf,配置双栈 NAT 伪装与 TCP MSS 钳制规则,在 UFW 中放行 UDP 51820 端口,并启动 wg-quick@wg0 服务。

预期终端输出
interface: wg0
  public key: <SERVER_PUBLIC_KEY>
  private key: (hidden)
  listening port: 51820

安全与生产运维提示: 请务必在 /etc/wireguard/wg0.conf 中保持 SaveConfig = false。如果设为 true,当 wg-quick 停止或重启时,它会用内核当前状态直接覆盖重写 /etc/wireguard/wg0.conf,不仅会抹除所有注释,还会破坏自动化客户端配置脚本的结构。

§ 05

第 5 步:编写集成 PresharedKey 与终端二维码的自动化客户端签发脚本

手动计算客户端 IP 偏移量并在多个文件之间复制粘贴公钥极易出错。为此,我们创建一个专用的系统管理脚本 /usr/local/sbin/wg-add-peer,实现一行命令自动化签发笔记本电脑或智能手机客户端配置。

针对每一个新增的客户端(Peer),该脚本除了生成独立的 Curve25519 公私钥对外,还会额外调用 wg genpsk 生成一个 256 位对称预共享密钥(PresharedKey),将其混入 WireGuard 的 Noise_IKpsk2 握手密钥派生函数(HKDF)中,叠加一层抗量子计算(Post-Quantum Resistance)对称加密保护。更重要的是,脚本使用 wg syncconf 进行内核级热重载,无需重启 wg0 接口即可让新客户端立即生效。

/usr/local/sbin/wg-add-peer (自动化客户端配置与二维码生成脚本)
bash
sudo tee /usr/local/sbin/wg-add-peer > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

if [[ $# -lt 2 ]]; then
  echo "Usage: sudo wg-add-peer <client-name> <octet-2-to-254>"
  echo "Example: sudo wg-add-peer macbook-pro 10"
  exit 1
fi

CLIENT_NAME="$1"
OCTET="$2"
SERVER_IP=$(ip -4 addr show "$(ip -4 route show default | awk '{print $5; exit}')" | awk '/inet / {split($2,a,"/"); print a[1]; exit}')
SERVER_PUBKEY=$(cat /etc/wireguard/keys/server_public.key)
CLIENT_DIR="/etc/wireguard/clients/${CLIENT_NAME}"

if [[ -d "${CLIENT_DIR}" ]]; then
  echo "Error: Peer ${CLIENT_NAME} already exists in ${CLIENT_DIR}"
  exit 1
fi

umask 077
mkdir -p "${CLIENT_DIR}"
wg genkey | tee "${CLIENT_DIR}/private.key" | wg pubkey > "${CLIENT_DIR}/public.key"
wg genpsk > "${CLIENT_DIR}/preshared.key"

CLIENT_PRIVKEY=$(cat "${CLIENT_DIR}/private.key")
CLIENT_PUBKEY=$(cat "${CLIENT_DIR}/public.key")
CLIENT_PSK=$(cat "${CLIENT_DIR}/preshared.key")

# 1. 将新 Peer 配置块追加至 /etc/wireguard/wg0.conf
cat >> /etc/wireguard/wg0.conf <<PEER_EOF

# Peer: ${CLIENT_NAME}
[Peer]
PublicKey = ${CLIENT_PUBKEY}
PresharedKey = ${CLIENT_PSK}
AllowedIPs = 10.66.66.${OCTET}/32, fd42:66:66::${OCTET}/128
PEER_EOF

# 2. 在不中断现有活跃 VPN 隧道的前提下热重载 wg0 内核配置
wg syncconf wg0 <(wg-quick strip wg0)

# 3. 生成客户端 .conf 配置文件
cat > "${CLIENT_DIR}/${CLIENT_NAME}.conf" <<CLIENT_EOF
[Interface]
PrivateKey = ${CLIENT_PRIVKEY}
Address = 10.66.66.${OCTET}/32, fd42:66:66::${OCTET}/128
DNS = 10.66.66.1, fd42:66:66::1
MTU = 1420

[Peer]
PublicKey = ${SERVER_PUBKEY}
PresharedKey = ${CLIENT_PSK}
Endpoint = ${SERVER_IP}:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
CLIENT_EOF

echo "==> 已创建客户端配置文件: ${CLIENT_DIR}/${CLIENT_NAME}.conf"
echo "==> 请使用 WireGuard 官方 iOS/Android 客户端扫描下方二维码:"
qrencode -t ansiutf8 < "${CLIENT_DIR}/${CLIENT_NAME}.conf"
EOF

sudo chmod 0700 /usr/local/sbin/wg-add-peer
sudo /usr/local/sbin/wg-add-peer iphone-16 10

命令与参数详解: 创建 /usr/local/sbin/wg-add-peer 自动化脚本:生成客户端密钥对与 PresharedKey,通过 wg syncconf 在不中断其他在线用户连接的前提下热加载 wg0 配置,生成客户端 .conf 文件,并直接在终端打印可供手机扫码导入的 ANSI UTF-8 二维码。

使用 wg syncconf 实现零停机增删客户端

切勿仅仅为了新增或吊销某个客户端而执行 systemctl restart wg-quick@wg0——重启网卡会瞬间切断所有当前在线用户的 SSH 会话或语音通话。使用 sudo wg syncconf wg0 <(sudo wg-quick strip wg0) 可以直接在 Linux 内核态原子级应用 Peer 变更,实现真正的零中断维护。

常见故障排查方案

排障手册

[故障现象] WireGuard 握手成功(latest handshake: 5 seconds ago),但打开部分 HTTPS 网站时一直转圈卡死

根本原因: 典型的路径 MTU 发现(PMTUD)黑洞问题。可能是客户端配置文件中遗漏了 MTU = 1420,或者客户端正处于外层 MTU 小于 1500 字节的 PPPoE 家宽 / 移动蜂窝网络下。

解决方案: 首先执行 sudo iptables -t mangle -S FORWARD 与 sudo ip6tables -t mangle -S FORWARD 确认服务端的 TCPMSS --clamp-mss-to-pmtu 规则已生效;随后在客户端配置的 [Interface] 下将 MTU 调低至 1380 或 1280(IPv6 协议规定的最小链路 MTU)。

[故障现象] 客户端连接后可以 Ping 通网关 10.66.66.1,但无法访问任何外部 IPv4/IPv6 网站

根本原因: 可能是 UFW 防火墙的默认转发策略(/etc/default/ufw 中的 DEFAULT_FORWARD_POLICY="DROP")在 wg0 规则之后拦截了转发包,或者 MASQUERADE 规则中填写的网卡名称(eth0 vs ens3)与实际主网卡不符。

解决方案: 执行 ip -4 route show default 核对 /etc/wireguard/wg0.conf 中的主网卡名,并将 /etc/default/ufw 中的 DEFAULT_FORWARD_POLICY 设为 "ACCEPT"(或将 PostUp 中的 -A FORWARD 改为 -I FORWARD 1 插入到规则链最顶端)。

[故障现象] 连接 WireGuard 后进行 IPv6 泄露测试,网页仍然显示客户端本地宽带运营商的真实 IPv6 地址

根本原因: 客户端配置文件 [Peer] 块中的 AllowedIPs 仅填写了 0.0.0.0/0 而遗漏了 ::/0,导致客户端操作系统将所有 IPv6 流量直接通过本地物理网卡直连发送。

解决方案: 在所有全局代理模式的客户端配置中,务必将 AllowedIPs 设为 0.0.0.0/0, ::/0,并同时分配双栈隧道内网地址(10.66.66.X/32, fd42:66:66::X/128)。

[故障现象] 客户端无法通过 10.66.66.1 解析域名(浏览器报错 DNS_PROBE_FINISHED_NO_INTERNET)

根本原因: Netcup 宿主机上的 UFW 防火墙拦截了从 wg0 隧道接口进入的 UDP/TCP 53 端口 DNS 查询请求。

解决方案: 在服务端执行 sudo ufw allow in on wg0 to any port 53 专门放行来自 wg0 接口的 DNS 请求,随后在客户端运行 dig @10.66.66.1 netcup.com 验证解析。

常见问题解答 (FAQ)

权威解答

在 Netcup VPS 或 Root Server 上运行 WireGuard VPN 会违反服务条款 (ToS) 或公平流量政策吗?

为您个人的笔记本/手机设备、远程办公或企业研发团队搭建私有的 WireGuard VPN 在 Netcup VPS 与 Root Server 上是 100% 合规且完全允许的。只有搭建向公众开放的匿名代理、商业倒卖 VPN 服务,或者运行高频引发版权投诉与滥用举报(Abuse)的公共 Tor 出口节点,才会违反 Netcup 的服务条款。

如何配置分流隧道(Split-Tunnel),使客户端仅在访问 Netcup 内部 Docker 网段时才走 VPN?

只需打开您的客户端 .conf 配置文件,将 AllowedIPs = 0.0.0.0/0, ::/0 修改为您需要路由的 WireGuard 内网及私有 Docker 网段列表——例如改为 AllowedIPs = 10.66.66.0/24, fd42:66:66::/64, 172.28.0.0/16,并移除全局 DNS = 10.66.66.1 行即可。此时您的日常网页浏览直接走本地宽带,而访问服务器内网容器与数据库则自动加密穿过隧道。

为什么本文使用唯一本地地址(ULA fd42:66:66::/64)配合 IPv6 NAT66,而不是直接切分 Netcup 公网 /64 子网?

Netcup 将分配给您的公网 IPv6 /64 子网直接路由到虚拟机主网卡的链路层 MAC 地址,而非通过 DHCPv6-PD 前缀委派下发。这意味着如果要从公网 /64 中切分出一个 /80 给 wg0 接口,就必须额外安装并维护 ndppd(邻居发现代理守护进程)来响应上游网关的 NDP 请求。相比之下,使用 ULA(fd42:66:66::/64)配合 ip6tables MASQUERADE 在所有 Netcup 机型上都能开箱即用、确定性工作,还能同时隐藏各个客户端设备的接口标识符,提供更强的隐私保护。

如果笔记本电脑或手机不慎丢失,如何立即吊销该设备的 VPN 访问权限?

只需编辑 /etc/wireguard/wg0.conf 删除对应设备的 [Peer] 配置块,删除 /etc/wireguard/clients/<设备名> 目录,然后执行 sudo wg syncconf wg0 <(sudo wg-quick strip wg0)(或直接运行 sudo wg set wg0 peer <客户端公钥> remove)。Linux 内核会在毫秒级时间内立即销毁该设备的加密会话。

参考资料 // 官方技术文档与核验来源

延伸阅读 // 核心架构评测与买前必读

领取优惠码 →