ss/ssr/v2ray/socks5 透明代理

先说 ss/ssr 透明代理吧,ss-redir 是 ss-libevssr-libev 中的一个工具,配合 iptables 可以在 Linux 上实现 ss、ssr 透明代理,ss-redir 的 TCP 透明代理是通过 REDIRECT 方式实现的,而 UDP 透明代理是通过 TPROXY 方式实现的。注意:ss-redir 只存在于 libev 版本。
当然,ss/ssr 透明代理并不是只能用 ss-redir 来实现,使用 ss-local + redsocks2 同样可以实现 socks5(ss-local 是 socks5 服务器)全局透明代理;ss-local + redsocks2 实际上是 ss-redir 的分体实现,TCP 使用 REDIRECT 方式实现,UDP 使用 TPROXY 方式实现。
最后说一下 v2ray 的透明代理,其实原理和 ss/ssr-libev 一样,v2ray 可以看作是 ss-local、ss-redir、ss-server 的合体,同一个 v2ray 程序既可以作为 server 端,也可以作为 client 端。所以 v2ray 的透明代理也有两种实现方式,一是利用对应的 “ss-redir”(dokodemo-door入站协议),二是利用对应的 “ss-local”(socks入站协议) + redsocks2(redsocks2 可与任意 socks5 代理组合以实现透明代理)。

方案说明

用过 Linux SS/SSR 客户端(尤其指命令行界面)的都知道,它们比 Windows/Android 中的 SS/SSR 客户端难用多了,安装好就只有一个 ss-local(libev 版还有 ss-redir、ss-tunnel,但我相信大部分人装的都是 python 版的),启动 ss-local 后并不会像 Windows/Android 那样自动配置系统代理,此时它仅仅是一个本地 socks5 代理服务器,默认监听 127.0.0.1:1080,如果需要利用该 socks5 代理上外网,必须在命令中指定对应的代理,如 curl -4sSkL -x socks5h://127.0.0.1:1080 https://www.google.com

但我想大部分人要的代理效果都不是这样的,太原始了。那能不能配置所谓的“系统代理”呢,可以是可以,但是好像只支持 http 类型的代理,即在当前 shell 中设置 http_proxyhttps_proxy 环境变量,假设存在一个 http 代理(支持 CONNECT 请求方法),监听地址是 127.0.0.1:8118,可以这样做:export http_proxy=http://127.0.0.1:8118; export https_proxy=$http_proxy。执行完后,git、curl、wget 等命令会自动从环境变量中读取 http 代理信息,然后通过 http 代理连接目的服务器。

那问题来了,ss-local 提供的是 socks5 代理,不能直接使用怎么办?也简单,Linux 中有很多将 socks5 包装为 http 代理的工具,比如 privoxy。只需要在 /etc/privoxy/config 里面添加一行 forward-socks5 / 127.0.0.1:1080 .,启动 privoxy,默认监听 127.0.0.1:8118 端口,注意别搞混了,8118 是 privoxy 提供的 http 代理地址,而 1080 是 ss-local 提供的 socks5 代理地址,发往 8118 端口的数据会被 privoxy 处理并转发给 ss-local。所以我们现在可以执行 export http_proxy=http://127.0.0.1:8118; export https_proxy=$http_proxy 来配置当前终端的 http 代理,这样 git、curl、wget 这些就会自动走 ss-local 出去了。

当然我们还可以利用 privoxy 灵活的配置,实现 Windows/Android 中的 gfwlist 分流模式。gfwlist.txt 其实是对应的 Adblock Plus 规则的 base64 编码文件,显然不能直接照搬到 privoxy 上。这个问题其实已经有人解决了,利用 snachx/gfwlist2privoxy python 脚本就可轻松搞定。但其实我也重复的造了一个轮子:zfl9/gfwlist2privoxy,至于为什么要造这个轮子,是因为我当时运行不了他的脚本(也不知道什么原因),所以花了点时间用 shell 脚本实现了一个 gfwlist2privoxy(但其实我是用 perl 转换的,只不过用 shell 包装了一下)。脚本转换出来的是一个 gfwlist.action 文件,我们只需将该 gfwlist.action 文件放到 /etc/privoxy 目录,然后在 config 中添加一行 actionsfile gfwlist.action(当然之前 forward-socks5 那行要注释掉),重启 privoxy 就可以实现 gfwlist 分流了。

