摘要:本篇文章记录了在保证服务器对外正常提供对外服务的情况下,如何使用wireguard接管服务器的全局出站流量。

wireguard安装

内核版本比较新的服务器

Linux kernel 版本在5.6以上,已原生内置 WireGuard 支持(于 2020 年合并)。不用在去手动安装

apt-get update
apt-get install wireguard-tools

运行完成后,运行下面命令,有类型下面的输出表示wireguard安装成功。

root@test:~# modinfo wireguard
filename:       /lib/modules/6.8.0-87-generic/kernel/drivers/net/wireguard/wireguard.ko.zst
alias:          net-pf-16-proto-16-family-wireguard
alias:          rtnl-link-wireguard
version:        1.0.0
author:         Jason A. Donenfeld <Jason@zx2c4.com>
description:    WireGuard secure network tunnel
license:        GPL v2
srcversion:     9BD2B2AF854D86752147554
depends:        libcurve25519-generic,udp_tunnel,ip6_udp_tunnel,libchacha20poly1305,curve25519-x86_64
retpoline:      Y
intree:         Y
name:           wireguard

内核版本比较老的服务器

Linux kernel 版本在5.6以下。

cat > /etc/apt/sources.list << EOF
deb http://archive.debian.org/debian/ buster main
deb http://archive.debian.org/debian-security buster/updates main
deb http://archive.debian.org/debian/ buster-backports main
EOF

apt-get update

# 下面这条命令很重要。如果不运行,可能出现apt-get install显示安装成功了,也会提示 Module wireguard not found in directory。
# 命令会将内核更新到最新的小版本(比如从 kernel 4.1升级到kernel 4.2),不会跨版本更新(比如从 kernel 4.0升级到kernel 5.0)
apt upgrade linux-image-amd64 linux-headers-amd64

apt-get install wireguard-dkms wireguard-tools

运行完成后,运行下面命令,有类型下面的输出表示wireguard安装成功。

root@vmtest:~# dkms status
wireguard, 1.0.20210219, 4.19.0-27-amd64, x86_64: installed

root@vmtest:~# modinfo wireguard
filename:       /lib/modules/4.19.0-27-amd64/updates/dkms/wireguard.ko
intree:         Y
alias:          net-pf-16-proto-16-family-wireguard
alias:          rtnl-link-wireguard
version:        1.0.20210219
author:         Jason A. Donenfeld <Jason@zx2c4.com>
description:    WireGuard secure network tunnel
license:        GPL v2
srcversion:     768ECDF7EFCFA2F491F6008
depends:        udp_tunnel,ip6_udp_tunnel
retpoline:      Y
name:           wireguard

配置教程

情景1

情景1:假如有两台服务器,后端服务器A、流量服务器B,后端服务器A对外提供22(ssh)、80(http)服务。在保证可以通过后端服务器A的公网ip访问服务的同时,后端服务器A所有自己的出站流量通过流量服务器B进行出口。

流量服务器B的配置如下:

root@vmb:~# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
root@vmb:~# sysctl -p

流量服务器B的wireguard配置文件示例:

[Interface]
Address = 172.25.1.10/24
ListenPort = 8001
PrivateKey = 0NVRC7Y2CUttYUHL+BvfrHSVn8EvmzuxBMAccaYw0nE=

[Peer]
PublicKey = 3pKQw+aWAOpkGPXe44esd+64RjjXVDndL0v2OhYrrSk=   #对端 Publickey
AllowedIPs = 172.25.1.0/24

创建一个 /etc/wireguard/wg0.conf 文件,把内容保存进去,注意文件名固定,必须叫 wg0.conf
然后执行下面的命令:

systemctl enable wg-quick@wg0
systemctl restart wg-quick@wg0

流量服务器B就配置好了。

后端服务器A的配置如下:

[Interface]
Address = 172.25.1.11/24
PrivateKey = +OYD60Biar0xO+oliwoM4q+/MSA60UM3KF41vraPLlw=
DNS = 114.114.114.114
PostUp = ip rule add from 172.27.201.240 table custom_eth0
PostUp = ip route add default via 172.27.207.253 dev eth0 table custom_eth0
PreDown = ip rule del from 172.27.201.240 table custom_eth0
PreDown = ip route del default via 172.27.207.253 dev eth0 table custom_eth0

