使用 WireGuard 为 IPV6-Only 机器添加 IPV4 网络

标题描述的需求比较特化, WireGuard 的应用场景非常广泛, 只是给 IPV6-Only 的机器添加 IPV4 网络比较典型.

Cloudflare 的 Warp 和 Tailscale 都是基于 WireGuard 的, 它们也都能做到给机器添加特殊的网络出口访问.

最近 Warp 刚好又故障了, 所以折腾了下手动配置 WireGuard , 实现使用一台双栈服务器为 IPV6-Only 的机器提供 IPV4 网络出口.

本文使用的系统环境

  • OS: Debian12 / Bookworm
  • WireGuard: v1.0.20210914
  • netfilter: iptables v1.8.9 (不用 nft 是因为命令写进配置里太复杂了…)

首先在两台服务器上都安装 WireGuard

bash
apt update && apt install wireguard-tools wireguard

进入配置目录, 为两台服务器创建密钥对

bash
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey

privatekey 是私钥, publickey 是公钥.

编写服务端配置, 新建 wg233.conf 文件, wg233 可以替换为自己想要的接口名称.

ini
[Interface]
Address = 10.39.0.1/24 # 内网IP/CIDR
ListenPort = 39182 # 监听端口
PrivateKey = 服务端的 privatekey 内容

# Hooks, 用于在开启 WireGuard 接口时启用 IP 转发和添加 NAT 规则
PostUp = echo "1" > /proc/sys/net/ipv4/ip_forward
# 如果服务器的公网接口不是 eth0, 请替换为实际的接口名称
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = iptables -A FORWARD -i %i -j ACCEPT
PostUp = iptables -A FORWARD -o %i -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT
PostDown = iptables -D FORWARD -o %i -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

[Peer]
PublicKey    =  客户端的 publickey 内容
AllowedIPs  = 10.39.0.2/32 # 稍后将要配置的客户端IP

编写客户端配置, 同样的新建一个配置文件, 配置文件名即为接口名 (不需要和服务端一致).

ini
[Interface]
Address = 10.39.0.2/24 # 和服务端的 AllowedIPs 一致
PrivateKey = 客户端的 privatekey 内容

# 客户端的 Hooks, 这里添加了对 Docker 的支持
# 若你更改过 Docker 的默认接口和网段, 请相应修改
PostUp = iptables -A FORWARD -i docker0 -o %i -j ACCEPT
PostUp = iptables -A FORWARD -i %i -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o %i -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 172.17.0.0/16 -o %i -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -D FORWARD -i docker0 -o %i -j ACCEPT

[Peer]
PublicKey         = 服务端的 publickey 内容
Endpoint          = [服务端公网ipv6]:39182
AllowedIPs        = 0.0.0.0/0
PersistentKeepalive = 25 # keepalive 间隔, 单位秒

启动两个 WireGuard 服务:

bash
systemctl enable --now wg-quick@wg233

输入 wg 命令查看状态, 预期输出:

bash
interface: wg233
  public key: QdUOWJE...Nnm8=
  private key: (hidden)
  listening port: 55670
  fwmark: 0xca6c

peer: TcO+...vanU=
  endpoint: [ip]:39182
  allowed ips: 0.0.0.0/0
  latest handshake: 44 seconds ago
  transfer: 34.35 MiB received, 3.72 MiB sent
  persistent keepalive: every 25 seconds

Some tips:

  1. 已经删除了的 WireGuard 配置还在 systemd 里?

    使用下面的命令清理:

    bash
    systemctl reset-failed
  2. WireGuard 附带安装的 openresolv 修改了原来的 DNS 配置?

    openresolv 的配置在 /etc/resolvconf.conf.

    将 name_servers 部分设为你想要使用的 DNS 服务器, 用空格分隔多个:

    ini
    # Configuration for resolvconf(8)
    # See resolvconf.conf(5) for details
    
    resolv_conf=/etc/resolv.conf
    # If you run a local name server, you should uncomment the below line and
    # configure your subscribers configuration files below.
    #name_servers=127.0.0.1
    name_servers="2606:4700:4700::1111 2001:4860:4860::8888 2001:4860:4860::8844"
    
    # Mirror the Debian package defaults for the below resolvers
    # so that resolvconf integrates seemlessly.
    dnsmasq_resolv=/var/run/dnsmasq/resolv.conf
    pdnsd_conf=/etc/pdnsd.conf
    unbound_conf=/etc/unbound/unbound.conf.d/resolvconf_resolvers.conf
  3. 关于 IP/CIDR 的计算:


Q.E.D.
海信VIDDA 旧电视 LED55N3000U 折腾记录