但仅仅依靠 http_proxyhttps_proxy 环境变量实现的终端代理效果不是很好,因为有些命令根本不理会你的 http_proxyhttps_proxy 变量,它们依旧走的直连。但又有大神想出了一个巧妙的方法,即 rofl0r/proxychains-ng,其原理是通过 LD_PRELOAD 特殊环境变量提前加载指定的动态库,来替换 glibc 中的同名库函数。这个 LD_PRELOAD 指向的其实就是 proxychains-ng 实现的 socket 包装库,这个包装库会读取 proxychains-ng 的配置文件(这里面配置代理信息),之后执行的所有命令调用的 socket 函数其实都是 proxychains-ng 动态库中的同名函数,于是就实现了全局代理,而命令对此一无所知。将 proxychains-ng 与 privoxy 结合起来基本上可以完美实现 ss/ssr 的本地全局 gfwlist 代理(小技巧,在 shell 中执行 exec proxychains -q bash 可以实现当前终端的全局代理,如果需要每个终端都自动全局代理,可以在 bashrc 文件中加入这行)。

但很多人对此依旧不满意,因为他们想实现 OpenWrt 这种路由级别的全局透明代理(并且还有 gfwlist、绕过大陆地址段这些分流模式可选择),这样只要设备连到该路由就能直接无缝上网,完全感觉不到“墙”的存在。如果忽略分流模式(即全部流量都走代理出去),那么实现是很简单的(几条 iptables 就可以搞定,但是这太简单粗暴了,很多国内网站走代理会非常慢,体验很不好);但是如果要自己实现 gfwlist、绕过大陆地址段这些模式,就稍微有点点复杂了,尤其是 gfwlist 模式。但这种透明代理的模式的确很诱人,毕竟只要设置一次就可以让所有内网设备上 Internet,于是我开始摸索如何在 Linux 中实现类似 OpenWrt 的代理模式,而我摸索出来的成果就是 ss-tproxy 透明代理脚本,ss-tproxy 可以运行在 Linux 软路由(网关)、Linux 物理机、Linux 虚拟机等环境中;可以透明代理 ss-tproxy 主机自己以及所有网关和 DNS 指向 ss-tproxy 主机的内网主机的 TCP、UDP 流量。

代理脚本

https://github.com/zfl9/ss-tproxy

安装依赖

curl

请检查 curl 是否支持 HTTPS 协议,使用 curl --version 可查看(Protocols)

perl5

Perl5 的版本最好 v5.10.0+ 以上(使用 perl -v 命令可查看)

ipset

TPROXY

TPROXY 是一个 Linux 内核模块,在 Linux 2.6.28 后进入官方内核。一般正常的发行版都没有裁剪 TPROXY 模块,TPROXY 模块缺失问题主要出现在无线路由固件上(某些精简型发行版也会去掉 TPROXY 模块,比如 Alpine)。使用以下方法可以检测当前内核是否包含 TPROXY 模块。

iproute2

dnsmasq

对于 gfwlist/chnlist 模式,需要确保该 dnsmasq 支持 --ipset 选项。

chinadns-ng

chinadns-ng 是我利用业余时间用 C 语言编写的另一个 chinadns,修复若干问题,优化了性能。

# 获取源码
git clone https://github.com/zfl9/chinadns-ng

# 编译安装
cd chinadns-ng
make && sudo make install

dns2tcp

dns2tcp 是一个用 C 语言写的小工具,专做 dns udp2tcp 转换,具体编译方法见 dns2tcp 的 README。

ipt2socks

ipt2socks 是一个用 C 语言写的小工具,专做 iptables-to-socks5 转换,具体编译方法见 ipt2socks 的 README。

v2ray

安装很简单,直接使用 v2ray 官方提供的 shell 脚本即可,默认配置开机自启

