Skip to content

常见问题

zfl9 edited this page May 19, 2023 · 25 revisions

非标准的 IPv4 内网地址段

标准内网地址段如:10.0.0.0/8172.16.0.0/12192.168.0.0/16,如果你将其它 IP 段作为内网使用(有人甚至将公网 IP 段作为内网使用),那么强烈建议你纠正这个错误,这不仅会导致透明代理出问题,也会隐藏其它 bug(很多软件设计者并没有考虑到你使用的是一个非标准内网地址段)。如果因为各种原因无法更改(比如公司内部),那么请将相关网段加入 ignlist.ext

做 代理网关/单臂路由/旁路网关 时,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,那么不用担心,这只是因为代理进程从启动到监听 TCP/UDP 端口需要一个时间过程。

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 地址不可以在公网上被路由。

如果 udp 代理不可用,建议使用 tcponly 模式(v4.6+)

对于 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。

如何只对指定的 host/addr 进行代理,其它的通通走直连

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

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 模块缺失,不过都有相应的解决办法,不难移植。测试过的系统有:ArchLinux、RHEL、CentOS、Debian、Alpine、OpenWrt。

ss-tproxy 是否可以运行在虚拟机中

可以。以 VMware 为例,只需将网络设为 桥接模式 即可,这样这台虚拟机就接入了当前网络,与物理机基本没有区别。

与 UFW 一起使用的问题

如果使用了UFW,会出现局域网代理流量无法转发的问题,修复方法https://github.com/zfl9/ss-tproxy/issues/199: 打开/etc/ufw/before.rules,在-A ufw-before-input -j ufw-not-local这行下面加入以下内容:

# if TPROXY, RETURN
-A ufw-not-local -m mark --mark 0x2333 -j RETURN

如果fwmark不是0x2333,请修改为对应的fwmark。

请使用 root 权限执行 ss-tproxy 脚本

因为脚本涉及到iptables规则的修改,/etc/resolv.conf系统文件的修改等;所以,若无特殊说明,请用root权限执行脚本。

Clone this wiki locally