v2ray 性能与稳定性优化记录

起因:v2ray 频繁出现 websocket: close 1006 (abnormal closure): unexpected EOF + common/mux: failed to ... 三连日志,伴随偶发掉连。 


范围:mux 多路复用、Sockopt TCP 选项、Linux 服务端内核参数。 


未改项:传输协议、TLS、Sniffing、路由、DNS、Policy、loglevel 保持原状。

改动概览

#改动需重启
1Mux客户端关闭 (enabled: false)v2ray
2Sockopt客户端 + 服务端启用 TFO / KeepAlive / NoDelay;服务端额外指定 tcpcongestion: bbrv2ray
3内核 sysctl + systemd服务端BBR+fq、TFO=3、收发缓冲区、连接队列、fd 上限sysctl 实时生效;systemd 改 NOFILE 需 daemon-reload + restart

一、Mux 多路复用:关闭

背景

Mux 把多条逻辑流复用到一条底层 TCP/WS 连接。一旦底层连接被 CDN / 中间设备断开,所有复用流同时报错——这就是日志里 1006 后跟一片 closed pipe 的根源。走 CDN 或长距离弱网时,关 mux 比开启更稳

配置位置

仅客户端 config.json  outbounds[],每个 vmess/vless 出口节点都加:

"outbounds": [{
  "protocol": "vmess",
  "settings": { /* ... */ },
  "streamSettings": { /* ... */ },
  "mux": {
    "enabled": false
  }
}]

服务端 inbound 没有对应的 mux 开关,自动识别并解复用,不需要改服务端

操作步骤

  1. 编辑客户端 v2ray 配置:

  2. 保存后重启客户端:

    # systemd
    sudo systemctl restart v2ray
    
    # GUI 客户端:在系统托盘菜单选 "重启" 或重连节点

验证

回滚

 "enabled": false 改回 true(或删除整个 mux 块走默认),重启 v2ray。


二、Sockopt:双端开启 TCP 调优

背景

让 v2ray 在创建 socket 时开启 TCP Fast Open、KeepAlive、TCP_NODELAY,并指定服务端发送方向的拥塞控制为 BBR。注意 必须双端都配 才能完整生效(TFO 要双端协商;BBR 设在哪端,那端发送时才走 BBR)。

配置位置

客户端 outbounds[].streamSettings

"outbounds": [{
  "streamSettings": {
    "sockopt": {
      "tcpFastOpen":           true,
      "tcpKeepAliveInterval":  30,
      "tcpKeepAliveIdle":      300,
      "tcpNoDelay":            true
    }
  }
}]

服务端 inbounds[].streamSettings(额外加 tcpcongestion):

"inbounds": [{
  "streamSettings": {
    "sockopt": {
      "tcpFastOpen":           true,
      "tcpKeepAliveInterval":  30,
      "tcpKeepAliveIdle":      300,
      "tcpNoDelay":            true,
      "tcpcongestion":         "bbr"
    }
  }
}]

字段说明

字段作用备注
tcpFastOpen启用 TFO,三次握手最后一包就带数据,省 1 个 RTT需双端 + 内核 tcp_fastopen=3 配合
tcpKeepAliveIdle多久空闲后开始发心跳(秒)300s
tcpKeepAliveInterval心跳间隔(秒)30s,可对抗 NAT / CDN idle 超时
tcpNoDelay关闭 Nagle,小包立即发出降低小请求延迟
tcpcongestion拥塞算法仅 Linux 有效,设在发送端;代理下载方向大头是服务端发,故服务端配 bbr

操作步骤

  1. 客户端:在 outbound 加 sockopt 块。

  2. 服务端:在 inbound 加 sockopt 块(含 tcpcongestion: "bbr")。

  3. 验证配置语法:

    /usr/local/bin/v2ray test -config /usr/local/etc/v2ray/config.json
  4. 重启服务:

    sudo systemctl restart v2ray

验证

# 服务端确认 v2ray 启动无错
sudo journalctl -u v2ray -n 50 --no-pager

# 内核层 TFO 是否启用(不开内核 TFO,sockopt 也无效)
sysctl net.ipv4.tcp_fastopen   # 期望 3

可选:用 tcpdump 抓 SYN 包确认 TFO Cookie:

sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0' -vv
# 关注输出里是否出现 "tfo cookie"

回滚

删除 sockopt 块整体,或将关心的字段单独置 false / 移除,重启 v2ray。


三、Linux 服务端内核参数

背景

长肥管道(高带宽 + 高 RTT)下 Linux 默认的 cubic + 约 6MB 缓冲跑不满线路;高并发新连接也会撞默认 somaxconn=128  LimitNOFILE=1024 上限。本节全部在服务端 Linux 主机上操作,与 v2ray 配置文件无关。