ss-libev

ArchLinux 建议使用 pacman -S shadowsocks-libev 安装,方便快捷,更新也及时。
CentOS/RHEL 或其它发行版,强烈建议 编译安装,仓库安装的可能会有问题(版本太老或者根本用不了)。
下面的代码完全摘自 ss-libev 官方 README.md,随着时间的推移可能有变化,最好照着最新 README.md 来做。

ssr-libev

shadowsocksr-backup/shadowsocksr-libev(貌似已停止更新,但目前使用没问题,只是一些新特性不支持,如有更好的源请告诉我~)
https://github.com/shadowsocksrr/shadowsocksr-libev/tree/Akkariiin/master,另一个 ssr-libev 源,Akkariiin-* 分支目前仍在更新
本文仍以 shadowsocksr-backup/shadowsocks-libev 为例,毕竟另一个源我没试过,但是这个源我自己用过大半年,没有任何问题,很稳定

如果编译失败,可以看下这个 issue:https://github.com/shadowsocksrr/shadowsocksr-libev/issues/40(gcc 版本过高导致的)
解决方法就是使用此分支:git clone -b Akkariiin/develop https://github.com/shadowsocksrr/shadowsocksr-libev.git

haveged

如果有时候启动 ss-redir、ss-tunnel 会失败,且错误提示如下,则需要安装 haveged 或 rng-utils/rng-tools。

这里以 haveged 为例,当然,你也可以选择安装 rng-utils/rng-tools,都是一样的:

代理测试

测试 IPv4
这里就简单的使用 curl 进行测试,如果有网页源码输出,基本就没什么问题:

测试 IPv6
对于 ss-tproxy v4.x,如果启用了 ipv6 透明代理,可进行一些简单的 ipv6 测试:

# 访问 IPv6 的百度和谷歌
curl -6vsSkL https://ipv6.baidu.com
curl -6vsSkL https://ipv6.google.com

测试分流
也可以使用 curl 进行一个简单的分流模式验证,原理就是检查访问网站用的外部 IP:

# global 模式: 理论显示代理 IP
# gfwlist 模式: 理论显示本地 IP
# chnroute 模式: 理论显示本地 IP
curl -4sSkL https://myip.ipip.net

原理解析

ss-tproxy v3.0 已过时,ss-tproxy v4.6 的原理解析有时间再补。// TODO

常见问题

ss-tproxy v3.0 已过时,请更新至 ss-tproxy v4.6,此处的问答均针对 ss-tproxy v4.6。

建议在 github 上报告 ss-tproxy 相关问题,disqus 评论在国内无法访问,而且也不好追溯。

做 代理网关/单臂路由/旁路网关 时,ss-tproxy 主机代理正常,其它主机代理异常
如果异常情况为:黑名单地址正常访问,白名单地址不可访问;那么请将 ipts_set_snat(IPv4)、ipts_set_snat6(IPv6)设为 true。另外检查一下 ss-tproxy 主机上是否预设了某些 iptables 规则,有部分 Linux 系统会将 FORWARD 链的默认策略设为 DROP 状态,如果有这种情况,请进行一些合理的调整,如果对 iptables 不是很熟悉,请参照下面的步骤,配置 pre_start 钩子函数。

代理出现异常时,应留意系统是否预设了某些 iptables 规则、是否有相关规则与 ss-tproxy 冲突
如果你对 iptables 规则不是很了解,最好请在启动 ss-tproxy 之前将 iptables 规则清空,并将相关的默认策略设为 ACCEPT。建议使用 ss-tproxy 的 pre_start() 钩子来做这件事,编辑 ss-tproxy.conf 配置文件,然后添加如下内容即可(这些语句会在 ss-tproxy 执行启动逻辑之前自动执行):

