[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

posted @ 2025-08-13 21:33  夜歌乘年少  阅读(50)  评论(0)    收藏  举报