[Peer]
PublicKey = A9VE413wEd++Qv1h3iEB74m0sJjospJnwO90y/BuIzM=   #对端 Publickey
Endpoint = 121.40.140.88:8001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

注意: 配置文件172.27.201.240、172.27.207.253 分别是后端服务器A的eth0网卡的ip地址和网关,需要根据自己的配置自行替换。
可以通过ip route show default查看,例如我的:

root@iZbp1b05v2lu3tai6zb7n3Z:~# ip route show default
default via 172.27.207.253 dev eth0 proto dhcp src 172.27.201.241 metric 100 

接着创建一个 /etc/wireguard/wg0.conf 文件,把内容保存进去,注意文件名固定,必须叫 wg0.conf
然后执行下面的命令:

systemctl enable wg-quick@wg0
systemctl restart wg-quick@wg0

配置完成后可以在后端服务器A上面运行 curl ifconfig.me来判断流量是否通过流量服务器B进行出口。

情景2

情景2:假如有两台服务器,后端服务器A、流量服务器B,后端服务器A对外提供22(ssh)、80(http)服务。后端服务器A的所有流量和服务都通过流量服务器B进行出口,可以通过流量服务器B的公网ip来访问A提供的服务。

很简单,服务器B配置一个frps

[common]
bind_addr = 172.25.1.10
bind_port = 7000
token=ADBHNGHJ123
proxy_bind_addr = 0.0.0.0

服务器B的wireguard配置文件:

[Interface]
Address = 172.25.1.10/24
ListenPort = 8001
PrivateKey = 0NVRC7Y2CUttYUHL+BvfrHSVn8EvmzuxBMAccaYw0nE=

[Peer]
PublicKey = 3pKQw+aWAOpkGPXe44esd+64RjjXVDndL0v2OhYrrSk=   #对端 Publickey
AllowedIPs = 172.25.1.0/24

服务器A的wireguard配置文件:

[Interface]
Address = 172.25.1.11/24
PrivateKey = +OYD60Biar0xO+oliwoM4q+/MSA60UM3KF41vraPLlw=
DNS = 114.114.114.114
PostUp = ip rule add from 172.27.201.240 table custom_eth0
PostUp = ip route add default via 172.27.207.253 dev eth0 table custom_eth0
PreDown = ip rule del from 172.27.201.240 table custom_eth0
PreDown = ip route del default via 172.27.207.253 dev eth0 table custom_eth0

[Peer]
PublicKey = A9VE413wEd++Qv1h3iEB74m0sJjospJnwO90y/BuIzM=   #对端 Publickey
Endpoint = 121.40.140.88:8001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

很简单,服务器A配置一个frpc

[common]
server_addr = 172.25.1.10
server_port = 7000
token=ADBHNGHJ123
login_fail_exit = false