pre_start() {
    if is_true "$ipv4"; then
        iptables -t raw -F
        iptables -t raw -X
        iptables -t raw -P PREROUTING ACCEPT
        iptables -t raw -P OUTPUT ACCEPT

        iptables -t mangle -F
        iptables -t mangle -X
        iptables -t mangle -P PREROUTING ACCEPT
        iptables -t mangle -P INPUT ACCEPT
        iptables -t mangle -P FORWARD ACCEPT
        iptables -t mangle -P OUTPUT ACCEPT
        iptables -t mangle -P POSTROUTING ACCEPT

        iptables -t nat -F
        iptables -t nat -X
        iptables -t nat -P PREROUTING ACCEPT
        iptables -t nat -P INPUT ACCEPT
        iptables -t nat -P OUTPUT ACCEPT
        iptables -t nat -P POSTROUTING ACCEPT

        iptables -t filter -F
        iptables -t filter -X
        iptables -t filter -P INPUT ACCEPT
        iptables -t filter -P FORWARD ACCEPT
        iptables -t filter -P OUTPUT ACCEPT
    fi

    if is_true "$ipv6"; then
        ip6tables -t raw -F
        ip6tables -t raw -X
        ip6tables -t raw -P PREROUTING ACCEPT
        ip6tables -t raw -P OUTPUT ACCEPT

        ip6tables -t mangle -F
        ip6tables -t mangle -X
        ip6tables -t mangle -P PREROUTING ACCEPT
        ip6tables -t mangle -P INPUT ACCEPT
        ip6tables -t mangle -P FORWARD ACCEPT
        ip6tables -t mangle -P OUTPUT ACCEPT
        ip6tables -t mangle -P POSTROUTING ACCEPT

        ip6tables -t nat -F
        ip6tables -t nat -X
        ip6tables -t nat -P PREROUTING ACCEPT
        ip6tables -t nat -P INPUT ACCEPT
        ip6tables -t nat -P OUTPUT ACCEPT
        ip6tables -t nat -P POSTROUTING ACCEPT

        ip6tables -t filter -F
        ip6tables -t filter -X
        ip6tables -t filter -P INPUT ACCEPT
        ip6tables -t filter -P FORWARD ACCEPT
        ip6tables -t filter -P OUTPUT ACCEPT
    fi
}

ss-tproxy status 显示不准确(已运行却显示 stopped)
首先检查 ss-tproxy.conf 中的 opts_ss_netstat 选项是否设置正确,默认是 auto 自选选择模式,即如果有 ss 就优先使用 ss 命令,如果没有才会去使用 netstat 命令;如果自动选择模式对你不适用,那么可以改为 ss 或 netstat 来明确告诉 ss-tproxy 你要使用哪个端口检测命令。如果确认不是设置问题,而是在执行 ss-tproxy start|restart 操作后,某些状态为 stopped,然后当你再次执行 ss-tproxy status 查看状态时,它们又变为了 running,那么不用担心,这只是 ss/netstat 的一个检测延迟而已。

ss-tproxy 现在是否支持 ipv6 的透明代理(v4.x 版本已支持)
ipv6 已经在 ss-tproxy v4.x 中实现,欢迎大家进行测试,我目前并没有 ipv6 环境,测试是在某位热心网友协助下进行的,在此表示感谢。虽然 ss-tproxy v4.6 版本的 ipv6 透明代理不需要任何额外的配置,直接使用 gua 地址即可实现透明代理,但是仍然有个比较烦的地方,那就是 gua 地址随时会变化;如果无法忍受这种情况,可以给我们的设备分配一个 ula 地址段,ula 地址就如同 192.168.0.0/16 这样的 ipv4 私有地址,我们仅需给 ss-tproxy 主机固定一个 ula 地址,然后将其它主机的 ipv6 默认网关设为 ss-tproxy 主机的 ula 地址即可,因为 ula 地址是我们自己内部管理和分配的,不会随时变动,这样就不用被 gua 地址牵着鼻子走了。不过要注意,如果使用 ula 地址实现 ipv6 透明代理,那么请打开 ss-tproxy.conf 的 ipts_set_snat6 选项,因为 ula 地址不可以在公网上被路由。

