基于wireguard的全局出站流量接管
摘要:本篇文章记录了在保证服务器对外正常提供对外服务的情况下,如何使用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本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。