背景
在实际部署中,使用 mihomo(Clash 的高性能核心)进行系统代理时,出现了 SFTP 上传失败、连接正常但卡死 的情况。
经过排查发现,SFTP 不走 http_proxy 环境变量,但 TUN 或 Redir 模式下的 mihomo 会全局接管 TCP 流量,影响了 SSH 通信稳定性,尤其是文件上传等长连接。
问题表现
xxx用户使用mihomo代理后,SFTP 上传卡死;xx用户无代理,上传一切正常;- 两用户均能正常建立连接,
ps aux | grep sftp显示会话活跃; - 上传失败无明显报错,怀疑为底层 TCP 拦截或路由错配。
原因分析
Clash/TUN 的“透明代理”机制
Clash TUN 模式会通过虚拟网卡或 iptables 将本地进程的 TCP 请求重定向至代理,默认全量流量都会走代理隧道,包括:
- SSH/SFTP;
- Git、rsync;
- 非浏览器程序等非 HTTP 通信。
解决方案一:扩展 NO_PROXY 变量
修改你的代理启动脚本,在启用代理时添加目标服务器白名单:
export NO_PROXY="localhost,127.0.0.1,::1,xx.xx.xx.xx,my-server.local"
建议补充所有常用局域网网段:
export NO_PROXY="localhost,127.0.0.1,::1,192.168.0.0/16,10.0.0.0/8,xx.xx.xx.xx"
这样环境变量会告知部分程序“不要使用代理连接这些地址”,尽管对 SSH 效果有限,但对于 curl、pip 等工具有效。
解决方案二:在 Clash 中设置 DIRECT 路由规则
编辑 ~/.config/mihomo/config.yaml,加入明确规则避免代理指定主机:
rules:
- IP-CIDR,192.168.0.0/16,DIRECT
- IP-CIDR,xx.xx.xx.xx/32,DIRECT
- DOMAIN-SUFFIX,local,DIRECT
- MATCH,PROXY
说明:
- 第一条允许整个局域网直连;
- 第二条针对目标服务器单独直连;
- 第三条直连
.local域名; - 最后一条兜底走代理。
注意规则顺序至关重要,必须先 DIRECT 再 PROXY。
进阶补充:用于 SFTP 的测试方法
你可以通过以下方式测试是否成功绕过代理:
curl
curl -v http://xx.xx.xx.xx --connect-timeout 3
sftp
sftp xxx@xx.xx.xx.xx
sftp> put test.txt
若上传成功且速度正常,则说明绕过成功。
完整脚本示例(优化版)
mihomo() {
case $1 in
on)
export http_proxy=http://127.0.0.1:7890
export https_proxy=$http_proxy
export NO_PROXY="localhost,127.0.0.1,::1,xx.xx.xx.xx"
pgrep -f mihomo || {
~/bin/mihomo -d ~/.config/mihomo/ -f ~/.config/mihomo/config.yaml &>~/.config/mihomo/log &
}
echo '已开启代理环境'
;;
off)
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY no_proxy NO_PROXY
pkill -9 -f mihomo
echo '已关闭代理环境'
;;
esac
}
总结
使用系统级代理时,一定要明确哪些流量应走代理,哪些应保持直连。对于 SSH、SFTP、Docker、Kubernetes 等低层服务:
- 尽量避免被全局代理干扰;
- 使用 NO_PROXY 或 Clash 规则进行精准分流;
- 代理“越智能”,越需要手动控制关键流量的“透明度”。
本方案适用于 mihomo, Clash.Meta, OpenClash, sing-box 等主流代理框架。