特别注意,ss-tproxy v3.0+ 要求代理服务器支持 udp 转发
对于 ss/ssr 来说,ss-redir/ssr-redir 需要开启 udp relay 功能,然后 ss-server/ssr-server 也需要开启 udp relay 功能,如果服务器还有防火墙规则,请注意放行对应的 udp 端口,此外还请确认你当地的 ISP 没有对 udp 流量进行恶意丢包。对于 v2ray(vmess),因为它的 udp 是通过 tcp 转发出去的(即 udp over tcp),所以不需要放行服务器的防火墙端口,也不需要担心 ISP 对 udp 流量的恶意干扰,因为走的是 tcp 而不是 udp。

ss-tproxy v4.6 版本已内置 tcponly 模式,如果 udp relay 始终失败,建议使用 tcponly 模式

如何只对指定的 host/addr 进行代理,其它的通通走直连
其实非常简单,使用 gfwlist 模式即可;gfwlist 模式会读取 gfwlist.txt、gfwlist.ext 两个黑名单文件,如果你只想代理某些域名、IP、网段,其它的都不想代理,可以直接将 gfwlist.txt 文件清空(执行命令 true >/etc/ss-tproxy/gfwlist.txt),然后编辑 gfwlist.ext 文件,填写要代理的域名、IP、网段即可(文件中有格式说明)。注意,在这种模式下就不要执行 update-chnlistupdate-gfwlist 命令了,因为它们会操作 gfwlist.txt 文件。

如何将 socks5 代理转换为 ss-tproxy v3.0+ 可用的透明代理
如果觉得编译 ss-libev、ssr-libev 很麻烦,也可以使用 ipt2socks 工具给任意 socks5 代理提供透明代理支持(如 ss-local、ssr-local、ssh动态端口转发、v2ray的socks5传入协议),ipt2socks 的具体编译方法在 README 中有详细说明,当然你也可以使用 redsocks/redsocks2 来做这种转换工作,这里就以 ipt2socks 为例吧。ipt2socks 的必要参数只有两个:-s 指定后端 socks5 服务器的地址,-p 指定后端 socks5 服务器的端口,一些例子:

# 默认为纯 TPROXY 模式
ipt2socks -s 127.0.0.1 -p 1080

# 使用 REDIRECT+TPROXY 混合模式
ipt2socks -s 127.0.0.1 -p 1080 -R

# 默认监听 60080 端口,可指定其它端口
ipt2socks -s 127.0.0.1 -p 1080 -l 61080

# 默认启用 TCP 和 UDP,可单独禁用它们
ipt2socks -s 127.0.0.1 -p 1080 -T # 仅启用 TCP 透明代理
ipt2socks -s 127.0.0.1 -p 1080 -U # 仅启用 UDP 透明代理

# 默认启用 IPv4 和 IPv6,可单独禁用它们
ipt2socks -s 127.0.0.1 -p 1080 -4 # 仅启用 IPv4 透明代理
ipt2socks -s 127.0.0.1 -p 1080 -6 # 仅启用 IPv6 透明代理

# 默认启动一个工作线程,启动多个线程可提高性能
ipt2socks -s 127.0.0.1 -p 1080 -j4 # 启动 4 个工作线程(SO_REUSEPORT)

# 默认只打印错误日志,在调试时请务必指定 -v 选项
ipt2socks -s 127.0.0.1 -p 1080 -v

假设启动参数为 ipt2socks -s 127.0.0.1 -p 1080,意味着我们应该使用纯 TPROXY 代理模式,即 ss-tproxy.conf 的 tproxy 配置项为 true,且 socks5 服务器监听在 127.0.0.1:1080/tcp,该 socks5 服务器支持 TCP 和 UDP 代理。以 ss-local 为例,首先还是配置 /etc/ss.json,如:

{
    "server": "服务器地址",
    "server_port": 服务器端口,
    "local_address": "127.0.0.1",
    "local_port": 1080,
    "method": "加密方式",
    "password": "用户密码",
    "no_delay": true,
    "fast_open": true,
    "reuse_port": true
}

服务器地址、服务器端口应该与 ss-tproxy.conf 中填写的一致,然后修改 proxy_startcmdproxy_stopcmd

proxy_startcmd='start_sslocal_ipt2socks'
proxy_stopcmd='kill -9 $(pidof ss-local) $(pidof ipt2socks)'