配置位置


新建 /etc/sysctl.d/99-v2ray.conf

或者在/etc/sysctl.conf追加下面内容也可以,然后systemctl -p也可以

# ---- 拥塞控制(吞吐量提升最大)----
net.core.default_qdisc          = fq
net.ipv4.tcp_congestion_control = bbr

# ---- TCP Fast Open(与 sockopt 配合)----
net.ipv4.tcp_fastopen = 3

# ---- 缓冲区(长肥管道)----
net.core.rmem_max   = 26214400
net.core.wmem_max   = 26214400
net.ipv4.tcp_rmem   = 4096 87380  26214400
net.ipv4.tcp_wmem   = 4096 16384  26214400

# ---- 连接队列 ----
net.core.somaxconn           = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse        = 1

# ---- 文件描述符(系统级)----
fs.file-max = 1000000

修改 systemd 服务(/etc/systemd/system/v2ray.service  /lib/systemd/system/v2ray.service),在 [Service] 段加:

[Service]
LimitNOFILE=1000000

⚠️ 小内存机器(< 1 GB)需按比例下调缓冲区,否则连接数一多 OOM。 ⚠️ 容器场景:sysctl 改的是宿主机内核,容器要么用 --privileged,要么 docker run --sysctl ... 显式声明。

操作步骤

# 1. 加载 sysctl 配置(不需要重启系统)
sudo sysctl --system

# 2. 若 BBR 模块未自动加载
sudo modprobe tcp_bbrecho tcp_bbr | sudo tee /etc/modules-load.d/bbr.conf   
# 开机自加载

# 3. systemd 改动必须 daemon-reload + restart,光改文件无效
sudo systemctl daemon-reload
sudo systemctl restart v2ray

验证

逐项检查:

# BBR
sysctl net.ipv4.tcp_congestion_control    # 期望: bbr
sysctl net.core.default_qdisc             # 期望: fq
lsmod | grep tcp_bbr                      # 期望有输出

# TFO 内核层
sysctl net.ipv4.tcp_fastopen              # 期望: 3

# 缓冲区
sysctl net.core.rmem_max                  # 期望: 26214400
sysctl net.ipv4.tcp_rmem                  # 期望: 4096 87380 26214400

# 连接队列
sysctl net.core.somaxconn                 # 期望: 4096
sysctl net.ipv4.tcp_max_syn_backlog       # 期望: 8192

# fd 系统级
sysctl fs.file-max                        # 期望: 1000000

# fd 进程级(最容易漏的一项)
cat /proc/$(pgrep -n v2ray)/limits | grep "Max open files"
# 期望: Max open files   1000000   1000000

一键自查脚本:

cat <<'EOF' | sudo bash
echo "=== BBR ==="
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc
lsmod | grep -E "^tcp_bbr" || echo "[!] bbr module NOT loaded"

echo; echo "=== TFO & buffers ==="
sysctl net.ipv4.tcp_fastopen net.core.rmem_max net.core.wmem_max
sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem

echo; echo "=== Conn queue ==="
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.ipv4.tcp_tw_reuse

echo; echo "=== File limits ==="
sysctl fs.file-max
PID=$(pgrep -n v2ray)
if [ -n "$PID" ]; then
  grep "Max open files" /proc/$PID/limits
else
  echo "[!] v2ray process not running"
fi
EOF

回滚

# 撤销 sysctl
sudo rm /etc/sysctl.d/99-v2ray.conf
sudo sysctl --system

# 撤销 systemd 改动:删除 LimitNOFILE 那一行
sudo systemctl daemon-reload
sudo systemctl restart v2ray

常见踩坑速查

现象原因处理
sysctl: cannot stat .../tcp_bbr内核版本 < 4.9uname -r 确认,升级内核
BBR 设了 sysctl 但仍显示 cubictcp_bbr 模块未加载modprobe tcp_bbr + 写入 /etc/modules-load.d/bbr.conf
LimitNOFILE=1000000  /proc/$PID/limits 仍 1024没 daemon-reload,或没 restart 服务,或服务文件路径不对systemctl cat v2ray 确认 systemd 实际读的文件
容器内 sysctl 报 read-only容器无内核权限宿主机改,或 docker run --sysctl net.ipv4.tcp_fastopen=3 ...
TFO 仍不生效客户端 / 服务端 / 内核 三处缺一三处都开(sockopt 双端 + tcp_fastopen=3
关 mux 后速度变慢但更稳预期行为,mux 本就是用稳定性换吞吐直连快线可重新开 mux;走 CDN 保持关闭




发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。