[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 2222


[http]
type = tcp
local_ip = 127.0.0.1
local_port = 8001
remote_port = 8001

唯一要注意的一点就是,一定要先启动后端服务器A的frpc,然后再启动后端服务器A的wireguard。不然后端服务器A会失联

配置脚本

#!/bin/bash

# ====================================================
# WireGuard 生产级双端配置文件生成脚本 (Ubuntu 24.04)
# ====================================================

# 1. 依赖检查
if ! command -v wg &> /dev/null; then
    echo "❌ 错误: 未安装 wireguard-tools。"
    echo "请先执行: sudo apt update && sudo apt install wireguard-tools"
    exit 1
fi

if ! command -v curl &> /dev/null; then
    echo "❌ 错误: 未安装 curl。请先执行: sudo apt install curl"
    exit 1
fi

echo -e "\n⏳ 正在获取本机公网 IP..."

# 2. 获取公网 IP (使用 grep 提取 JSON 中的 ip 字段)
PUBLIC_IP=$(curl -s --connect-timeout 5 https://api.ip.sb/geoip/ | grep -oP '"ip":\s*"\K[^"]+')

if [ -z "$PUBLIC_IP" ]; then
    echo "⚠️ 警告: 无法通过 api.ip.sb/geoip/ 自动获取本机公网 IP。"
    read -p "👉 请手动输入 B 服务器的公网 IP: " PUBLIC_IP
else
    echo "✅ 成功获取公网 IP: $PUBLIC_IP"
fi

echo -e "\n⏳ 正在探测出口物理网卡名称..."

# 3. 网卡检测与交互 (优化部分)
# 尝试自动获取默认路由的网卡名
DETECTED_NIC=$(ip route | grep default | awk '{print $5}' | head -n 1)

if [ -n "$DETECTED_NIC" ]; then
    echo "✅ 系统自动检测到默认网卡为: [$DETECTED_NIC]"
    # 提示用户确认或修改,并设置 15 秒超时
    read -t 15 -p "👉 请确认是否使用该网卡作为 NAT 出口 (直接回车确认,或手动输入新的网卡名): " USER_INPUT_NIC
    
    # 判断用户是否输入了内容
    if [ -z "$USER_INPUT_NIC" ]; then
        DEFAULT_NIC="$DETECTED_NIC"
        echo "   -> 用户未输入,默认使用探测到的: $DEFAULT_NIC"
    else
        DEFAULT_NIC="$USER_INPUT_NIC"
        echo "   -> 使用用户手动指定的网卡: $DEFAULT_NIC"
    fi
else
    echo "⚠️ 警告: 系统未能自动检测到默认网卡。"
    # 提示用户手动输入,如果不输入则默认给 eth0
    read -t 15 -p "👉 请手动输入物理网卡名 (默认: eth0): " USER_INPUT_NIC
    
    if [ -z "$USER_INPUT_NIC" ]; then
        DEFAULT_NIC="eth0"
        echo "   -> 用户未输入,已回退使用默认值: eth0"
    else
        DEFAULT_NIC="$USER_INPUT_NIC"
        echo "   -> 使用用户手动指定的网卡: $DEFAULT_NIC"
    fi
fi

echo -e "\n⏳ 正在生成加密密钥..."

# 4. 生成密钥对
SERVER_PRIV=$(wg genkey)
SERVER_PUB=$(echo "$SERVER_PRIV" | wg pubkey)

CLIENT_PRIV=$(wg genkey)
CLIENT_PUB=$(echo "$CLIENT_PRIV" | wg pubkey)

# 5. 生成服务端配置文件 (B 服务器)
cat > wg0_server.conf <<EOF
[Interface]
# B 服务器隧道内网 IP
Address = 172.25.1.10/24
ListenPort = 8001
PrivateKey = $SERVER_PRIV

# 核心规则:允许内核转发并配置 NAT 伪装上网
PostUp = iptables -I FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -s 172.25.1.0/24 -o $DEFAULT_NIC -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 172.25.1.0/24 -o $DEFAULT_NIC -j MASQUERADE

[Peer]
# A 服务器 (客户端)
PublicKey = $CLIENT_PUB
AllowedIPs = 172.25.1.0/24
EOF

# 6. 生成客户端配置文件 (A 服务器)
cat > wg0_client.conf <<EOF
[Interface]
# A 服务器隧道内网 IP
Address = 172.25.1.11/24
PrivateKey = $CLIENT_PRIV
# 必须配置 DNS 防止解析死锁
DNS = 8.8.8.8, 1.1.1.1

# =========================================================================
# ⚠️ 高危防失联策略路由 (请在 A 服务器上手动修改尖括号内的参数)。如果要完全屏蔽A服务器流量可以不需要。
# =========================================================================
# 1. 请在 A 服务器上执行 echo "200 custom_eth0" >> /etc/iproute2/rt_tables
# 2. 解除下面 4 行的注释,并替换为你 A 服务器真实的公网 IP、网关和物理网卡名
# 3. 网关可以通过 ip route show default 查看
# PostUp = ip rule add from <A的公网IP> table custom_eth0
# PostUp = ip route add default via <A的公网网关> dev <A的物理网卡> table custom_eth0
# PreDown = ip rule del from <A的公网IP> table custom_eth0
# PreDown = ip route del default via <A的公网网关> dev <A的物理网卡> table custom_eth0
# =========================================================================

[Peer]
# B 服务器 (服务端)
PublicKey = $SERVER_PUB
Endpoint = ${PUBLIC_IP}:8001
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF

# 7. 权限收紧
chmod 600 wg0_server.conf wg0_client.conf

echo -e "\n🎉 配置文件生成完毕!"
echo "📄 服务端配置: wg0_server.conf"
echo "📄 客户端配置: wg0_client.conf"

frps服务配置

[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target wg-quick@wg0.service
Wants = network.target

[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /etc/wireguard/frpc -c /etc/wireguard/frpc.toml
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy = multi-user.target