然后在 ss-tproxy.conf 的任意位置定义我们的 start_sslocal_ipt2socks 函数,比如在文件末尾添加:

start_sslocal_ipt2socks() {
    (ss-local -c /etc/ss.json -u </dev/null &>>/var/log/ss-local.log &)
    (ipt2socks -s 127.0.0.1 -p 1080 </dev/null &>>/var/log/ipt2socks.log &)
}

iptables: No chain/target/match by that name
如果是 iptables -j TPROXY 这条命令报的错(使用 ss-tproxy start -x 可查看调试信息),那就是没有 TPROXY 模块。

ss-tproxy.conf 中的函数不可重复定义
特别注意,因为 ss-tproxy 和 ss-tproxy.conf 都是一个 bash 脚本,所以这两个文件的内容也必须符合 bash 的语法规则,比如你不能在里面重复定义一个函数,虽然这不会报错,但是只有最后一个函数才会生效,这可能会坑死你,如果你定义了多个同名的 bash 函数,请将它们合并为一个!

切换为 gfwlist 模式后不能正常代理了
从其它模式切换到 gfwlist 模式时可能会出现此问题,原因是因为内网主机的 DNS 缓存。在访问被墙网站时,比如 www.google.com,客户机首先会进行 DNS 解析,因为之前解析过这个域名,因此客户机实际上并没有向外部网络发送 dns 解析请求,而是直接取出缓存中的 IP 地址,然后访问它;因为解析请求没有经过 ss-tproxy 主机的 dnsmasq 处理,所以对应 IP 也没有添加到 ipset-gfwlist 集合中,导致客户机发给该 IP 的数据包不会被 ss-tproxy 处理,也就是走直连出去了,GFW 当然不会让它通过了,也就出现了连接被重置等问题。解决方法也很简单,对于 Windows,请先关闭浏览器,然后打开 cmd.exe,执行 ipconfig /flushdns 来清空 DNS 缓存,然后重新打开浏览器,应该正常了;其它系统也差不多,清理 DNS 缓存即可。

有时会无法访问代理服务器
如果你在 ss-tproxy 中使用自己的 VPS 代理服务,且出现这么一个现象:访问其它地址都没问题,唯独不能正常访问自己的 VPS,比如 ssh 连不上,那么请检查你是否修改了这两个内核参数:net.ipv4.tcp_tw_reusenet.ipv4.tcp_tw_recycle,请确认它们的值都为 0(也就是禁用),vps 端和本地主机都检查一下,这两个内核参数其实默认都是为 0 的,也就是说,只要你没动过内核参数,基本不会出现这种诡异的问题。

ss-tproxy 支持什么发行版
一般都支持,没有限制。如果是路由器的那种系统或者其它的精简版系统,可能会有点问题,比如 TPROXY 模块缺失,自带的 bash 是阉割版,不支持 shell 数组等语法,不过都有相应的解决办法,不难移植。测试过的系统有:ArchLinux、RHEL、CentOS、Debian、Alpine、OpenWrt。

ss-tproxy 是否可以运行在虚拟机中
可以。以 VMware 为例,只需将网络设为 桥接模式 即可,这样这台虚拟机就接入了当前网络,与物理机没有区别。我在公司就是这样用的。

切换模式、切换节点不方便,能否避免直接修改文件
这确实是个问题,切换节点需要修改配置文件,切换模式需要修改配置文件,有没有更加简便一些的方式?抱歉,没有。不过因为 ss-tproxy.conf 是一个 shell 脚本,所以我们可以在这里面做些文章。如果你有很多个节点(付费机场一般都是,当然 ss-tproxy 可能更适合自建代理的用户),可以这样做:

