[linux] 基于WireGuard + tc 搭建弱网测试统一代理
在linux主机上安装WireGuard VPN,并使用tc命令对VPN的虚拟网卡wg0进行限速,然后使用VPN客户端连接到这台主机,即可轻松实现全平台的弱网测试。
tc的配置可通过脚本切换,实现随意切换不同的弱网环境的需求。
配置过程
系统准备
首先,检查系统是否支持sch_netem,应存在打印filename等信息
modinfo sch_netem
若报错sch_netem不存在,需要安装非kvm版本的linux内核
sudo apt install linux-image-generic linux-headers-generic
#卸载kvm版本内核
sudo apt autoremove --purge 'linux-image-*-kvm' 'linux-headers-*-kvm'
sudo reboot
#再次查看,应存在打印
modinfo sch_netem
VPN配置
安装 WireGuard VPN :
sudo apt install wireguard qrencode -y
生成WireGuard服务端公私钥 :
umask 077
# 生成私钥
wg genkey | sudo tee /etc/wireguard/server_privatekey
# 根据私钥生成公钥
sudo cat /etc/wireguard/server_privatekey | wg pubkey | sudo tee /etc/wireguard/server_publickey
#可用如下命令查看,保存好服务端公私钥
sudo cat /etc/wireguard/server_privatekey
sudo cat /etc/wireguard/server_publickey
编写服务端配置文件 /etc/wireguard/wg0.conf
需要修改 PrivateKey 和 PostUp PostDown 规则中的网卡名称
[Interface]
# 服务器在 VPN 网络中的私有 IP 地址。10.10.0.1 是一个常见的选择。
Address = 10.10.0.1/24
# 监听的 UDP 端口
ListenPort = 51820
# 填入您刚刚生成的服务器私钥
# 运行 `sudo cat /etc/wireguard/server_privatekey` 查看并复制粘贴
PrivateKey = PASTE_YOUR_SERVER_PRIVATE_KEY_HERE
# 启动 VPN 时自动配置 NAT 规则,让客户端能通过服务器访问互联网
# enp1s0 是服务器的公网网卡名,请根据实际情况修改 (可用 `ip addr` 命令查看)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
# --- 客户端配置将添加在此处 ---
生成客户端公私钥,并并写入服务端配置
我们写一个脚本批量处理
需要修改 PrivateKey 和 YOUR_SERVER_PUBLIC_IP 服务端公网IP地址
#!/bin/bash
# ================================================================= #
# WireGuard 批量客户端生成脚本 #
# ================================================================= #
# --- 请修改以下变量 ---
# 服务器的公钥 (运行 `sudo cat /etc/wireguard/server_publickey` 获取)
SERVER_PUBLIC_KEY="YOUR_SERVER_PUBLIC_KEY_HERE"
# 服务器的公网IP地址和端口
SERVER_ENDPOINT="YOUR_SERVER_PUBLIC_IP:51820"
# 您想要生成的客户端总数
CLIENT_COUNT=12
# VPN 的子网前缀,客户端IP将在此基础上递增
# 例如,如果设置为 10.10.0. ,客户端IP将是 10.10.0.2, 10.10.0.3 ...
VPN_SUBNET_PREFIX="10.10.0."
# 客户端配置文件的存放目录
CLIENT_CONFIG_DIR="/etc/wireguard/clients"
# 服务器配置文件的路径
SERVER_CONFIG_FILE="/etc/wireguard/wg0.conf"
# --- 脚本主逻辑 ---
# 检查 qrencode 是否安装 (用于生成二维码)
if ! command -v qrencode &> /dev/null
then
echo "警告: qrencode 未安装,无法生成二维码。可以运行 'sudo apt install qrencode' 来安装。"
fi
echo "开始批量生成 ${CLIENT_COUNT} 个 WireGuard 客户端配置..."
# IP地址从2开始,因为 .1 通常是服务器地址
for i in $(seq 2 $((CLIENT_COUNT + 1)))
do
CLIENT_NAME="client${i}"
CLIENT_IP="${VPN_SUBNET_PREFIX}${i}"
echo "---正在处理: ${CLIENT_NAME} (${CLIENT_IP})---"
# 1. 生成客户端密钥对
CLIENT_PRIVATE_KEY=$(wg genkey)
CLIENT_PUBLIC_KEY=$(echo "${CLIENT_PRIVATE_KEY}" | wg pubkey)
# 2. 将客户端的 [Peer] 配置追加到服务器配置文件
echo "# Client: ${CLIENT_NAME}" | sudo tee -a ${SERVER_CONFIG_FILE}
echo "[Peer]" | sudo tee -a ${SERVER_CONFIG_FILE}
echo "PublicKey = ${CLIENT_PUBLIC_KEY}" | sudo tee -a ${SERVER_CONFIG_FILE}
echo "AllowedIPs = ${CLIENT_IP}/32" | sudo tee -a ${SERVER_CONFIG_FILE}
echo "" | sudo tee -a ${SERVER_CONFIG_FILE}
echo "已将 ${CLIENT_NAME} 的 Peer 配置追加到 ${SERVER_CONFIG_FILE}"
# 3. 创建客户端 .conf 配置文件
CLIENT_CONFIG_FILE_PATH="${CLIENT_CONFIG_DIR}/${CLIENT_NAME}.conf"
# 使用 Here Document 创建文件,更清晰
cat <<EOF > "${CLIENT_CONFIG_FILE_PATH}"
[Interface]
PrivateKey = ${CLIENT_PRIVATE_KEY}
Address = ${CLIENT_IP}/24
DNS = 8.8.8.8, 1.1.1.1
[Peer]
PublicKey = ${SERVER_PUBLIC_KEY}
Endpoint = ${SERVER_ENDPOINT}
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF
echo "已为 ${CLIENT_NAME} 生成配置文件: ${CLIENT_CONFIG_FILE_PATH}"
# 4. (可选) 为配置文件生成二维码图片
if command -v qrencode &> /dev/null
then
qrencode -o "${CLIENT_CONFIG_FILE_PATH}.png" < "${CLIENT_CONFIG_FILE_PATH}"
echo "已为 ${CLIENT_NAME} 生成二维码: ${CLIENT_CONFIG_FILE_PATH}.png"
fi
done
# 修改客户端配置目录权限,防止普通用户误操作,但允许root读取
sudo chmod 700 ${CLIENT_CONFIG_DIR}
echo "================================================================="
echo "批量生成完成!"
echo "所有客户端配置文件和二维码都已保存在 ${CLIENT_CONFIG_DIR} 目录中。"
echo "请不要忘记重启 WireGuard 服务来应用新的 Peer 配置:"
echo "sudo wg-quick down wg0 && sudo wg-quick up wg0"
echo "================================================================="
执行脚本
#先创建目录
sudo mkdir -p /etc/wireguard/clients
sudo chmod +x /etc/wireguard/batch_wg_clients.sh
sudo /etc/wireguard/batch_wg_clients.sh
#如果在已启动服务后修改客户端配置,脚本运行后,需重启wg服务
sudo wg-quick down wg0 && sudo wg-quick up wg0
启用内核ip转发
编辑 sysctl.conf 文件
sudo vim /etc/sysctl.conf
# 在末尾添加
net.ipv4.ip_forward=1
# 保存文件后,应用更改
sudo sysctl -p
#验证 以下命令应输出1
cat /proc/sys/net/ipv4/ip_forward
启动 WireGuard 服务
# 启动 wg0 这个接口的 WireGuard 服务
sudo wg-quick up wg0
# 设置开机自启
sudo systemctl enable wg-quick@wg0
#查看wg服务状态
sudo wg show
配置tc
首先测试系统tc功能正常
# 清除 wg0 上可能存在的旧规则
sudo tc qdisc del dev wg0 root
# 增加 300ms 延迟,并有 5% 的概率丢包
sudo tc qdisc add dev wg0 root netem delay 300ms loss 5%
#验证是否添加成功
sudo tc qdisc show dev wg0
然后使用客户端连接,验证延迟生效
为tc创建目录及脚本
# 创建一个存放脚本的目录
sudo mkdir -p /opt/network-scripts
# 创建并编辑脚本文件
sudo vim /opt/network-scripts/netsim.sh
sudo chmod +x /opt/network-scripts/netsim.sh
写入如下脚本
#!/bin/bash
# 网络模拟脚本 for WireGuard (wg0)
# 使用方法: sudo ./netsim.sh [profile_name]
INTERFACE="wg0"
PROFILE=$1
# 清除所有规则的函数
clear_rules() {
echo "Clearing all tc rules on $INTERFACE..."
sudo tc qdisc del dev $INTERFACE root 2>/dev/null || echo "No rules to clear."
}
# 应用规则的函数
apply_rules() {
local rules=$1
echo "Applying rules to $INTERFACE: $rules"
# 使用 'replace' 可以方便地替换现有规则,无需先删除
sudo tc qdisc replace dev $INTERFACE root netem $rules
echo "Current rules:"
sudo tc qdisc show dev $INTERFACE
}
# 检查接口是否存在
if ! ip link show $INTERFACE > /dev/null 2>&1; then
echo "Error: Interface $INTERFACE does not exist."
exit 1
fi
case "$PROFILE" in
"clear")
clear_rules
;;
"high-latency-loss") # 默认弱网配置
apply_rules "delay 500ms loss 5%"
;;
"3g") # 模拟普通3G网络
apply_rules "delay 200ms 50ms loss 2% rate 750kbit"
;;
"edge") # 模拟2G/EDGE网络
apply_rules "delay 500ms 100ms loss 5% rate 240kbit"
;;
"unreliable") # 高丢包网络
apply_rules "loss 15% delay 50ms"
;;
"jitter") # 高抖动网络 (延迟在100ms±40ms间波动)
apply_rules "delay 100ms 40ms distribution normal"
;;
"bandwidth-1mbps") # 仅限速1Mbps
# 对于单纯限速,使用 tbf 更合适
sudo tc qdisc replace dev $INTERFACE root tbf rate 1mbit burst 32kbit latency 50ms
echo "Current rules:"
sudo tc qdisc show dev $INTERFACE
;;
*)
echo "Usage: sudo $0 {clear|high-latency-loss|3g|edge|unreliable|jitter|bandwidth-1mbps}"
exit 1
;;
esac
exit 0
使用方式
应用高延迟高丢包网络:sudo /opt/network-scripts/netsim.sh high-latency-loss
切换到模拟3G网络:sudo /opt/network-scripts/netsim.sh 3g
切换到仅限速1Mbps:sudo /opt/network-scripts/netsim.sh bandwidth-1mbps
清除所有弱网规则,恢复正常网络:sudo /opt/network-scripts/netsim.sh clear

浙公网安备 33010602011771号