如何提高代理的性能(当然仅针对 ss-redir、ssr-redir 这些)
首先,优先选择 C 语言版的 SS/SSR,当然 Python 版也没问题,然后服务器的监听端口我个人觉得 80 和 443 比较好一点,8080 也可以,貌似这些常用端口可以减少 QoS 的影响,当然这只是我个人的一些意见,然后就是修改内核参数,ss-tproxy 主机的 sysctl.conf 以及 vps 的 sysctl.conf 都建议修改一下,最好同步设置。另外我还有一个提速小技巧,那就是在 ss-tproxy 中启动多个 ss-redir、ssr-redir,它们都监听同一个地址和端口(是的你没听错),对于 ss-redir,需要添加一个 --reuse-port 选项来启用端口重用,而对于 ssr-redir,默认情况下就启用了端口重用,而且也没有这个选项。为了简单,这里就以 ss-redir 为例,老规矩,修改 ss-tproxy.conf,添加一个函数,用来启动 N 个 ss-redir 进程:

start_multiple_ssredir() {
    for ((i = 0; i < $1; ++i)); do
        (ss-redir -c /etc/ss.json -u --reuse-port </dev/null &>>/var/log/ss.log &)
    done
}

然后修改我们的启动命令,将 proxy_startcmd 改为 'start_multiple_ssredir 4',其中 4 可以改为任意正整数,这个数值的意思是启动多少个 ss-redir 进程,不建议超过当前的 CPU 核心数,太多了性能反而会下降,当然你也可以将它改为 1,此时只会启动一个进程,也就没有所谓的加速了。

ss-libev、ssr-libev 如何进行多节点负载均衡(SO_REUSEPORT)
其实非常简单,和上面的多进程 ss-libev、ssr-libev 加速差不多,只不过它们使用的 ss 服务器地址不一样而已,不过记得将 vps 地址加入到 proxy_svraddr4/6 数组,proxy_svrport 也记得放行相应的 vps 端口,然后定义 start_load_balancing() 函数用来启动多个 ss、ssr 进程:

start_load_balancing() {
    (ss-redir  -c /etc/ss1.json -u --reuse-port </dev/null &>>/var/log/ss1.log &)
    (ss-redir  -c /etc/ss2.json -u --reuse-port </dev/null &>>/var/log/ss2.log &)
    (ssr-redir -c /etc/ssr1.json -u </dev/null &>>/var/log/ssr1.log &)
    (ssr-redir -c /etc/ssr2.json -u </dev/null &>>/var/log/ssr2.log &)
}

然后修改 ss-tproxy.conf,将启动命令与关闭命令修改一下:

proxy_startcmd='start_load_balancing'
proxy_stopcmd='kill -9 $(pidof ss-redir) $(pidof ssr-redir)'

支持 ss-libev 或 ssr-libev 与 kcptun 一起使用吗
可以。ss-libev + kcptun 和 ssr-libev + kcptun 操作起来都差不多,为了简单,这里就以 ss-libev 为例。首先我假设你已经在 vps 上运行了 ss-server 和 kcptun-server,并且 ss-server 监听 0.0.0.0:8053/tcp+udp(监听 0.0.0.0 是为了处理 ss-redir 的 udp relay,因为 kcptun 只支持 tcp 协议的加速),kcptun-server 监听 0.0.0.0:8080/udp(用来加速 ss-redir 的 tcp relay,会被封装为 kcp 协议,使用 udp 传输);当然这些端口都是可以自定义的,我并没有规定一定要使用这两个端口!然后编辑 ss-tproxy.conf,修改 proxy 相关的配置,假设 vps 地址为 1.2.3.4:

注意,kcptun 的 client 和 server 程序默认并不是叫做 kcptun-clientkcptun-server,而是一个很难听的名字,如 client_linux_amd64server_linux_amd64,我为了好记,将它改为了 kcptun-client、kcptun-server;如果你没有改这个名字,那么你就需要修改一下上面的 kcptun-client 为对应的 client 二进制文件名,但是我建议你改一下,可以省去不少麻烦。然后你可能注意到了 start_sslibev_kcptun 这个命令,这实际上是我们待会要定义的一个函数,方便启动 ss-redir 和 kcptun-client,我们需要在 ss-tproxy.conf 中定义这个函数:

其实 ss-tproxy 完全不关心你使用什么代理,也不关心你怎么组合它们,只要逻辑走得通,就没有问题。