Quantcast
Channel: 看得透又看得远者prevail. ppt.cc/flUmLx ppt.cc/fqtgqx ppt.cc/fZsXUx ppt.cc/fhWnZx ppt.cc/fnrkVx ppt.cc/f2CBVx
Viewing all 20523 articles
Browse latest View live

linux桌面系统上的全局代理程序:ss-tproxy

$
0
0

Linux 透明代理

什么是正向代理?

代理软件通常分为客户端(client)和服务端(server),server 运行在境外服务器(通常为 Linux 服务器),client 运行在本地主机(如 Windows、Linux、Android、iOS),client 与 server 之间通常使用 tcp 或 udp 协议进行数据通信。大多数 client 被实现为一个 http、socks5 代理服务器,一个软件如果想通过 client 进行科学上网,需要使用 http、socks5 协议与 client 进行数据交互,这是绝大多数人的使用方式。这种代理方式,我们称之为 正向代理。所谓正向代理就是,一个软件如果想要使用 client 的代理服务,需要经过特定的设置,否则不会经过 client 的代理。

什么是透明代理?

在正向代理中,一个软件如果想走 client 的代理服务,我们必须显式配置该软件,对该软件来说,有没有走代理是很明确的,大家都“心知肚明”。而透明代理则与正向代理相反,当我们设置好合适的防火墙规则(仅以 Linux 的 iptables 为例),我们将不再需要显式配置这些软件来让其经过代理或者不经过代理(直连),因为这些软件发出的流量会自动被 iptables 规则所处理,那些我们认为需要代理的流量,会被通过合适的方法发送到 client 进程,而那些我们不需要代理的流量,则直接放行(直连)。这个过程对于我们使用的软件来说是完全透明的,软件自身对其一无所知。这就叫做 透明代理。注意,所谓透明是对我们使用的软件透明,而非对 client、server 或目标网站透明,理解这一点非常重要。

透明代理如何工作?

在正向代理中,期望使用代理的软件会通过 http、socks5 协议与 client 进程进行交互,以此完成代理操作。而在透明代理中,我们的软件发出的流量是完全正常的流量,并没有像正向代理那样,使用 http、socks5 等专用协议,这些流量经过 iptables 规则的处理后,会被通过“合适的方法”发送给 client 进程(当然是指那些我们认为需要走代理的流量)。注意,此时 client 进程接收到不再是 http、socks5 协议数据,而是经过 iptables 处理的“透明代理数据”,“透明代理数据”从本质上来说与正常数据没有区别,只是多了一些“元数据”在里面,使得 client 进程可以通过 netfilter 或操作系统提供的 API 接口来获取这些元数据(元数据其实就是原始目的地址和原始目的端口)。那么这个“合适的方法”是什么?目前来说有两种:
  • REDIRECT:只支持 TCP 协议的透明代理。
  • TPROXY:支持 TCP 和 UDP 协议的透明代理。
因此,对于 TCP 透明代理,有两种实现方式,一种是 REDIRECT,一种是 TPROXY;而对于 UDP 透明代理,只能通过 TPROXY 方式来实现。为方便叙述,本文以 纯 TPROXY 模式 指代 TCP 和 UDP 都使用 TPROXY 来实现,以 REDIRECT + TPROXY 模式 指代 TCP 使用 REDIRECT 实现,而 UDP 使用 TPROXY 来实现,有时候简称 REDIRECT 模式,它们都是一个意思。

此脚本的作用及由来

通过上面的介绍,其实可以知道,在构建透明代理的过程中,需要的仅仅是 iptables、iproute2 以及 ss/ssr/v2ray 等支持透明代理的软件,那 ss-tproxy 脚本的作用是什么呢?如果你尝试搭建过透明代理,那么你就会体会到,这一过程其实并不容易,你需要设置许多繁琐的 iptables 规则,还要应对国内复杂的 DNS 环境,另外还要考虑 UDP 透明代理的支持,此外你通常还希望这个透明代理能实现分流操作,而不是一股脑的全走代理。于是就有了 ss-tproxy 脚本,该脚本的目的就是辅助大家快速地搭建一个透明代理环境,该透明代理支持 gfwlist、chnroute 等常见分流模式,以及一个无污染的 DNS 解析服务;除此之外,ss-tproxy 脚本不做任何其它事情;因此你仍然需要 iptables、iproute2 以及 ss/ssr/v2ray 等支持透明代理的软件,因为透明代理的底层服务是由它们共同运作的,理解这一点非常重要。
为什么叫做 ss-tproxy?因为该脚本最早的时候只支持 ss 的透明代理,当然现在它并不局限于特定的代理软件。
另外还有一点需要注意,透明代理使用的 client 与正向代理使用的 client 通常是不同的,因为正向代理的 client 是 http、socks5 服务器,而透明代理的 client 则是透明代理服务器,它们之间有本质上的区别。对于 ss,你需要使用 ss-libev 版本(ss-redir),ssr 则需要使用 ssr-libev 版本(ssr-redir),而对于 v2ray,配置好 dokodemo-door 入站协议即可。再次强调,透明代理只是 client 不同,并不关心你的 server 是什么版本,因此你的 vps 上,可以运行所有与之兼容的 server 版本,以 ss/ssr 为例,你可以使用 python 版的 ss、ssr,也可以使用 golang 版的 ss、ssr 等等,只要它们之间可以兼容。
ss-tproxy 可以运行在 Linux 软路由/网关、Linux 物理机、Linux 虚拟机等环境中,可以透明代理 ss-tproxy 主机本身以及所有网关指向 ss-tproxy 主机的其它主机的 TCP、UDP 流量。也就是说,你可以在任意一台 Linux 主机上部署 ss-tproxy 脚本,然后同一局域网内的其它主机可以随时将其网关及 DNS 指向 ss-tproxy 主机,这样它们的 TCP 和 UDP 流量就会自动走代理了。
ss-tproxy v4.0 简介
  • 去除不常用的 global 分流模式
  • 支持 IPv4、IPv6 双协议栈的透明代理(可配置)
  • 使用 chinadns-ng 替代原版 chinadns,修复若干问题
  • 完美兼容"端口映射",只代理"主动出站"的流量,规则更加细致化
  • 支持配置要代理的黑名单端口,这样可以比较好的处理 BT/PT 流量
  • 支持自定义 dnsmasq/chinadns 端口,支持加载外部 dnsmasq 配置
  • ss-tproxy stop 后,支持重定向内网主机发出的 DNS 到本地直连 DNS
  • 支持网络可用性检查,无需利用其它的 hook 来避免脚本自启失败问题
  • 脚本逻辑优化及结构调整,尽量提高脚本的可移植性,去除非核心依赖
v4.0 只剩下 gfwlistchnroutechnlist 3 种分流模式,相关介绍:
  • gfwlist 分流模式:gfwlist.txt 中的域名走代理,其余走直连,即黑名单模式。
  • chnroute 分流模式:除了国内地址、保留地址之外,其余均走代理,即白名单模式。
  • chnlist 分流模式:本质还是 gfwlist 模式,只是域名列表为国内域名,即回国模式。
有人可能会有疑问,为什么使用 ss-tproxy 后,虽然可以访问谷歌,但依旧无法 ping 谷歌,这是为什么呢?这是因为 ping 走的是 ICMP 协议,没有哪个代理软件会去支持 ICMP 的代理,因为 ICMP 的代理并没有任何实际意义。

相关依赖

核心依赖:
  • iptables:核心部件,用于配置 IPv4 的透明代理规则。
  • ip6tables:核心部件,用于配置 IPv6 的透明代理规则。
  • xt_TPROXY:TPROXY 内核模块,这是必须的,无论什么模式。
  • ip:通常位于 iproute2 软件包,用于配置策略路由(TPROXY)。
  • ipset:ipset 用于存储 gfwlist 的黑名单 IP,以及 chnroute 的白名单 IP。
  • dnsmasq:基础 DNS 服务,对于 gfwlist 模式,该 dnsmasq 需要支持 --ipset 选项。
  • chinadns-ng:chnroute 模式的 DNS 服务,注意是 chinadns-ng,而不是原版 chinadns。
如果某些模式你基本不用,那么对应的依赖就不用管。比如,你不打算使用 IPv6 透明代理,则无需关心 ip6tables,又比如你不打算使用 chnroute 模式,也无需关心 chinadns-ng,安装依赖之前先检查当前系统是否已有对应依赖。
可选依赖:
  • curl:用于更新 chnlist、gfwlist、chnroute 分流模式的相关列表。
  • base64:用于更新 gfwlist 的域名列表,gfwlist.txt 是 base64 格式编码的。
  • perl:用于更新 gfwlist 的域名列表,gfwlist.txt 是 adblock plus 规则,要进行转换。

安装脚本

git clone https://github.com/zfl9/ss-tproxy
cd ss-tproxy
chmod +x ss-tproxy
cp -af ss-tproxy /usr/local/bin
mkdir -p /etc/ss-tproxy
cp -af ss-tproxy.conf gfwlist* chnroute* /etc/ss-tproxy
cp -af ss-tproxy.service /etc/systemd/system #可选,安装 service 文件

卸载脚本

ss-tproxy stop
ss-tproxy flush-postrule
ss-tproxy delete-gfwlist
rm -fr /usr/local/bin/ss-tproxy /etc/ss-tproxy #删除脚本及配置文件
升级脚本前请先卸载脚本,如果有残留规则无法清除,请务必重启系统。

文件列表

  • ss-tproxy:shell 脚本,欢迎各位大佬一起来改进此脚本。
  • ss-tproxy.conf:配置文件,本质是 shell 脚本,修改需重启生效。
  • ss-tproxy.service:systemd 服务文件,用于 ss-tproxy 的开机自启。
  • chnroute.set:IPv4 国内地址及保留地址的 ipset 文件,不要手动修改。
  • chnroute6.set:IPv6 国内地址及保留地址的 ipset 文件,不要手动修改。
  • gfwlist.txt:存储 gfwlist、chnlist 分流模式的黑名单域名,不要手动修改。
  • gfwlist.ext:存储 gfwlist、chnlist 分流模式的扩展黑名单,可配置,重启生效。
ss-tproxy 只是一个 shell 脚本,并不是常驻后台的服务,因此所有的修改都需要 restart 来生效。

配置说明

  • 注释:井号开头的行为注释行,配置文件本质上是一个 shell 脚本,对于同名变量或函数,后定义的会覆盖先定义的。
  • mode:分流模式,默认为 chnroute 模式,可根据需要修改为 gfwlist 模式;需要说明的是,如果想使用 chnlist 回国模式,那么 mode 依旧为 gfwlist,gfwlist 模式与 chnlist 模式共享 gfwlist.txtgfwlist.ext 文件,因此使用 chnlist 模式前,需要先执行 ss-tproxy update-chnlist 将 gfwlist.txt 替换为国内域名,同时手动编辑 gfwlist.ext 扩展黑名单,将其中的 Telegram IPv4/IPv6 地址段注释,此外你还需要修改 dns_direct/dns_direct6 为本地直连 DNS(如 Google 公共 DNS),然后修改 dns_remote/dns_remote6 为大陆 DNS(如 114 公共 DNS,走国内代理)。
  • ipv4/ipv6:启用 IPv4/IPv6 透明代理,你需要确保本机代理进程能正确处理 IPv4/IPv6 相关数据包,脚本不检查它。
  • tproxy:true 为纯 TPROXY,false 为 REDIRECT/TPROXY 混合,ss/ssr 只能使用 false,v2ray 经配置后可使用 true。
  • proxy_svraddr4/proxy_svraddr6:填写 VPS 服务器的外网 IPv4/IPv6 地址,IP 或域名都可以,填域名要注意,这个域名最好不要有多个 IP 地址与之对应,因为脚本内部只会获取其中某个 IP,这极有可能与本机代理进程解析出来的 IP 不一致,这可能会导致 iptables 规则死循环,应尽量避免这种情况,比如你可以将该域名与其中某个 IP 的映射关系写到 ss-tproxy 主机的 /etc/hosts 文件中,这样解析结果就是可预期的。允许填写多个 VPS 地址,用空格隔开,填写多个地址的目的是方便切换代理,比如我现在有两个 VPS,A、B,假设你先使用 A,因为某些因素,导致 A 的网络性能低下,那么你可能需要切换到 B,如果只填写了 A 的地址,就需要去修改 ss-tproxy.conf,将地址改为 B,修改启动与关闭命令,最后还得重启 ss-tproxy 脚本,很麻烦,更麻烦的是,如果现在 A 的网络又好了,那么你可能又想切换回 A,那么你又得重复上述步骤。但现在,你不需要这么做,你完全可以在 proxy_svraddr 中填写 A 和 B 的地址,假设你默认使用 A(proxy_startcmd 启动 A 代理进程),那么启动 ss-tproxy 后,使用的就是 A,此后如果想切换为 B,仅需停止 A 代理进程,再启动 B 代理进程(切回来的步骤则相反),该过程无需操作 ss-tproxy;这种配置下应注意 proxy_stopcmd,stopcmd 最好能停止 A 和 B 进程,不然切换进程后执行 ss-tproxy stop 可能不会正确停止相关的代理进程。另外,你只需填写实际会使用到的 VPS 地址,比如本机代理进程仅使用 IPv4 访问 VPS,则 proxy_svraddr6 可能是空的,反之,如果本机代理进程仅使用 IPv6 访问 VPS,则 proxy_svraddr4 可能是空的;这两个数组是否为空与 ipv4ipv6 选项没有必然的联系,比如你可以启用 IPv4 和 IPv6 透明代理,但是本机代理进程仅使用 IPv4 访问 VPS,这是完全可以的,但不允许 proxy_svraddr4 与 proxy_svraddr6 都为空,你至少需要填写一个地址。
  • proxy_svrport:填写 VPS 上代理服务器的外部监听端口,格式同 ipts_proxy_dst_port,填写不正确会导致 iptables 规则死循环。如果是 v2ray 动态端口,如端口号 1000 到 2000 都是代理监听端口,则填 1000:2000(含边界)。
  • proxy_tcpport/proxy_udpport:本机代理进程的透明代理监听端口,前者为 TCP 端口,后者为 UDP 端口,通常情况下它们是相同的,根据实际情况修改。需要注意的是,ss-tproxy v3.0 之后都要求代理软件支持 UDP,否则 DNS 是无法正常解析的,请务必检查 UDP 代理的连通情况,对于 ss/ssr,它们的 UDP 代理数据是通过 UDP 协议进行传递的,某些 ISP 可能会对 UDP 恶意丢包,v2ray 某些协议则为 UDP over TCP,对于这种情况则无需担心 UDP 丢包问题。
  • proxy_startcmd/proxy_stopcmd:前者是启动本机代理进程的 shell 命令,后者是关闭本机代理进程的 shell 命令。这些命令应该能快速执行完毕,否则会导致透明代理长期处于半启动或半关闭状态。具体的 startcmd、stopcmd 示例见后。
  • dnsmasq_bind_port:dnsmasq 监听端口,默认 53,如果端口已被占用则修改为其它未占用的端口,如 60053
  • dnsmasq_conf_dir/dnsmasq_conf_file:dnsmasq 外部配置文件/目录,被作为 conf-dirconf-file 选项值。
  • ipts_set_snat:是否设置 IPv4 的 MASQUERADE 规则,通常保持为 false 即可。有两种情况需要将其设置为 true:第一种,ss-tproxy 部署在出口路由位置且确实需要 MASQUERADE 规则(即该主机至少两张网卡,一张连接内网,一张连接公网,要进行源地址转换);第二种,在设置为 false 的情况下,代理不正常,那么也需要将其改为 true,曾经遇到过这种情况,可能与路由器的配置有关。注意,MASQUERADE 规则在 ss-tproxy stop 仍然是有效的,如果你想清空这些残留规则,可以执行 ss-tproxy flush-postrule 命令。
  • ipts_set_snat6:是否设置 IPv6 的 MASQUERADE 规则,默认为 true,通常你必须将其设置为 true,因为 IPv6 的透明代理需要利用 ULA 内网地址,如果设置为 false,那么其它内网主机将无法访问 IPv6 网络,因为 ULA 地址是不可以在公网上被路由的,因此你必须进行 SNAT 源地址转换。除非你使用 GUA 地址进行透明代理,但这样会让配置变得复杂且不易使用,因为 GUA 地址是动态变化的,运营商不会给你分配一个固定的 GUA 地址段。ss-tproxy stop 之后,这些规则仍然有效,如果你想清空这些残留规则,可以执行 ss-tproxy flush-postrule 命令。
  • ipts_intranet/ipts_intranet6:填写需要代理的内网网段,可以填写多个,空格隔开,当然也可以一个都不填,这表示只代理 ss-tproxy 主机自身的流量。对于 IPv6 透明代理,此选项有非常多值得讨论的地方,具体请看后文。
  • ipts_reddns_onstop:当 ss-tproxy stop 之后,是否使用 iptables 规则将内网主机发往 ss-tproxy 主机的 DNS 请求重定向至本地直连 DNS(即 dns_direct/dns_direct6),为什么要这么做呢?因为其它内网主机的 DNS 是指向 ss-tproxy 主机的,但是现在我们已经关闭了 ss-tproxy(dnsmasq 进程关闭了),所以这些内网主机会因为无法解析 DNS 而无法正常上网,而设置此选项后,这些 DNS 请求会被重定向给 114.114.114.114 等国内直连 DNS,这样它们就又可以正常上网了,在 ss-tproxy start 前,这些规则会自动删除,如果你需要手动删除这些规则,可以执行 ss-tproxy flush-postrule 命令。该选项的默认值为 true,如果 ss-tproxy 主机上有正常运行的 DNS 服务,那么这个选项应该设置为 false。
  • ipts_proxy_dst_port:告诉 ss-tproxy,黑名单地址的哪些目的端口需要走代理。所谓黑名单地址,对于 gfwlist/chnlist 模式来说,就是 gfwlist.txt/gfwlist.ext 里面的域名、IP、网段,对于 chnroute 模式来说,就是 chnroute/chnroute6 之外的地址(即国外地址),当然黑名单地址还包括 proxy_svraddr4/proxy_svraddr6 中所指定的 VPS 地址。该选项的默认值为 1:65535,因此只要我们访问黑名单地址,就会走代理,因为所有端口号都在其中。如果觉得端口范围太大,那么你可以修改这个选项的值,比如设置为 1:1023,8080,在这种配置下,只有当我们访问黑名单地址的 1 到 1023 和 8080 这些目的端口时才会走代理,访问黑名单地址的其它目的端口是不会走代理的,因此可以利用此选项来放行 BT、PT 流量,因为这些流量的目的端口通常都在 1024 以上。修改此选项需要足够小心,配置不当会导致某些常用软件无法正常走代理,因为它们使用的端口号可能不在你所指定的范围之内,因此指定为 1:65535 可能是最保险的一种做法。
  • opts_ss_netstat:告诉 ss-tproxy,使用 ss 还是 netstat 命令进行端口检测,目前检测本机代理进程是否正常运行的方式是直接检测其是否已监听对应的端口,虽然这种方式有时候并不准确,但是我现在貌似并没有其它更好的便携方法来做这个事情。选项的默认值为 auto,表示自动模式,所谓自动模式就是,如果当前系统有 ss 命令则使用 ss 命令进行检测,如果没有 ss 命令但是有 netstat 命令则使用 netstat 命令进行检测,而 ss 选项值则是明确告诉 ss-tproxy 使用 ss进行检测,同理,netstat 选项也是明确告诉 ss-tproxy 使用 netstat 进行端口检测。通常情况下保持 auto 即可。
  • opts_overwrite_resolv:如果设置为 true,则表示直接使用 I/O 重定向方式修改 /etc/resolv.conf 文件,这个操作是不可逆的,但是可移植性好;如果设置为 false,则表示使用 mount -o bind 魔法来暂时性修改 /etc/resolv.conf文件,当 ss-tproxy stop 之后,/etc/resolv.conf 会恢复为原来的文件,也就是说这个修改操作是可逆的,但是这个方式可能某些系统会不支持,默认为 false,如果遇到问题请修改为 true
  • opts_ip_for_check_net:指定一个允许 Ping 的 IP 地址(IPv4 或 IPv6 都行),用于检查外部网络的连通情况,默认为 114.114.114.114,注意这个 IP 地址应该为公网 IP,如果你填一个私有 IP,即使检测成功,也不能保证外网是可访问的,因为这仅代表我可以访问这个内网。根据实际网络环境进行更改,一般改为延迟较低且较稳定的一个 IP。
IPv6 透明代理的实施方式
如果你现在的网络已经支持 IPv6,那么你从 ISP 分配到的应该是 GUA 公网地址,但是 GUA 地址是随时会变化的(DHCP),这对于透明代理来说可是个糟糕的事情,因为 iptables 截获其它主机发出的数据包的原理是匹配它们的源 IP,也就是填写在 ipts_intranet6 选项中的 IP 段,如果你在这里填写 GUA 地址段,那么当 GUA 地址变更后,你需要及时的修改 ipts_intranet6 为最新的 GUA 地址段,否则 ss-tproxy 就将无法拿到其它设备发出的流量。显然,这样的体验非常糟糕。
那怎么办呢?一个可行的方案是,给我们的设备分配一个固定的 ULA 地址段,ULA 地址其实就相当于 IPv4 的 192.168.1.0/24 私有地址段,私有地址段只能在内部网络中使用,在公网上不允许被路由。但是这没关系,我们配置 ULA 地址的目的是为了让我们的设备有固定的 IP 段,而不会像 GUA 地址那样随时都发生变更。分配 ULA 地址后,我们的设备就有了两个 IPv6 地址,一个是 GUA 公网地址,一个是 ULA 私有地址。
ss-tproxy 的默认网关应保持不变,还是原有的 GUA 默认网关,以确保 ss-tproxy 主机能够正常访问 IPv6;而其它主机的默认网关则应修改为 ss-tproxy 主机的 ULA 地址,而不再是 DHCP 分配的 GUA 默认网关,这样它们发出的流量才会经过 ss-tproxy。然后我们在 ipts_intranet6 中填写此 ULA 网段,同时启用 ipts_set_snat6 选项,做源地址转换,因为 ULA 地址需要转换为 GUA 地址才能被路由。这其实和我们现在的 IPv4 NAT 网络差不多,不同的是,这些设备具有一个 IPv6 公网地址,因此我们仍然可以从外部 IPv6 网络访问这些具有 GUA 地址的设备。
但在实际测试中发现一个棘手的问题,我们的设备具有两个 IPv6 地址,当设备准备发送一个 IP 包时,会遇到源地址选择问题,比如它可能会选择 GUA 地址作为该 IP 包的源 IP,也可能会选择 ULA 地址作为该 IP 包的源 IP,如果它选择 ULA 地址作为源 IP,那没什么问题,符合我们的预期,但如果它选择 GUA 地址作为源 IP,就有问题了,这种情况将导致 ss-tproxy 主机的 iptables 规则无法拿到这些数据包,因为它们的源 IP 不再是 ULA 私有地址,而是 GUA 公网地址,这些数据包实际上会直接转发到国内网络,并没有走代理。
要避免这个问题目前有三种方案:
  1. 禁用除 ss-tproxy 主机外的其它主机的 GUA 地址,这样它们始终会使用 ULA 地址作为源 IP,但这会让 IPv6 变得毫无优势,因为这种配置下,完全等于我们之前的 IPv4 NAT 网络,没有任何本质区别。
  2. 配置除 ss-tproxy 主机外的其它主机的路由条目,强制使用 ULA 地址作为源 IP,而不是 GUA 地址,比如可以使用 ip route 的 src 选项,但是对于其它操作系统,尚不清楚如何干预源地址的选择。
  3. 另外还有一种方式,即在要走代理的设备上都分别部署 ss-tproxy 脚本,这样我们甚至不需要关心什么 GUA、ULA,因为我们只代理本机的流量,无需关心其它主机过来的流量,但这实际上并不太现实。
proxy_startcmdproxy_stopcmd
先说 ss-redir,首先配置好 ss-redir 的配置文件,如:
{
"server": "服务器地址",
"server_port": 服务器端口,
"local_address": "本地监听地址",
"local_port": 本地监听端口,
"method": "加密方式",
"password": "用户密码",
"no_delay": true,
"fast_open": true,
"reuse_port": true
}
服务器地址、服务器端口、本地监听端口应与 ss-tproxy.conf 中填写的一致,如果仅代理 ss-tproxy 主机自身的流量,本地监听地址可以为 127.0.0.1::1,否则必须为 0.0.0.0::。然后 proxy_startcmdproxy_stopcmd 可以这么写:
#proxy_startcmd='(ss-redir -c /etc/ss.json -u -v 
>/var/log/ss-redir.log &)' # -v 表示记录详细日志 proxy_startcmd='(ss-redir -c /etc/ss.json -u >/var/log/ss-redir.log &)'#这里就不记录详细日志了proxy_stopcmd='kill -9 $(pidof ss-redir)'
ssr-redir 也差不多,配置就不贴出来了,网上一大堆,注意事项同上,proxy_startcmdproxy_stopcmd 例子:
#proxy_startcmd='(ssr-redir -c /etc/ssr.json -u -v 
>/var/log/ssr-redir.log &)' proxy_startcmd='(ssr-redir -c /etc/ssr.json -u >/var/log/ssr-redir.log &)'proxy_stopcmd='kill -9 $(pidof ssr-redir)'
最后说下 v2ray,只关心本机代理进程的配置,v2ray 的透明代理配置比较简单,只需要在原有客户端配置的基础上,加上一个 dokodemo-door 入站协议即可。由于 v2ray 配置复杂,在报告透明代理有问题之前,请务必检查你的配置是否有问题,这里不想解答任何 v2ray 配置问题,原则上不建议在 v2ray 上配置任何分流或路由规则,脚本会为你做这些事,如果你硬要这么做,那么出问题请自行解决,这里不提供相关的指导。下面是一个简单的配置示例:
{
"log": {
"access":"/var/log/v2ray/access.log",
"error":"/var/log/v2ray/error.log",
"loglevel":"info"//调试时请改为 debug
},

"inbounds": [
{
"protocol":"dokodemo-door",
"listen":"0.0.0.0", //如果仅代理本机,可填环回地址
"port":60080, //本地监听端口必须与配置文件中的一致
"settings": {
"network":"tcp,udp", //注意这里是 tcp + udp
"followRedirect":true
},
"streamSettings": {
"sockopt": {
//"tproxy": "tproxy" // tproxy + tproxy 模式
"tproxy":"redirect"// redirect + tproxy 模式
}
}
}
],

"outbounds": [
{
"protocol":"shadowsocks",
"settings": {
"servers": [
{
"address":"node.proxy.net", //服务器地址
"port":12345, //服务器端口
"method":"aes-128-gcm", //加密方式
"password":"password"//用户密码
}
]
}
}
]
}
v2ray 的 proxy_startcmdproxy_stopcmd 例子,假设使用 systemctl 进行启动与停止,则:
proxy_startcmd='systemctl start v2ray'
proxy_stopcmd='systemctl stop v2ray'
钩子函数
ss-tproxy 脚本支持 4 个钩子函数,分别是 pre_start(启动前执行)、post_start(启动后执行)、pre_stop(停止前执行)、post_stop(停止后执行)。举个例子,在不修改 ss-tproxy 脚本的前提下,设置一些额外的 iptables 规则,假设我需要在 ss-tproxy 启动后添加某些规则,然后在 ss-tproxy 停止后再删除这些规则,则修改 ss-tproxy.conf,添加以下内容:
post_start() {
iptables -A ...
iptables -A ...
iptables -A ...
}

post_stop() {
iptables -D ...
iptables -D ...
iptables -D ...
}
需要注意的是,shell 中的函数是不允许重复定义的,虽然这不会有任何报错,但是实际只有最后一个函数生效。另外对于需要添加 iptables 规则的情况,可以考虑将 iptables 规则添加到 ss-tproxy 的自定义链上,这些自定义链在 ss-tproxy 停止后会自动删除,因此你只需要关心 post_start() 钩子函数的内容;目前有这几个自定义链:
$ipts -t mangle -N SSTP_PREROUTING
$ipts -t mangle -N SSTP_OUTPUT
$ipts -t nat -N SSTP_PREROUTING
$ipts -t nat -N SSTP_OUTPUT
$ipts -t nat -N SSTP_POSTROUTING
它们分别挂接到去掉 SSTP_ 前缀的同名预定义链上,如下:
$ipts -t mangle -A PREROUTING  -j SSTP_PREROUTING
$ipts -t mangle -A OUTPUT -j SSTP_OUTPUT
$ipts -t nat -A PREROUTING -j SSTP_PREROUTING
$ipts -t nat -A OUTPUT -j SSTP_OUTPUT
$ipts -t nat -A POSTROUTING -j SSTP_POSTROUTING
脚本开机自启
比较简单,对于 SysVinit 发行版,直接在 /etc/rc.d/rc.local 开机脚本中加上 ss-tproxy 的启动命令即可:
/usr/local/bin/ss-tproxy start
对于 Systemd 发行版,将 ss-tproxy.service 服务文件放到 /etc/systemd/system/ss-tproxy.service,然后执行:
systemctl daemon-reload
systemctl enable ss-tproxy
如果使用 Systemd 管理 ss-tproxy,应避免使用 ss-tproxy start|stop|restart 这几个命令,当然除了这几个命令外,其它命令都是可以执行的,比如 ss-tproxy statusss-tproxy update-gfwlist,为什么呢?因为 systemctl 启动一个脚本之后,systemctl 会在内部保存一个状态,即脚本已经 running,然后只有当你下次使用 systemctl 停止该脚本的时候,systemctl 内部才会将这个状态改为 stopped。所以当你执行 systemctl start ss-tproxy 后,这个服务的状态就是 running,如果你执行 ss-tproxy stop 来停止脚本,那么这个服务状态是不会变的,依旧是 running,但实际上它已经 stopped 了,而当你执行 systemctl start ss-tproxy 来启动脚本时,systemctl 并不会在内部执行 ss-tproxy start,因为这个服务的状态是 running,说明已经启动了,就不会再次启动了。这样一来就完全混乱了,你以为执行完毕后 ss-tproxy 就启动了,然而实际上,执行 ss-tproxy status 看下还是 stopped 的。为避免这种情况,请务必使用 systemctl start|stop|restart ss-tproxy,而不是 ss-tproxy start|stop|restart,换句话说,不要交叉使用这两套命令。
脚本命令行选项
  • ss-tproxy help:查看帮助信息
  • ss-tproxy version:查看版本号
  • ss-tproxy start:启动透明代理
  • ss-tproxy stop:关闭透明代理
  • ss-tproxy restart:重启透明代理
  • ss-tproxy status:查看代理状态
  • ss-tproxy show-iptables:查看当前的 iptables 规则
  • ss-tproxy flush-postrule:清空遗留的 iptables 规则
  • ss-tproxy flush-dnscache:清空 dnsmasq 的查询缓存
  • ss-tproxy delete-gfwlist:删除 gfwlist 黑名单 ipset
  • ss-tproxy update-chnlist:更新 chnlist(restart 生效)
  • ss-tproxy update-gfwlist:更新 gfwlist(restart 生效)
  • ss-tproxy update-chnroute:更新 chnroute(restart 生效)
  • 在任意位置指定 -x 选项可启用调试,如 ss-tproxy start -x
ss-tproxy delete-gfwlist 的作用:在 gfwlist/chnlist 模式下,ss-tproxy restartss-tproxy stop; ss-tproxy start 并不会移除 gfwlist 这个 ipset,如果你进行了 ss-tproxy update-gfwlistss-tproxy update-chnlist 操作,或者修改了 /etc/ss-tproxy/gfwlist.ext 文件,建议在 start 前执行一下此步骤,防止因为之前遗留的 gfwlist 列表导致奇怪的问题。注意,如果执行了 ss-tproxy delete-gfwlist 那么你可能还需要清空内网主机的 dns 缓存,并重启浏览器等被代理的应用。
如果你需要修改 ss-tproxy.conf 的特殊配置项,请先执行 ss-tproxy stop,然后再修改配置文件,最后再执行 ss-tproxy start 来生效,而不是改好配置后执行 ss-tproxy restart,这会出现不可预估的错误,需要遵循这个约定的配置项有:
  • ipv4
  • ipv6
  • proxy_stopcmd
  • ipts_rt_tab
  • ipts_rt_mark
  • opts_overwrite_resolv
  • file_dnsserver_pid
对于其它配置项,都可以在改完配置后,执行 ss-tproxy restart 命令来生效,无需遵循上述约定。
钩子函数小技巧
1、某些系统的 TPROXY 模块可能需要手动加载,对于这种情况,可以利用 pre_start() 钩子来加载它:
pre_start() {
#加载 TPROXY 模块
modprobe xt_TPROXY
}
2、chnroute 模式下,想放行某些不在 chnroute 中的 IP,可以利用 post_start() 将它们加到 ipset 中:
post_start() {
#定义要放行的 IPv4 地址
local chnroute_append_list=(11.22.33.44 44.33.22.11)
foripaddrin"${chnroute_append_list[@]}";do
ipset add chnroute $ipaddr&>/dev/null
done

#定义要放行的 IPv6 地址
local chnroute_append_list6=(2400:da00::6666 2001:dc7:1000::1)
foripaddrin"${chnroute_append_list6[@]}";do
ipset add chnroute6 $ipaddr&>/dev/null
done
}
如果还想放行某些域名,可以利用 dnsmasq_conf_file/dnsmasq_conf_dir 选项,首先创建一个 dnsmasq 配置文件,比如在 /etc/ss-tproxy 目录下创建 chnroute_ignore.conf,假设想放行 github.com 以及 github.io 两个域名,则配置内容如下:
server = /github.com/114.114.114.114
server = /github.io/114.114.114.114
ipset = /github.com/chnroute,chnroute6
ipset = /github.io/chnroute,chnroute6
然后在 ss-tproxy.conf 的 dnsmasq_conf_file 数组中写上该配置文件的绝对路径,如 dnsmasq_conf_file=(/etc/ss-tproxy/chnroute_ignore.conf),注意这只适合 chnroute 模式,如果想让配置更加智能些,即只在 chnroute 模式下加载该 dnsmasq 配置,可以将原有的 dnsmasq_conf_file 注释掉,然后在它下面写上一个简单的判断语句即可:
if [ "$mode"='chnroute' ];then
dnsmasq_conf_file=(/etc/ss-tproxy/chnroute_ignore.conf)
else
dnsmasq_conf_file=()
fi
3、不想让某些内网主机走 ss-tproxy 的透明代理,即使它们将网关设为 ss-tproxy 主机,那么可以这么做:
post_start() {
#定义要放行的 IPv4 地址
local intranet_ignore_list=(192.168.1.100 192.168.1.200)
foripaddrin"${intranet_ignore_list[@]}";do
iptables -t mangle -I SSTP_PREROUTING -s $ipaddr -j RETURN
iptables -t nat -I SSTP_PREROUTING -s $ipaddr -j RETURN
done

#定义要放行的 IPv6 地址
local intranet_ignore_list6=(fd00:abcd::1111 fd00:abcd::2222)
foripaddrin"${intranet_ignore_list6[@]}";do
ip6tables -t mangle -I SSTP_PREROUTING -s $ipaddr -j RETURN
ip6tables -t nat -I SSTP_PREROUTING -s $ipaddr -j RETURN
done
}
切换代理小技巧
如果觉得切换代理要修改 ss-tproxy.conf 很麻烦,可以这么做:将 proxy_startcmd 和 proxy_stopcmd 改为空调用,即 proxy_startcmd='true'proxy_stopcmd='true',然后配置好 proxy_svraddr4/6,将所有可能会用到的服务器地址都放进去,最后执行 ss-tproxy start 启动,因为我们没有填写任何代理进程的启动和停止命令,所以会显示代理进程未运行,没关系,现在我们要做的就是启动对应的代理进程,假设为 ss-redir 且使用 systemd 管理,则执行 systemctl start ss-redir,现在你再执行 ss-tproxy status 就会看到对应的状态正常了,当然代理也是正常的,如果需要换为 v2ray,假设也是使用 systemd 管理,那么只需要先关闭 ss-redir,然后再启动 v2ray 就行了,即 systemctl stop ss-redirsystemctl start v2ray,这相当于启动了一个代理框架,切换代理无需操作 ss-tproxy,直接切换进程即可。
FAQ
如果透明代理未正常工作,请先自行按照如下顺序进行一个简单的排查:
  1. 检查 ss-tproxy.conf 以及代理软件的配置是否正确,此文详细说明了许多配置细节,它们并不是废话,请务必仔细阅读此文。如果确认配置无误,那么请务必开启代理进程的详细日志(debug/verbose logging),以及 dnsmasq、chinadns-ng 的详细日志(ss-tproxy.conf),日志是调试的基础。
  2. 如果 ss-tproxy 在配置正确的情况下出现运行时报错,请在执行 ss-tproxy 相关命令时带上 -x 调试选项,以查看是哪条命令报的错。出现这种错误通常是脚本自身的问题,可直接通过 issue 报告此错误,但是你需要提供尽可能详细的信息,别一句话就应付了我,这等同于应付了你自己。
  3. 如果 ss-tproxy status 显示的状态不正常,那么通常都是配置问题,pxy/tcp 显示 stopped 表示代理进程的 TCP 端口未监听,pxy/udp 显示 stopped 表示代理进程的 UDP 端口未监听,dnsmasq 和 chinadns-ng 显示 stopped 时请查看它们各自的日志文件,可能是监听端口被占用了,等等。
  4. 在 ss-tproxy 主机上检查 DNS 是否工作正常,域名解析是访问互联网的第一步,这一步如果出问题,后面的就不用测试了。这里选择 dig 作为 DNS 调试工具,因此请先安装 dig 工具。在调试 DNS 之前,先开启几个终端,分别 tail -f 代理进程、dnsmasq、chinadns-ng 的日志文件;然后再开一个终端,执行 dig www.baidu.comdig www.google.com,观察 dig 以及前面几个终端的日志输出,发现不对的地方可以先尝试自行解决,如果解决不了,请通过 issue 报告它。对于 ss/ssr,最常见的错误就是代理的 udp relay 未开启,因此请先确保 udp relay 是否正常,udp relay 不正常会导致 dig www.google.com 解析失败;如果确认已开启 udp relay,那么你还要注意是否出现了 udp 丢包,某些 ISP 会对 udp 数据包进行恶意性丢弃,检查 udp 是否丢包通常需要检查本地以及 vps 上的代理进程的详细日志输出。
  5. 如果 ss-tproxy 主机的 DNS 工作正常,说明 UDP 透明代理应该是正常的,那么接下来应该检查 TCP 透明代理,最简单的方式就是使用 curl 工具进行检测,首先安装 curl 工具,然后执行 curl -4vsSkL https://www.baidu.comcurl -4vsSkL https://www.google.com,如果启用了 ss-tproxy 的 IPv6 透明代理支持,则还应该进行 IPv6 的网页浏览测试,即执行 curl -6vsSkL https://ipv6.baidu.comcurl -6vsSkL https://ipv6.google.com,观察它们的输出是否正常(即是否能够正常获取 HTML 源码),同时观察代理进程、dnsmasq、chinadns-ng 的日志输出。
  6. 如果 ss-tproxy 主机的 DNS 以及 curl 测试都没问题,那么就进行最后一步,在其它内网主机上分别测试 DNS 以及 TCP 透明代理(最简单的就是浏览器访问百度、谷歌),同时你也应该观察代理进程、dnsmasq、chinadns-ng 的日志输出。对于某些系统,可能会优先使用 IPv6 网络(特别是解析 DNS 时),因此如果你没有启用 ss-tproxy 的 IPv6 透明代理,那么请通过各种手段禁用 IPv6(或者进行其它一些妥当的处理),否则会影响透明代理的正常使用。
在报告问题时,请务必提供详细信息,而不是单纯一句话,xxx 不能工作,这对于问题的解决没有任何帮助。

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

先说 ss/ssr 透明代理吧,ss-redir 是 ss-libevssr-libev 中的一个工具,配合 iptables 可以在 Linux 上实现 ss、ssr 透明代理,ss-redir 的 TCP 透明代理是通过 REDIRECT 方式实现的,而 UDP 透明代理是通过 TPROXY 方式实现的。注意:ss-redir 只存在于ss-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 主机本身以及所有网关指向 ss-tproxy 主机的内网主机的 TCP、UDP 流量。

代理脚本

安装依赖

curl

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

# ArchLinux
pacman -S curl
Bash

perl5

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

# ArchLinux
pacman -S perl
Bash

ipset

# CentOS
yum -y install ipset

# ArchLinux
pacman -S ipset
Bash

TPROXY

TPROXY 是一个 Linux 内核模块,在 Linux 2.6.28 后进入官方内核。一般正常的发行版都没有裁剪 TPROXY 模块,TPROXY 模块缺失问题主要出现在无线路由固件上(某些精简型发行版也会去掉 TPROXY 模块,比如 Alpine)。使用以下方法可以检测当前内核是否包含 TPROXY 模块。
# 查找 TPROXY 模块
find /lib/modules/$(uname -r) -type f -name '*.ko*'|grep'xt_TPROXY'

# 正常情况下的输出
/lib/modules/4.16.8-1-ARCH/kernel/net/netfilter/xt_TPROXY.ko.xz

# 尝试手动加载模块
modprobe xt_TPROXY
Bash

iproute2

# CentOS
yum -y install iproute

# ArchLinux
pacman -S iproute2
Bash

dnsmasq

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

# ArchLinux
pacman -S dnsmasq
Bash

chinadns

这是原版 chinadns,适用于 ss-tproxy v3.0,ss-tproxy v4.0 请用 chinadns-ng。
# 获取
wgethttps://github.com/shadowsocks/ChinaDNS/releases/download/1.3.2/chinadns-1.3.2.tar.gz

# 解压
tar xf chinadns-1.3.2.tar.gz

# 安装
cd chinadns-1.3.2/
./configure
make&&makeinstall
Bash

chinadns-ng

chinadns-ng 是我利用业余时间用 C 语言编写的另一个 chinadns,修复若干问题,优化了性能。
# 获取源码
git clone https://github.com/zfl9/chinadns-ng

# 编译安装
cd chinadns-ng
make&&sudomakeinstall
Bash

v2ray

安装很简单,直接使用 v2ray 官方提供的 shell 脚本即可,默认配置开机自启
# 官方安装脚本
bash<(curl -4sSkL https://install.direct/go.sh)

# 安装的文件有
/etc/v2ray/config.json 配置文件
/usr/bin/v2ray/v2ray V2Ray 程序
/usr/bin/v2ray/v2ctl V2Ray 工具
/usr/bin/v2ray/geoip.dat IP 数据文件
/usr/bin/v2ray/geosite.dat 域名数据文件

# 是否安装成功
/usr/bin/v2ray/v2ray -help # 查看帮助
Bash

ss-libev

ArchLinux 建议使用 pacman -S shadowsocks-libev 安装,方便快捷,更新也及时。
CentOS/RHEL 或其它发行版,强烈建议 编译安装,仓库安装的可能会有问题(版本太老或者根本用不了)。
下面的代码完全摘自 ss-libev 官方 README.md,随着时间的推移可能有变化,最好照着最新 README.md 来做。
# Installation of basic build dependencies
## Debian / Ubuntu
sudoapt-getinstall --no-install-recommends gettext build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libmbedtls-dev libsodium-dev
## CentOS / Fedora / RHEL
sudo yum install gettext gcc autoconf libtool automake make asciidoc xmlto c-ares-devel libev-devel
## Arch
sudo pacman -S gettext gcc autoconf libtool automake make asciidoc xmlto c-ares libev

# Installation of Libsodium
export LIBSODIUM_VER=1.0.13
wgethttps://download.libsodium.org/libsodium/releases/old/libsodium-$LIBSODIUM_VER.tar.gz
tar xvf libsodium-$LIBSODIUM_VER.tar.gz
pushd libsodium-$LIBSODIUM_VER
./configure --prefix=/usr &&make
sudomakeinstall
popd
sudo ldconfig

# Installation of MbedTLS
export MBEDTLS_VER=2.6.0
wgethttps://tls.mbed.org/download/mbedtls-$MBEDTLS_VER-gpl.tgz
tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz
pushd mbedtls-$MBEDTLS_VER
make SHARED=1 CFLAGS=-fPIC
sudomake DESTDIR=/usr install
popd
sudo ldconfig

# Start building
git clone https://github.com/shadowsocks/shadowsocks-libev.git
cd shadowsocks-libev
git submodule update --init --recursive
./autogen.sh && ./configure &&make
sudomakeinstall
Bash

ssr-libev

shadowsocksr-backup/shadowsocksr-libev(貌似已停止更新,但目前使用没问题,只是一些新特性不支持,如有更好的源请告诉我~)
https://github.com/shadowsocksrr/shadowsocksr-libev/tree/Akkariiin/master,另一个 ssr-libev 源,Akkariiin-* 分支目前仍在更新
本文仍以 shadowsocksr-backup/shadowsocks-libev 为例,毕竟另一个源我没试过,但是这个源我自己用过大半年,没有任何问题,很稳定
# Installation of basic build dependencies
## Debian / Ubuntu
sudoapt-getinstall --no-install-recommends gettext build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libmbedtls-dev libsodium-dev
## CentOS / Fedora / RHEL
sudo yum install gettext gcc autoconf libtool automake make asciidoc xmlto c-ares-devel libev-devel
## Arch
sudo pacman -S gettext gcc autoconf libtool automake make asciidoc xmlto c-ares libev

# Installation of Libsodium
export LIBSODIUM_VER=1.0.13
wgethttps://download.libsodium.org/libsodium/releases/old/libsodium-$LIBSODIUM_VER.tar.gz
tar xvf libsodium-$LIBSODIUM_VER.tar.gz
pushd libsodium-$LIBSODIUM_VER
./configure --prefix=/usr &&make
sudomakeinstall
popd
sudo ldconfig

# Installation of MbedTLS
export MBEDTLS_VER=2.6.0
wgethttps://tls.mbed.org/download/mbedtls-$MBEDTLS_VER-gpl.tgz
tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz
pushd mbedtls-$MBEDTLS_VER
make SHARED=1 CFLAGS=-fPIC
sudomake DESTDIR=/usr install
popd
sudo ldconfig

# Start building
git clone https://github.com/shadowsocksr-backup/shadowsocksr-libev.git
cd shadowsocksr-libev
./configure --prefix=/usr/local/ssr-libev &&make&&makeinstall
cd /usr/local/ssr-libev/bin
mv ss-redir ssr-redir
mv ss-local ssr-local
ln -sf ssr-local ssr-tunnel
mv ssr-* /usr/local/bin/
rm -fr /usr/local/ssr-libev
Bash
如果编译失败,可以看下这个 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。
This system doesn't provide enough entropy to quickly generate high-quality random numbers
Installing the rng-utils/rng-tools or haveged packages may help.
On virtualized Linux environments, also consider using virtio-rng.
The service will not start until enough entropy has been collected.

该系统不能提供足够的熵来快速生成高质量的随机数,
安装 rng-utils/rng-tools 或 haveged 软件包可能会有所帮助。
在虚拟化的 Linux 环境中,请考虑使用 virtio-rng。
shadowsocks 服务只有在收集到足够的熵后才会启动。
None
这里以 haveged 为例,当然,你也可以选择安装 rng-utils/rng-tools,都是一样的:
# ArchLinux
pacman -S haveged
systemctl enable haveged
systemctl start haveged

# CentOS
yum -y install haveged
## CentOS 6.x
chkconfig haveged on
service haveged start
## CentOS 7.x
systemctl enable haveged
systemctl start haveged
Bash

代理测试

测试 IPv4
这里就简单的使用 curl 进行测试,如果有网页源码输出,基本就没什么问题:
# 访问 IPv4 的百度和谷歌
curl -4sSkL https://www.baidu.com
curl -4sSkL https://www.google.com
Bash
测试 IPv6
对于 ss-tproxy v4.0,如果启用了 ipv6 透明代理,可进行一些简单的 ipv6 测试:
# 访问 IPv6 的百度和谷歌
curl -6sSkL https://ipv6.baidu.com
curl -6sSkL https://ipv6.google.com
Bash
测试分流
也可以使用 curl 进行一个简单的分流模式验证,原理就是检查访问网站用的外部 IP:
# global 模式: 理论显示代理 IP
# gfwlist 模式: 理论显示本地 IP
# chnroute 模式: 理论显示本地 IP
curl -4sSkL https://myip.ipip.net
Bash

原理解析

这里的脚本解析仅针对 ss-tproxy v3.0,ss-tproxy v4.0 变化太多了,暂时没时间整理。

脚本浅析

开头部分主要是检查脚本相关的一些文件是否存在
# 默认的 ss-tproxy.conf 配置文件路径
ss_tproxy_config='/etc/ss-tproxy/ss-tproxy.conf'

# 设置 PATH,确保不会在运行过程中出现命令找不到的情况
PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

# 检查 ss-tproxy 脚本相关的文件是否存在,以及加载配置文件
[! -f "$ss_tproxy_config"]&&{echo"[ERR] No such file or directory: '$ss_tproxy_config'" 1>&2;exit 1;}||source"$ss_tproxy_config"
[! -f "$file_gfwlist_txt"]&&{echo"[ERR] No such file or directory: '$file_gfwlist_txt'" 1>&2;exit 1;}
[! -f "$file_gfwlist_ext"]&&{echo"[ERR] No such file or directory: '$file_gfwlist_ext'" 1>&2;exit 1;}
[! -f "$file_chnroute_txt"]&&{echo"[ERR] No such file or directory: '$file_chnroute_txt'" 1>&2;exit 1;}
[! -f "$file_chnroute_set"]&&{echo"[ERR] No such file or directory: '$file_chnroute_set'" 1>&2;exit 1;}
Bash
中间部分都是一些 function 函数,目前定义的函数有
function check_command {... }# 检查相关命令是否存在
function update_chnonly {... }# 为 chnonly 模式更新列表
function update_gfwlist {... }# 为 gfwlist 模式更新列表
function update_chnroute {... }# 为 chnroute 模式更新列表
function flush_dnscache {... }# 清空 dnsmasq 上的 DNS 缓存
function start_proxy {... }# 运行 proxy_runcmd 启动命令
function start_resolver {... }# 开启无污染的 DNS 解析及分流
function start_iptables {... }# 设置相关模式的 iptables 规则
function start_dnsproxy {... }# 更新 /etc/resolv.conf 解析文件
function start {... }# 脚本启动的主逻辑,调用上述函数
function stop {... }# 脚本关闭的主逻辑,清理相关规则
function status {... }# 脚本状态的主逻辑,ss/netstat 检测
function show_iptables {... }# 查看 mangle 表和 nat 表的相关规则
function flush_iptables {... }# 清空 raw、mangle、nat、filter 表
functionhelp{... }# 打印 ss-tproxy 脚本的使用&帮助信息
Bash
结尾部分就是处理命令行参数,然后调用上面写好的函数
case$1in
start) check_command; start; status;;
stop) check_command; stop; status;;
status) check_command; status;;
r*) check_command; stop; status;echo; start; status;;
show-iptables) show_iptables;;
flush-iptables) flush_iptables;;
flush-gfwlist) ipset -F gfwlist &>/dev/null;;
flush-dnscache) check_command; flush_dnscache;;
update-chnonly) check_command; update_chnonly;;
update-gfwlist) check_command; update_gfwlist;;
update-chnroute) check_command; update_chnroute;;
c*) check_command;;
h*)help;;
*)help;exit 1;;
esac
Bash

dns 解析模块

开头部分
遍历 proxy_server 数组,如果是域名,则解析为对应 IP,稍后会加到 dnsmasq 的静态解析列表中(相当于 hosts 文件),之所以要这么做,是因为 v2ray 的一个特性造成的,如果给 v2ray 配置的代理服务器为域名,那么 v2ray 每次连接到代理服务器之前,都会去解析这个域名(而不是像 ss-libev、ssr-libev 那样,启动的时候就先解析出对应的服务器 IP),如果没有把这个域名加入静态解析列表,那么此刻代理就会陷入死循环,因为 v2ray 自己发出去的 dns 解析请求被导向代理隧道了(global 模式、chnroute 模式),而代理本身就是要先解析出这个域名对应的 IP 才能连接到我们的代理服务器;而如果我们在启动代理之前就先解析出对应的 IP,并加入 dnsmasq 的静态解析列表,就不会有问题了,因为当 v2ray 发出的 dns 解析请求到达 dnsmasq 时,dnsmasq 会从静态解析列表中返回这个 IP,然后就能正常连接 v2ray 代理服务器了。
for server in"${proxy_server[@]}";do
if[$(grep -Ec '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'<<<"$server") -eq 0 ];then
server_addrs+=("/$server/$(ping -nq -c1 -t1 -W1 $server |head -n1 |awk -F'[()]''{print $2}')")
fi
done
Bash
global 模式
比较简单,因为不需要分流,全部解析都交给远程 dns 去解析(8.8.8.8,走代理),之所以加个 dnsmasq,而不是直接用 iptables 代理到 8.8.8.8,是为了利用 dnsmasq 的缓存功能来加速 DNS 解析,不然每次解析都要请求远程服务器,多慢啊,有了 DNS 缓存,我第二次解析同一个域名就直接可以返回给请求客户端了,因此,所有 mode 我都加入了 dnsmasq 来作缓存。
dnsmasq -C <(cat <<EOF
$(["$dnsmasq_log_enable"='true']&&echo'log-queries')
log-facility = $dnsmasq_log_file
log-async = 20
domain-needed
cache-size = $dnsmasq_cache_size
$([$(dnsmasq --help |grep -c min-cache-ttl) -ne 0 ] && echo "min-cache-ttl = $dnsmasq_cache_time")
no-negcache
no-resolv
port = 60053
server = ${dns_remote/:/#}
$(for server_addr in"${server_addrs[@]}";doecho"address = $server_addr";done)
EOF

)
Bash
gfwlist 模式
和 global 模式的配置差不多,只不过默认使用国内 dns 进行解析(114.114.114.114,走直连),然后对位于 gfwlist.txt、gfwlist.ext 中的域名使用远程 dns 进行解析(8.8.8.8,走代理),也就是所谓的黑名单模式,当然这里还使用了 dnsmasq 的 ipset 功能,黑名单中的这些域名解析出的 IP 地址会自动加入到我们指定的 ipset 列表中,这样我们在 iptables 规则中就可以动态的让这些 IP 走代理,从而完成分流(域名到 IP 的映射)。
dnsmasq -C <(cat <<EOF
$(["$dnsmasq_log_enable"='true']&&echo'log-queries')
log-facility = $dnsmasq_log_file
log-async = 20
domain-needed
cache-size = $dnsmasq_cache_size
$([$(dnsmasq --help |grep -c min-cache-ttl) -ne 0 ] && echo "min-cache-ttl = $dnsmasq_cache_time")
no-negcache
no-resolv
port = 60053
server = $dns_direct
$(for server_addr in"${server_addrs[@]}";doecho"address = $server_addr";done)
$(perl -pe "s@^.*+\$@server=/$&/${dns_remote/:/#}\nipset=/$&/gfwlist@" $file_gfwlist_txt <(
perl -ne 'print unless m@^\s|\s\n$|^#|^\d++\.\d++\.\d++\.\d++(?:/\d++)
?$@'$file_gfwlist_ext
))
EOF

)
Bash
chnroute 模式
这里的 dnsmasq 就是起到一个缓存的作用,因为 chinadns 不支持 dns 缓存,为了提高解析性能(抗住大并发的 dns 解析请求),所以很有必要加上 dnsmasq;这里解释一下第一段代码的作用,为什么要将直连 dns 加入 chnroute 列表,要理解这个,首先要理解 chinadns 的分流原理(个人理解,有错误还请指出);chinadns 要运行,首先要给它配置两组 dns 服务器,一组是 国内 dns,一组是 可信 dns(国外 dns),所以至少需要给它配置两个上游 dns,就假设为 114.114.114.114(国内 dns)、8.8.8.8(可信 dns,走代理),然后还要给它指定一个 chnroute 列表(大陆地址段);当 chinadns 收到一个解析请求时,它会同时向这两组 dns 发出请求,然后:
  • 如果国内 dns 先返回(正常情况,因为直连肯定比代理快),那么 chinadns 会检查国内 dns 返回的 ip 是否为大陆地址(chnroute 列表),如果是,则 chinadns 会直接将这个解析出来的 IP 返回给请求客户端,然后完成解析(忽略可信 dns 的结果);如果国内 dns 返回的 ip 不是大陆地址(chnroute 列表),那么 chinadns 会过滤掉国内 dns 的解析结果,然后等待可信 dns 的解析结果并将其返回给请求客户端,完成解析。
  • 如果可信 dns 先返回(非正常情况,比如给可信 dns 加了本地缓存,导致它最先返回),那么 chinadns 会直接返回可信 dns 的解析结果,而不会考虑国内 dns 解析结果,如果是这样的话,那么其实 chinadns 的分流就完全出问题了,根本就没有分流,全都是返回远程 dns 解析出来的结果,所以一定不能给 chinadns 的可信 dns 设置 dns 缓存(如给它套一层 dnsmasq/pdnsd/dnsforwarder)。
那这和第一段代码有什么关联?当然有关联,你可曾想过,chinadns 如何知道你传递给它的这些 dns 哪个是国内 dns,哪个是国外 dns?那肯定得通过 chnroute.txt 列表来判断啊,如果这个 dns 是大陆地址,那么它就是 国内 dns,否则它就是 可信 dns,而为了保险,我干脆就将 dns_direct 加入这个列表,这样就可以避免 chinadns 将我们的国内 dns 认为是国外 dns 了(我印象中出现过这种情况,而且 issues 里面也有一个人遇到过这个问题)。
# 将直连 dns 加入列表
temp_chnroute_txt=$(mktemp)
cat$file_chnroute_txt>$temp_chnroute_txt
echo"$dns_direct/32">>$temp_chnroute_txt
# 将内网地址段加入列表
for intranet in"${ipts_intranet[@]}";doecho"$intranet">>$temp_chnroute_txt;done

# 运行 chinadns(分流)
chinadns_params="-b 0.0.0.0 -p 65353 -s $dns_direct,$dns_remote -c $temp_chnroute_txt"
["$chinadns_mutation"='true']&& chinadns_params+=' -m'
["$chinadns_verbose"='true']&& chinadns_params+=' -v'
(chinadns $chinadns_params</dev/null &>>$chinadns_logfile&)

# 运行 dnsmasq(缓存)
dnsmasq -C <(cat <<EOF
$(["$dnsmasq_log_enable"='true']&&echo'log-queries')
log-facility = $dnsmasq_log_file
log-async = 20
domain-needed
cache-size = $dnsmasq_cache_size
$([$(dnsmasq --help |grep -c min-cache-ttl) -ne 0 ] && echo "min-cache-ttl = $dnsmasq_cache_time")
no-negcache
no-resolv
port = 60053
server = 127.0.0.1#65353
$(for server_addr in"${server_addrs[@]}";doecho"address = $server_addr";done)
EOF

)
Bash

iptables 规则

start_iptables() 这个函数基本上是最复杂的函数了,但只要理清楚了这里面的关系和执行逻辑,就很容易理解。
设置相关内核参数
# 启用软路由功能
sysctl -w net.ipv4.ip_forward=1 &>/dev/null

# 禁止发送 icmp 重定向
fordirin$(ls /proc/sys/net/ipv4/conf);do
sysctl -w net.ipv4.conf.$dir.send_redirects=0 &>/dev/null
done
Bash
检查 ipts_non_snat 选项的函数
function check_snat_rule {
if["$ipts_non_snat"!='true'];then
if! iptables -t nat -C POSTROUTING -s $intranet! -d $intranet -j MASQUERADE &>/dev/null;then
iptables -t nat -A POSTROUTING -s $intranet! -d $intranet -j MASQUERADE
fi
fi
}
Bash
遍历 ipts_intranet 内网地址数组,找出非标网段
function dec2bin {
for((n = $1; n >0; n >>=1));do bit="$((n &1))$bit";done
printf" d\n""$bit"# 这有个显示问题,其实是 % 08d
}

function net2bin {
net=$(awk -F/ '{print $1}'<<<$1)
len=$(awk -F/ '{print $2}'<<<$1)
IFS='.'read -ra bytes <<<"$net"
for byte in"${bytes[@]}";do result+="$(dec2bin $byte)";done
echo"${result:0:len}"
}

for cidr in"${ipts_intranet[@]}";do
curnet=$(net2bin $cidr)
for stdnet in 00001010 101011000001 1010100111111110 1100000010101000;do
[["$curnet"=="$stdnet"* ]]&&continue 2
done
ipts_intranet_nonstd+=($cidr)
done
Bash
设置外层 iptables 自定义规则链、设置 ip rule 策略路由
iptables -t mangle -N SSTP_OUT
iptables -t mangle -N SSTP_PRE
iptables -t nat -N SSTP_OUT
iptables -t nat -N SSTP_PRE

iptables -t mangle -A OUTPUT -j SSTP_OUT
iptables -t mangle -A PREROUTING -j SSTP_PRE
iptables -t nat -A OUTPUT -j SSTP_OUT
iptables -t nat -A PREROUTING -j SSTP_PRE

# 之所以要设置 ip rule 规则是因为 TPROXY 代理方式需要
ip route add local 0/0 dev lo table $ipts_rt_tab
ip rule add fwmark $ipts_rt_mark table $ipts_rt_tab
Bash
纯 tproxy 方式 - gfwlist 分流
# 将黑名单中的 ip 和网段加入 ipset
ipset -N gfwlist hash:net &>/dev/null
perl -ne 'print if m@^\d++\.\d++\.\d++\.\d++(?:/\d++)?$@'$file_gfwlist_ext|xargs -n1 ipset -A gfwlist &>/dev/null

# 打上 iptables 标记,mark 了的会走代理
iptables -t mangle -N SETMARK
iptables -t mangle -A SETMARK -p udp -d ${dns_remote%:*} -j MARK --set-mark $ipts_rt_mark
iptables -t mangle -A SETMARK -m set --match-set gfwlist dst -j MARK --set-mark $ipts_rt_mark

# 本机发出去的 TCP 和 UDP 走一下 SETMARK 链
iptables -t mangle -A SSTP_OUT -p tcp -j SETMARK
iptables -t mangle -A SSTP_OUT -p udp -j SETMARK

# 将发往 127.0.0.1:53/udp 的包重定向给 dnsmasq
iptables -t nat -A SSTP_OUT -p udp -d 127.0.0.1 --dport 53 -j REDIRECT --to-ports 60053

# 遍历内网地址段,处理内网主机发过来的 TCP 和 UDP
for intranet in"${ipts_intranet[@]}";do
# 将内网主机发出的 dns 请求包重定向给 dnsmasq
iptables -t mangle -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j ACCEPT
iptables -t nat -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j REDIRECT --to-ports 60053

# 让内网主机发出的 TCP 和 UDP 走一下 SETMARK 链
iptables -t mangle -A SSTP_PRE -p tcp -s $intranet -m mark ! --mark $ipts_rt_mark -j SETMARK
iptables -t mangle -A SSTP_PRE -p udp -s $intranet -m mark ! --mark $ipts_rt_mark -j SETMARK

# 检查是否需要设置 SNAT/MASQUERADE 规则
check_snat_rule
done

# 将所有打了标记的 TCP 和 UDP 包透明地转发到代理的监听端口
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_tcport
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p udp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_udport
Bash
纯 tproxy 方式 - global/chnroute 分流
# 打上 iptables 标记
iptables -t mangle -N SETMARK
iptables -t mangle -A SETMARK -d 0/8 -j RETURN
iptables -t mangle -A SETMARK -d 10/8 -j RETURN
iptables -t mangle -A SETMARK -d 127/8 -j RETURN
iptables -t mangle -A SETMARK -d 169.254/16 -j RETURN
iptables -t mangle -A SETMARK -d 172.16/12 -j RETURN
iptables -t mangle -A SETMARK -d 192.168/16 -j RETURN
iptables -t mangle -A SETMARK -d 224/4 -j RETURN
iptables -t mangle -A SETMARK -d 240/4 -j RETURN
for cidr in"${ipts_intranet_nonstd[@]}";do
iptables -t mangle -A SETMARK -d $cidr -j RETURN
done
if!["$proxy_dports"];then
for server in"${proxy_server[@]}";do
iptables -t mangle -A SETMARK -d $server -j RETURN
done
else
for server in"${proxy_server[@]}";do
iptables -t mangle -A SETMARK -d $server -p tcp -m multiport --dports $proxy_dports -j RETURN
iptables -t mangle -A SETMARK -d $server -p udp -m multiport --dports $proxy_dports -j RETURN
done
fi
if["$mode"= chnroute ];then
ipset -X chnroute &>/dev/null
ipset -R <$file_chnroute_set
iptables -t mangle -A SETMARK -m set --match-set chnroute dst -j RETURN
fi
iptables -t mangle -A SETMARK -j MARK --set-mark $ipts_rt_mark

# 本机 TCP 和 UDP 走标记链
iptables -t mangle -A SSTP_OUT -p tcp -j SETMARK
iptables -t mangle -A SSTP_OUT -p udp -j SETMARK

# 本机 DNS 重定向给 dnsmasq
iptables -t nat -A SSTP_OUT -p udp -d 127.0.0.1 --dport 53 -j REDIRECT --to-ports 60053

# 遍历内网地址段,处理 TCP 和 UDP
for intranet in"${ipts_intranet[@]}";do
# 将内网主机发出的 dns 请求重定向给 dnsmasq
iptables -t mangle -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j ACCEPT
iptables -t nat -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j REDIRECT --to-ports 60053

# 让内网主机发出的 TCP 和 UDP 走一下标记链
iptables -t mangle -A SSTP_PRE -p tcp -s $intranet -m mark ! --mark $ipts_rt_mark -j SETMARK
iptables -t mangle -A SSTP_PRE -p udp -s $intranet -m mark ! --mark $ipts_rt_mark -j SETMARK

# 检查是否需要设置 SNAT/MASQUERADE 规则
check_snat_rule
done

# 将所有打了标记的 TCP 和 UDP 包透明地转发到代理的监听端口
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_tcport
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p udp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_udport
Bash
传统模式 - gfwlist 分流
# 导入黑名单 ip 和网段
ipset -N gfwlist hash:net &>/dev/null
perl -ne 'print if m@^\d++\.\d++\.\d++\.\d++(?:/\d++)?$@'$file_gfwlist_ext|xargs -n1 ipset -A gfwlist &>/dev/null

# TCP 使用重定向方式进行代理
iptables -t nat -N TCPCHAIN
iptables -t nat -A TCPCHAIN -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-ports $proxy_tcport

# UDP 使用 TPROXY 方式进行代理
iptables -t mangle -N UDPCHAIN
iptables -t mangle -A UDPCHAIN -d ${dns_remote%:*} -j MARK --set-mark $ipts_rt_mark
iptables -t mangle -A UDPCHAIN -m set --match-set gfwlist dst -j MARK --set-mark $ipts_rt_mark

# 让本机 TCP 和 UDP 走一下代理链
iptables -t nat -A SSTP_OUT -p tcp -j TCPCHAIN
iptables -t mangle -A SSTP_OUT -p udp -j UDPCHAIN

# 将本机 dns 请求重定向到 dnsmasq
iptables -t nat -A SSTP_OUT -p udp -d 127.0.0.1 --dport 53 -j REDIRECT --to-ports 60053

# 遍历内网地址段,处理 TCP 和 UDP
for intranet in"${ipts_intranet[@]}";do
# 处理 dns,重定向到 dnsmasq
iptables -t mangle -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j ACCEPT
iptables -t nat -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j REDIRECT --to-ports 60053

# 处理 TCP、UDP,走代理链
iptables -t nat -A SSTP_PRE -p tcp -s $intranet -j TCPCHAIN
iptables -t mangle -A SSTP_PRE -p udp -s $intranet -m mark ! --mark $ipts_rt_mark -j UDPCHAIN

# 检查 SNAT 规则
check_snat_rule
done

# 将打了标记的 UDP 包透明地转发到代理进程的 UDP 监听端口
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p udp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_udport
Bash
传统模式 - global/chnroute 分流
# TCP 使用重定向方式进行代理
iptables -t nat -N TCPCHAIN
iptables -t nat -A TCPCHAIN -d 0/8 -j RETURN
iptables -t nat -A TCPCHAIN -d 10/8 -j RETURN
iptables -t nat -A TCPCHAIN -d 127/8 -j RETURN
iptables -t nat -A TCPCHAIN -d 169.254/16 -j RETURN
iptables -t nat -A TCPCHAIN -d 172.16/12 -j RETURN
iptables -t nat -A TCPCHAIN -d 192.168/16 -j RETURN
iptables -t nat -A TCPCHAIN -d 224/4 -j RETURN
iptables -t nat -A TCPCHAIN -d 240/4 -j RETURN
for cidr in"${ipts_intranet_nonstd[@]}";do
iptables -t nat -A TCPCHAIN -d $cidr -j RETURN
done
for server in"${proxy_server[@]}";do
iptables -t nat -A TCPCHAIN -d $server$(["$proxy_dports"]&&echo"-p tcp -m multiport --dports $proxy_dports") -j RETURN
done
if["$mode"= chnroute ];then
ipset -X chnroute &>/dev/null
ipset -R <$file_chnroute_set
iptables -t nat -A TCPCHAIN -m set --match-set chnroute dst -j RETURN
fi
iptables -t nat -A TCPCHAIN -p tcp -j REDIRECT --to-ports $proxy_tcport

# UDP 使用 TPROXY 方式进行代理
iptables -t mangle -N UDPCHAIN
iptables -t mangle -A UDPCHAIN -d 0/8 -j RETURN
iptables -t mangle -A UDPCHAIN -d 10/8 -j RETURN
iptables -t mangle -A UDPCHAIN -d 127/8 -j RETURN
iptables -t mangle -A UDPCHAIN -d 169.254/16 -j RETURN
iptables -t mangle -A UDPCHAIN -d 172.16/12 -j RETURN
iptables -t mangle -A UDPCHAIN -d 192.168/16 -j RETURN
iptables -t mangle -A UDPCHAIN -d 224/4 -j RETURN
iptables -t mangle -A UDPCHAIN -d 240/4 -j RETURN
for cidr in"${ipts_intranet_nonstd[@]}";do
iptables -t mangle -A UDPCHAIN -d $cidr -j RETURN
done
for server in"${proxy_server[@]}";do
iptables -t mangle -A UDPCHAIN -d $server$(["$proxy_dports"]&&echo"-p udp -m multiport --dports $proxy_dports") -j RETURN
done
if["$mode"= chnroute ];then
iptables -t mangle -A UDPCHAIN -m set --match-set chnroute dst -j RETURN
fi
iptables -t mangle -A UDPCHAIN -j MARK --set-mark $ipts_rt_mark

# 让本机 TCP 和 UDP 走一下代理链
iptables -t nat -A SSTP_OUT -p tcp -j TCPCHAIN
iptables -t mangle -A SSTP_OUT -p udp -j UDPCHAIN

# 将本机 dns 请求重定向到 dnsmasq
iptables -t nat -A SSTP_OUT -p udp -d 127.0.0.1 --dport 53 -j REDIRECT --to-ports 60053

# 遍历内网地址段,处理 TCP 和 UDP
for intranet in"${ipts_intranet[@]}";do
# 处理 dns,重定向到 dnsmasq
iptables -t mangle -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j ACCEPT
iptables -t nat -A SSTP_PRE -p udp -s $intranet --dport 53 -m mark ! --mark $ipts_rt_mark -j REDIRECT --to-ports 60053

# 处理 TCP、UDP,走代理链
iptables -t nat -A SSTP_PRE -p tcp -s $intranet -j TCPCHAIN
iptables -t mangle -A SSTP_PRE -p udp -s $intranet -m mark ! --mark $ipts_rt_mark -j UDPCHAIN

# 检查 SNAT 规则
check_snat_rule
done

# 将打了标记的 UDP 包透明地转发到代理进程的 UDP 监听端口
iptables -t mangle -A SSTP_PRE -m mark --mark $ipts_rt_mark -p udp -j TPROXY --on-ip 127.0.0.1 --on-port $proxy_udport
Bash

常见问题

这里有些问答可能仅适用于 ss-tproxy v3.0,请仔细甄别,切勿盲目照搬照抄。
建议在 github 上报告相关问题,disqus 评论在国内无法访问,而且也不好查看。
做 代理网关/单臂路由/旁路网关 时,ss-tproxy 主机代理正常,其它主机代理异常
首先排查是不是 ipts_non_snat 选项的问题,默认我设置的是 false,双重否定其实就是肯定,也就是说设置为 false 的话就表示会设置 SNAT 规则,通常情况下,只有你真的需要 SNAT 规则时你才需要将其设置为 false,比如你在网络出口位置使用 ss-tproxy(一头连接内网,一头连接公网),那么就需要设置 SNAT 规则,但其实这种情况下你的系统上早就已经设置好了 SNAT 规则,不然你是怎么上网的,对吧。因此,无论什么情况,都先尝试将 ipts_non_snat 选项设为 true,除非你在设置为 true 的情况下代理有问题,那么你才需要将其设置为 false。另外,这个选项如果你设置过 false,并启动了 ss-tproxy,那么除非你手动清除这个 SNAT 规则或者重启系统(nat 表,POSTROUTING 链),否则系统中还是会存在这个 SNAT 规则的,保险起见,在切换 ipts_non_snat 选项后,先执行一遍 ss-tproxy flush-iptables 命令(ss-tproxy v4.0 无此问题)。
某些系统自带一些 iptables 规则,可能会影响 ss-tproxy 的正常使用
如果你对 iptables 规则不是很了解,请在启动 ss-tproxy 之前将已有的 iptables 规则清空,通常情况下执行命令 ss-tproxy flush-iptables 即可清空,但最好自己再检查一下,因为据反馈有些系统的规则还是无法彻底清除,那么怎么检查呢?执行 flush-iptables 之后,手动执行下面几个命令,查看 raw、mangle、nat、filter 表的规则,如果都是空的那说明就是彻底清空了:
iptables -nL -t raw
iptables -nL -t mangle
iptables -nL -t nat
iptables -nL -t filter
Bash
比如 raw 表,默认是这样的,其它的表也类似,只不过预定义规则链不一样而已:
$ iptables -nL -t raw
Chain PREROUTING (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Bash
那如果执行了 flush-iptables 后还是有残留规则,该怎么办呢?请自行谷歌。如果系统每次开机都会自动设置一些规则,而且你还不知道如何关闭它,那么也可以在 ss-tproxy.conf 的 pre_start 钩子函数中加入 ss-tproxy flush-iptables 清理命令,如下,这样每次启动 ss-tproxy 都会自动清空规则:
function pre_start {
ss-tproxy flush-iptables
}
Bash
ss-tproxy status 显示不准确(已运行却显示 stopped)
首先检查 ss-tproxy.conf 中的 opts_ss_netstat 选项值是否设置正确,默认是 auto 自选选择模式,即如果有 ss 就优先使用 ss 命令,如果没有才会去使用 netstat 命令;如果自动选择模式对你不适用,那么可以改为 ss 或 netstat 来明确告诉 ss-tproxy 你要使用哪个端口检测命令(有些系统没有 ss,而有些系统却只有 ss);如果确定不是这个选项的问题,那么我估计你遇到了这个问题:执行 ss-tproxy start|restart 后,发现 pxy/tcp 和 pxy/udp 的状态是 stopped 的,然后再次执行 ss-tproxy status 查看状态,却又发现是 running 的,且代理进程也正常启动了,代理也是正常的;这个其实不是 ss-tproxy 的问题,应该是 ss、netstat 的检测延迟问题,因为第一次状态检测(start|restart)是在 proxy_runcmd 运行之后立即执行的,因为某些原因(具体什么原因我也没详细了解),导致 ss/netstat 没检测到对应的监听端口(或者还有一种情况,就是代理进程此时可能还没监听端口,还在处理其它事,如还在处理命令行选项等等,反正都有可能),然后你再次执行 status 命令查看状态时,因为存在一个时间间隔,所以基本上就能正常检测到了。
ss-tproxy 现在是否支持 ipv6 的透明代理(暂时不支持
ipv6 的支持已经在计划之中,但可能没有这么快,毕竟没有那么多业余时间来写,挺忙的。
ipv6 已经在 ss-tproxy v4.0 中实现,欢迎大家进行测试,我目前并没有 ipv6 环境,测试是在某位热心网友协助下进行的,在此表示感谢。
特别注意,ss-tproxy v3 要求代理服务器支持 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 流量的恶意干扰,因为根本没有走 udp,而是走的 tcp。如果你因为各种原因无法使用 udp relay,请考虑使用 v2ray,而且现在网络环境越来越差,ss/ssr 貌似有些顶不住了。
如何只对指定的 host/addr 进行代理,其它的通通走直连
其实非常简单,使用 gfwlist 模式即可;gfwlist 模式会读取 gfwlist.txt、gfwlist.ext 两个黑名单文件,如果你只想代理某些域名、IP、网段,其它的都不想代理,可以直接将 gfwlist.txt 文件清空(执行命令 true >/etc/ss-tproxy/gfwlist.txt),然后编辑 gfwlist.ext 文件,填写要代理的域名、IP、网段即可(文件中有格式说明)。注意,在这种模式下就不要执行 update-chnonlyupdate-gfwlist 命令了,因为它们会操作 gfwlist.txt 文件。
如何将 socks5 代理转换为 ss-tproxy v3 可用的透明代理
如果你因为各种原因无法编译 ss-libev、ssr-libev,但又想使用 ss-tproxy 的透明代理功能,也可以使用 redsocks2 来将任意支持 udp 的 socks5 代理转换为透明代理,这样即使你没有 ss-libev、ssr-libev,也可以使用 ss-tproxy 的透明代理功能(即使用 python 版 ss/ssr + redsocks2 来做透明代理)。当然因为我的系统只安装了 libev 版本,没有安装 python 版本,所以这里依旧使用 ssr-local 作为例子讲解(如果使用 python 版的 ss/ssr,那么你只需要将对应的 ssr-local 替换为 sslocal 命令,但记得开启 udp relay),怎么编译 redsocks2(注意是 redsocks2,不是原版 redsocks)这里就不多说了,官方 readme 有详细说明;我们只需要关注 redsocks2 的配置文件(假设文件路径为 /etc/redsocks2.conf):
base {
daemon= on;
log_info= on;
reuseport= on;
redirector= iptables;
log="file:/var/log/redsocks2.log";
}

redsocks {
local_ip= 0.0.0.0;
local_port= 60080;
ip= 127.0.0.1;
port= 61080;
type= socks5;
}

redudp {
local_ip= 0.0.0.0;
local_port= 60080;
ip= 127.0.0.1;
port= 61080;
type= socks5;
}
Ini
base 是 redsocks2 的配置,redsocks 是 tcp 透明代理的配置(REDIRECT),redudp 是 udp 透明代理的配置(TPROXY),ip 和 port 是 socks5 服务器的监听地址,在这里就是 ssr-local 的监听地址,而 local_ip、local_port 则是 redsocks2 进程的监听地址,注意是 0.0.0.0:60080/tcp+udp,端口需要和 ss-tproxy.conf 里面的 proxy_tcport、proxy_udport 相同,监听地址也必须为 0.0.0.0。然后就是配置 ss-tproxy.conf,假设 vps 地址为 1.2.3.4:
proxy_tproxy='false'
proxy_server=(1.2.3.4)
proxy_tcport='60080'
proxy_udport='60080'
proxy_runcmd='start_ssrlocal_redsocks2'
proxy_kilcmd='kill -9 $(pidof ssr-local)$(pidof redsocks2)'
Bash
然后在 ss-tproxy.conf 的任意位置定义我们的 start_ssrlocal_redsocks2 函数,比如在文件末尾添加:
function start_ssrlocal_redsocks2 {
(ssr-local -s1.2.3.4 -p8080 -mnone -kpassword -Oorigin -oplain -b0.0.0.0 -l61080 -u </dev/null &>/dev/null &)
/usr/local/bin/redsocks2 -c /etc/redsocks2.conf
}
Bash
iptables: No chain/target/match by that name
如果是 iptables -j TPROXY 这条命令报的错(使用 bash -x /usr/local/bin/ss-tproxy start 查看调试信息),那就是没有 TPROXY 模块。
Syntax error: redirection unexpected
如果运行脚本时报了这个错误,你应该检查一下你的 bash 是不是正常版本,或者使用 ls -l /bin/bash 看下这个文件是否软连接到了其它 shell。
ss-tproxy.conf 中的函数不可重复定义
特别注意,因为 ss-tproxy 和 ss-tproxy.conf 都是一个 bash 脚本,所以这两个文件的内容也必须符合 bash 的语法规则,比如你不能在里面重复定义一个函数,虽然这不会报错,但是只有最后一个函数才会生效,这可能会坑死你,如果你定义了多个同名的 bash 函数,请将它们合并为一个!
BT/PT 问题(global/chnroute 模式)
如果你经常使用 BT/PT 下载,请务必使用 gfwlist 模式,如果使用 global/chnroute 模式,可能会消耗大量的 VPS 流量,甚至可能导致 VPS 被封(因为很多主机商都不允许 BT/PT 下载)。因为使用 iptables 来识别 BT/PT 流量的效率太低(基本都是使用 string 模块来匹配,我个人是无法接受的),所以最好的办法还是使用 gfwlist 模式,因为 gfwlist 模式下只有被墙了的网站才会走代理,其它的都是走直连(绝大多数 BT/PT 流量)。
对于 ss-tproxy v4.0,你可以指定要代理的目的端口,可以利用此选项来避免 BT/PT 流量走代理的问题,具体请看 4.0 的 README。
默认的 8.8.8.8:53 DNS 有问题
请关闭 chinadns 的压缩指针,即将 ss-tproxy.conf 中的 chinadns_mutation 改为 false(新版已默认关闭),启用压缩指针时,有时候使用 1.1.1.1、8.8.8.8、8.8.4.4 这些国外 DNS 会有问题,无法正常解析 DNS,导致的现象就是国内网站可以上,但是国外网站不能上。ss-tproxy v4.0 无此问题。
start 时部分组件 stopped
如果是 dnsmasq 或 chinadns 启动失败,请先检查 /var/log 下面的日志,看看是不是监听地址被占用了(按道理来说,v3 最新版本已经将它们两个的监听端口调的很高了,基本没有与之冲突的监听地址);如果是 pxy/tcp 或 pxy/udp 启动失败,请检查 ss-tproxy.conf 里面的 proxy_tcport 和 proxy_udport 端口是否与 proxy_runcmd 启动的进程的监听端口一致,因为默认情况下,ss-redir 或 ssr-redir 的监听端口是 1080,而 ss-tproxy 设置的是 60080,当然这个端口是可以随便改的,但是我觉得还是使用高位端口好一些,省得那么多端口冲突。
切换模式后不能正常代理了
从其它模式切换到 gfwlist 模式时可能出现这个问题,原因还是因为内网主机的 DNS 缓存。在访问被墙网站时,比如 www.google.com,客户机首先会进行 DNS 解析,由于存在 DNS 缓存,这个 DNS 解析请求并不会被 ss-tproxy 主机的 dnsmasq 处理(因为根本没从客户机发出来),所以对应 IP 不会添加到 ipset-gfwlist 列表中,导致客户机发给该 IP 的数据包不会被 ss-tproxy 处理,也就是走直连出去了,GFW 当然不会让它通过了,也就出现了连接被重置等问题。解决方法也很简单,对于 Windows,请先关闭浏览器,然后打开 cmd.exe,执行 ipconfig /flushdns 来清空 DNS 缓存,然后重新打开浏览器,应该正常了;对于 Android,可以先打开飞行模式,然后再关闭飞行模式,或许可以清空 DNS 缓存。
有时会无法访问代理服务器
如果你在 ss-tproxy 中使用的是自己的 VPS 的代理服务,那么在除 ss-tproxy 主机外的其他主机上会可能会出现无法访问这台 VPS 的情况(比如 SSH 连不上,但是 ping 没问题),具体表现为连接超时。起初怀疑是 ss-tproxy 主机的 iptables 规则设置不正确,然而使用 TRACE 追踪后却什么都没发现,一切正常;在 VPS 上使用 tcpdump 抓包后,发现一个很奇怪的问题:VPS 在收到来自客户端的 SYN 请求后并没有进行 SYN+ACK 回复,客户端在尝试了几次后就会显示连接超时。于是怀疑是不是 VPS 的问题,谷歌之后才知道,原来是因为两个内核参数设置不正确导致的,这两个内核参数是:net.ipv4.tcp_tw_reusenet.ipv4.tcp_tw_recycle,将它们都设为 0(也就是禁用)即可解决此问题。其实这两个内核参数默认都是为 0 的,也就是说,只要你没动过 VPS 的内核参数,那么基本不会出现这种诡异的问题。
关于网关的 DHCP 配置细节
这里说的 DHCP 配置仅针对“代理网关”模式,其实如何配置 DHCP 完全取决于你自己的需求,第一种:将路由器 DHCP 分配的 Gateway 和 DNS 改为 ss-tproxy 主机的地址,然后给 ss-tproxy 主机配置静态 IP,注意不能使用 DHCP 来获取,因为获取到的 Gateway 是指向自己的,显然有问题,这种方式下,所有内网主机默认通过 ss-tproxy 代理上网,如果某些主机不想走代理,可以手动将这些主机的 Gateway 和 DNS 改为原来的,就可以恢复直连了,不会走代理。第二种:不改变任何 DHCP 配置,默认情况下除 ss-tproxy 主机本身外,其它主机都是走直连的,如果你想让某些主机走代理上网,可以手动将这些主机的 Gateway 和 DNS 改为 ss-tproxy 主机的 IP,这样就可以走代理上网了。当然如果你的路由器支持为不同的主机设置不同的 Gateway 和 DNS,那么也可以不修改任何内网主机的配置,直接在路由上配置对应的 DHCP 规则就行了。
ss-tproxy 支持什么发行版
一般都支持,没有限制,因为没有使用与特定发行版相关的命令和特性(我自己用的是 ArchLinux),当然我说的是普通 x86、arm 发行版,如果是路由器的那种系统,应该会有点问题,但是移植起来应该不难。我测试过的系统有:ArchLinux、RHEL、CentOS、Debian、Alpine;经过几个网友测试,OpenWrt 貌似也可以,当然需要自己改一些东西,比如 OpenWrt 自带的 bash 是有问题的,阉割版,运行起来会报错,换为标准版 bash 就没问题。
ss-tproxy 只能运行在网关上吗
显然不是,你可以在一台普通的 linux 主机(甚至是桥接模式下的虚拟机)上运行,并且这种方式也是能够透明代理其它主机的 TCP 和 UDP 的哦。
ss-tproxy 可以运行在副路由上吗
可以。假设你有两个路由器,一主一副,主路由通过 PPPOE 拨号上网,其它设备连接到主路由可以上外网(无科学上网),副路由的 WAN 口连接到主路由的 LAN 口,副路由的 WAN 网卡 IP 可以动态获取,也可以静态分配,此时,副路由自己也是能够上外网的。然后,在副路由上运行 ss-tproxy,此时,副路由已经能够科学上网了,然后,我们在副路由上配置一个 LAN 网段(不要与主路由的 LAN 网段一样),假设主路由的 LAN 网段是 192.168.1.0/24,副路由的 LAN 网段是 10.10.10.0/24。然后指定一个网关 IP 给副路由的 LAN 口,假设为 10.10.10.1,开启副路由上的 DHCP,分配的地址范围为 10.10.10.100-200,分配的网关地址为 10.10.10.1,分配的 DNS 服务器为 10.10.10.1。现在,修改 ss-tproxy.conf 的内网网段为 10.10.10.0/24,重启 ss-tproxy,然后连接到副路由的设备应该是能够科学上网的。你可能会问,为什么不直接在主路由上安装 ss-tproxy 呢?假设这里的副路由是一个树莓派,那么我不管在什么网络下(公司、酒店),只要将树莓派插上,然后我的设备(手机、笔记本)只需要连接树莓派就能无缝上网了,同时又不会影响内网中的其它用户,一举两得(当然我只是举个栗子,实际上可能没想的这么方便)。
ss-tproxy 可以运行在内网主机上吗(代理网关)
可以。先解释一下这里的“代理网关”(不知道叫什么好),由网友 @feiyu 启发。他的意思是,将 ss-tproxy 部署在一台普通的内网主机上(该主机的网络配置不变),然后将其他内网主机的网关和 DNS 指向这台部署了 ss-tproxy 的主机,进行代理。方案是可行的,我在 VMware 环境中测试通过。注意,这个“代理网关”可以是一台真机,也可以是一台虚拟机(桥接模式),比如在 Windows 系统中运行一个 VMware 或 VirtualBox 的 Linux 虚拟机,在这个虚拟机上跑 ss-tproxy 当然也是可以的(你还别说,真有不少人是这样用的,我在公司也是这么用的)。
切换模式、切换节点不方便,能否避免直接修改文件
这确实是个问题,切换节点需要修改配置文件,切换模式需要修改配置文件,有没有更加简便一些的方式?抱歉,没有。不过因为 ss-tproxy.conf 是一个 shell 脚本,所以我们可以在这里面做些文章。如果你有很多个节点(付费机场一般都是,当然 ss-tproxy 可能更适合自建代理的用户),可以这样做:
# 编辑 /etc/ss-tproxy/ss-tproxy.conf 配置文件,在尾部添加两行:
["$2"]&&ln -sf /etc/ss-tproxy/$2.conf /etc/ss-tproxy/node.conf
source /etc/ss-tproxy/node.conf

# 在 /etc/ss-tproxy 下创建节点文件,如 node-1.conf、node-2.conf
cd /etc/ss-tproxy
touch node-1.conf node-2.conf

# 编辑 node-1.conf、node-2.conf,每个文件都代表一个不同的节点
# 以 node-1.conf 为例,使用 gfwlist 模式,服务器为 ss-node-1
mode='gfwlist'
proxy_tproxy='false'
proxy_server=(ss-node-1)
proxy_tcport='60080'
proxy_udport='60080'
proxy_runcmd='systemctl start 1'
proxy_kilcmd='systemctl stop 1'

# node-N.conf 中可以包含 ss-tproxy.conf 中的所有变量,如 node2
mode='chnroute'
proxy_tproxy='false'
proxy_server=(ss-node-2)
proxy_tcport='60080'
proxy_udport='60080'
proxy_runcmd='systemctl start 2'
proxy_kilcmd='systemctl stop 2'
dns_remote='8.8.4.4:53'

# 语法:ss-tproxy start|stop|restart [node-1|node-2|node-N]
# 说明:第 2 个参数其实就是节点文件的名称(注意没有 .conf 后缀名)
ss-tproxy start|stop|restart node-1 # 切换至 /etc/ss-tproxy/node-1.conf
ss-tproxy start|stop|restart node-2 # 切换至 /etc/ss-tproxy/node-2.conf
# 另外注意,这个节点名称的参数是可选的,默认就是上次切换后的那个节点,举个栗子:
ss-tproxy restart node-1 # 切换至 /etc/ss-tproxy/node-1.conf(内部会执行 ln -sf 来切换)
ss-tproxy restart # 依旧使用 node-1.conf 节点,因为 node.conf 仍然指向 node-1.conf
ss-tproxy restart node-2 # 切换至 /etc/ss-tproxy/node-2.conf(内部会执行 ln -sf 来切换)
ss-tproxy restart # 依旧使用 node-2.conf 节点,因为 node.conf 仍然指向 node-2.conf
Bash
配置文件以及其它文件的路径是否可更改
当然是可以的,比如你想将 /etc/ss-tproxy 默认目录改为 /opt/ss-tproxy,只需要修改两个地方,一个是 ss-tproxy 脚本的第 3 行,将 main_conf 变量改为 /opt/ss-tproxy/ss-tproxy.conf;另一个是 /opt/ss-tproxy/ss-tproxy.conf 里面的 file_* 变量,改为 /opt/ss-tproxy 目录下的就行了。顺便说一句,ss-tproxy 脚本本身也并不是说一定要放到 /usr/local/bin 目录下,只是我个人喜欢将第三方命令放到这个目录而已。
CentOS 7.x 必须关闭 firewalld 防火墙
当然 RHEL 7.x 也一样,因为 iptables 和 firewalld 都是 netfilter 的用户空间配置工具,而默认情况下,RHEL/CentOS 7.x 会将 firewalld 服务设置为开机自启动,而且还会设置一些防火墙规则,如果你不关闭这个服务,可能在做代理网关时,会遇到无法上网的情况,所以请务必执行 systemctl disable firewalld 来关闭它(然后重启系统)。当然也不是说一定要关闭 firewalld,如果你对 iptables 和 firewalld 比较熟悉,完全可以自由支配它们。
为什么必须使用 bash,而不能使用 sh、zsh 这些 shell
因为 ss-tproxy 脚本里面用到了非常多的 bash 高级重定向,而且有些 built-in 命令和 sh、zsh 的用法不同,无法兼容。
为什么使用 ipip.net 的 chnroute 源,而不是 APNIC 的源
这个怎么说呢,ipip.net 的源我觉得挺好的,用了很久也没啥问题,当然如果需要,你也可以自己改为其它的 chnroute 源,比如改为 APNIC 的大陆地址段列表。但是 ss-tproxy.conf 中并未提供这个选项,该怎么改呢?其实不难,你不需要去修改脚本,只需要在 ss-tproxy.conf 文件末尾添加以下内容(基本框架可以照抄,具体的更新命令可以自定义),ss-tproxy v4.0 已切换至 APNIC 源:
if["$1"='update-chnroute'];then

# 自定义的更新命令 - begin
curl -4sSkL 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest'|grep ipv4 |grep CN |awk -F'|''{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }'>$file_chnroute_txt
# 自定义的更新命令 - end

echo'-N chnroute hash:net'>$file_chnroute_set;sed -r 's/^.+$/-A chnroute &/'$file_chnroute_txt>>$file_chnroute_set
reserved_address=('0.0.0.0/8''10.0.0.0/8''127.0.0.0/8''169.254.0.0/16''172.16.0.0/12''192.168.0.0/16''224.0.0.0/4''240.0.0.0/4')
for addr in"${reserved_address[@]}";doecho"$addr">>$file_chnroute_txt;done
exit 0
fi
Bash
其实你可以完全模仿这个例子,来重写 ss-tproxy 中定义的全部函数,并且还可以添加额外的 ss-tproxy COMMAND,就看你怎么写了。
如何提高代理的性能(当然仅针对 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 进程:
function start_multiple_ssredir {
ss_addr='1.2.3.4'
ss_port='8443'
ss_method='aes-128-gcm'
ss_passwd='passwd.for.test'
(ss-redir -s$ss_addr -p$ss_port -m$ss_method -k$ss_passwd -b0.0.0.0 -l60080 -u --reuse-port </dev/null &>/dev/null &)
for((i =1; i < $1;++i));do
(ss-redir -s$ss_addr -p$ss_port -m$ss_method -k$ss_passwd -b0.0.0.0 -l60080 --reuse-port </dev/null &>/dev/null &)
done
}
Bash
然后修改我们的启动命令,即 proxy_runcmd,将它改为 proxy_runcmd='start_multiple_ssredir 4',其中 4 可以改为任意正整数,这个数值的意思是启动多少个 ss-redir 进程,一般建议最多启动 CPU 核心数个 ss-redir 进程,太多了性能反而会下降,当然你也可以将它改为 1,此时只会启动一个进程,也就没有所谓的加速了(多个 ss-redir 进程的加速仅针对多线程下载、多终端并发访问的情况,话虽如此,但是效果还是很明显的)。
ss-libev、ssr-libev 如何进行多节点负载均衡(SO_REUSEPORT)
其实非常简单,和上面的多进程 ss-libev、ssr-libev 加速差不多,只不过 ss_addr 不同而已,反正只要这些 ss-redir、ssr-redir 进程监听同一个 addr:port(127.0.0.1:60080),就可以正常使用,实际上 ss-tproxy 并不关心你使用的是哪个 proxy_server,也不关心你使用的是 ss-libev 还是 ssr-libev 还是 v2ray。有必要声明是,通过 SO_REUSEPORT 端口重用实现的负载均衡是“平均分配”的,假设有 4 个进程同时监听 127.0.0.1:60080,那么内核会将客户端连接平均分配给这 4 个进程(每个进程分配到的概率为 25%)。例子:假设我有 2 个 ss 服务器(1.1.1.1、2.2.2.2),2 个 ssr 服务器(3.3.3.3、4.4.4.4),我想同时使用这 4 个服务器(负载均衡),该如何做?
proxy_server=(1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4)
proxy_runcmd='start_load_balancing'

function start_load_balancing {
(ss-redir -s1.1.1.1 -p80 -maes-128-gcm -kpassword -b0.0.0.0 -l60080 -u --reuse-port </dev/null &>/dev/null &)
(ss-redir -s2.2.2.2 -p80 -maes-128-gcm -kpassword -b0.0.0.0 -l60080 -u --reuse-port </dev/null &>/dev/null &)
(ssr-redir -s3.3.3.3 -p443 -maes-128-cfb -kpassword -b0.0.0.0 -l60080 -u </dev/null &>/dev/null &)
(ssr-redir -s4.4.4.4 -p443 -maes-128-cfb -kpassword -b0.0.0.0 -l60080 -u </dev/null &>/dev/null &)
}
Bash
使用“代理网关”模式时,ss-tproxy stop 后,内网主机无法上网
如果 ss-tproxy 主机上没有运行 DNS 服务器(注意,如果代理网关上已经有一个运行在 53 端口上的 dns 服务器,就不要再执行这里的操作了,有些人看都不没看清就直接照抄过去),那就会出现这个问题,因为你的 DNS 设为了 ss-tproxy 主机的 IP,而你执行 stop 操作后,ss-tproxy 上的 dnsmasq 就会被 kill(注意 kill 的是 ss-tproxy 运行的那个 dnsmasq 进程,系统运行的或者你自己运行的 dnsmasq 进程不会被 kill),使得内网主机无法解析 DNS,从而无法上网。解决方法也很简单,修改 ss-tproxy.conf,添加两个钩子函数,post_stop 钩子函数的作用是在 stop 之后启动一个 dnsmasq,监听 0.0.0.0:53 地址,给内网主机提供普通的 DNS 服务,pre_start 钩子函数的作用是在 start 之前 kill 这个 53 端口的 dnsmasq,因为 ss-tproxy 代理启动后,这个 dnsmasq 进程就没有存在的必要了。ss-tproxy v4.0 自带重定向选项,不需要这么麻烦。
function post_stop {
dnsmasq --conf-file=/dev/null --no-resolv --server=${dns_direct}&>/dev/null
}

function pre_start {
if["$opts_ss_netstat"!="netstat" -a "$(command -v ss &>/dev/null &&echo'true')"];then
ss -lnpu |awk -F, '/:53[ \t].+"dnsmasq"/ {print $(NF-1)}'|awk -F='{print $2}'|sort|uniq|xargskill -9 &>/dev/null
else
netstat -lnpu |awk -F/ '/:53[ \t].+dnsmasq/ {print $(NF-1)}'|awk'{print $NF}'|sort|uniq|xargskill -9 &>/dev/null
fi
}
Bash
为什么使用 ping 命令来解析域名?而不是 dig、nslookup、getent
起初我是使用 getent hosts $domain_name 来解析域名的,但是后来我发现在某些系统上没有 getent 命令,所以我就改为了 ping 来解析。
为什么不支持自定义 dnsmasq 和 chinadns 的端口,只能使用默认的
因为没有这个必要,默认情况下,dnsmasq 监听 60053 端口,chinadns 监听 65353 端口,基本上没哪个进程会监听这两个高位端口,我之所以设置为高位端口也是为了尽可能避免端口冲突问题,在早期版本中,dnsmasq 是监听在 53 端口的,但是我收到了很多关于 dnsmasq 监听端口冲突的反馈,虽然端口冲突问题不难解决,但是我为了一劳永逸,直接将这个端口改为了 60053,从根本上避免了这个问题。ss-tproxy v4.0 支持自定义 dnsmasq、chinadns-ng 监听端口,支持加载外部的 dnsmasq 配置,只要这些配置与 ss-tproxy 使用的配置不冲突就行。
为什么 gfwlist 模式需要用到 perl?而不是使用 sed、awk、grep 这些
因为 Perl 的正则表达式真的很强大,而且没有兼容性问题,sed、awk、grep 基本都有兼容性问题。注:ss-tproxy v4.0 中 Perl 不再是必要依赖。
支持 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,修改这几条配置(假设 vps 地址为 1.2.3.4):
proxy_server=(1.2.3.4)
proxy_runcmd='start_sslibev_kcptun'
proxy_kilcmd='kill -9 $(pidof ss-redir)$(pidof kcptun-client)'
Bash
注意,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,而不用在 proxy_runcmd 中写很长的启动命令;然后,在 ss-tproxy.conf 的任意位置添加以下配置(我个人喜欢在文件末尾添加),假设 method 为 aes-128-gcm,password 为 passwd.for.test:
function start_sslibev_kcptun {
(kcptun-client -l :8080 -r 1.2.3.4:8080 --mode fast2 </dev/null &>/dev/null &)
(ss-redir -s127.0.0.1 -p8080 -maes-128-gcm -kpasswd.for.test -b0.0.0.0 -l$proxy_tcport</dev/null &>/dev/null &)
(ss-redir -s1.2.3.4 -p8053 -maes-128-gcm -kpasswd.for.test -b0.0.0.0 -l$proxy_udport -U </dev/null &>/dev/null &)
}
Bash
延伸:除了 ss、ssr、v2ray,ss-tproxy 还支持其它的吗
首先你要清楚一点:ss-tproxy 并不关心你使用什么代理,它关心的仅仅是 proxy_tcportproxy_udportproxy_serverproxy_dports
  • proxy_tcport:用来接收 TCP 透明代理数据包的端口(REDIRECT/TPROXY),随便填,只要这个端口能处理 TCP 透明代理数据包
  • proxy_udport:用来接收 UDP 透明代理数据包的端口(TPROXY),随便填,只要这个端口能处理 UDP 透明代理数据包
  • proxy_server:告诉 ss-tproxy,哪些目标地址需要放行,显然,与代理有关的目标 IP 必须填上,如 VPS 的 IP/域名
  • proxy_dports:告诉 ss-tproxy,proxy_server 上的哪些端口需要放行,默认是 proxy_server 上的全部端口都放行
如果还不明白,我用通俗的语言来解释这 4 个核心选项的作用:我们将 ss-tproxy 主机看作一根水管,一头是入口(数据包都从这里进去),一头是出口(数据包都从这里出去),里面流的当前就是水了(数据包),那么 proxy_tcport 和 proxy_udport 就是告诉 ss-tproxy,你要将数据包送到哪里去(当然这里的数据包是指需要代理的数据包,放行的流量是不会被送到这个入口的),而 proxy_server 和 proxy_dports 就是告诉 ss-tproxy,这些数据包经过处理后会从哪里出来(也即目标地址、目标端口);管子内部随便你怎么接,你只要能保证数据包能流通,ss-tproxy 就会正确的配置好代理和分流。
这里的管子接法其实就是指底层代理的组合方式,管你是 ss-redir + kcptun,还是 ssr-redir + udp2raw,你只要能保证两头没问题,就可以使用。
为什么 REDIRECT + TPROXY 模式的代理需要监听 0.0.0.0
我在 README 里面强调过,ss-redir 和 ssr-redir 的监听地址需要指定为 0.0.0.0(当然其它代理软件也一样,如果是 REDIRECT + TPROXY 组合方式的话),如果你不指定这个监听地址,或者指定为监听 127.0.0.1,那么你会发现内网主机是无法正常代理上网的,为什么呢?据我个人猜测,应该是 iptables 的 REDIRECT 的问题(听说改为 DNAT 可以避免这个问题,但经过验证貌似也是有问题的),具体什么原因我也不想深究了,没多大意义。
如果只代理 ss-tproxy 本机的流量,不关心其它内网主机,那么完全可以将监听地址改为 127.0.0.1、::1。
如何在 ss-tproxy 中集成 koolproxy 等广告过滤软件
ss-tproxy v4.0 规则变动较大,下面的规则可能不再适用,个人觉得使用浏览器插件进行广告过滤也挺好的。
adbyby 和 koolproxy 是路由固件中常见的两个广告过滤插件,因为 adbyby 不支持 https 过滤,所以这里就以 koolproxy 作为例子讲解。首先打开 https://firmware.koolshare.cn/binary/KoolProxy/,下载对应平台的 koolproxy 二进制文件,然后将它放到 /opt/koolproxy 目录(当然放哪里没要求),并命名为 koolproxy,然后加上可执行权限;进入 /opt/koolproxy 目录,执行 ./koolproxy --cert 生成 koolproxy HTTPS 证书等文件;因为待会我们需要用一个非 root 用户来运行 koolproxy 进程(可以从 /etc/passwd 中随便找一个已存在的用户,比如 daemon),所以我们要先将 /opt/koolproxy 目录的所有者改为 daemon,不然 koolproxy 自动更新广告过滤规则时会遇到权限问题,即执行命令 chown -R daemon:daemon /opt/koolproxy;最后编辑 ss-tproxy.conf,在文件末尾添加这两个钩子函数,就可以实现 koolproxy + ss-tproxy 组合方式的 广告过滤 + 透明代理(广告过滤或多或少都会影响性能,如果设备性能不太好,不建议集成 koolproxy 等广告过滤软件,这种情况下在客户端进行广告过滤会好一些):
function post_start {
su -s/bin/sh -c'/opt/koolproxy/koolproxy -d -l2 -p65080 -b/opt/koolproxy/data' daemon
if["$proxy_tproxy"='true'];then
iptables -t mangle -I SSTP_OUT -m owner ! --uid-owner daemon -p tcp -m multiport --dports 80,443 -j RETURN
iptables -t nat -I SSTP_OUT -m owner ! --uid-owner daemon -p tcp -m multiport --dports 80,443 -j REDIRECT --to-ports 65080
for intranet in"${ipts_intranet[@]}";do
iptables -t mangle -I SSTP_PRE -m mark ! --mark $ipts_rt_mark -p tcp -m multiport --dports 80,443 -s $intranet! -d $intranet -j RETURN
iptables -t nat -I SSTP_PRE -m mark ! --mark $ipts_rt_mark -p tcp -m multiport --dports 80,443 -s $intranet! -d $intranet -j REDIRECT --to-ports 65080
done
else
iptables -t nat -I SSTP_OUT -m owner ! --uid-owner daemon -p tcp -m multiport --dports 80,443 -j REDIRECT --to-ports 65080
for intranet in"${ipts_intranet[@]}";do
iptables -t nat -I SSTP_PRE -s $intranet! -d $intranet -p tcp -m multiport --dports 80,443 -j REDIRECT --to-ports 65080
done
fi
}

function post_stop {
kill -9 $(pidof koolproxy)&>/dev/null 
}
}
from https://www.zfl9.com/ss-redir.html

全局(指整台机器的)代理程序方面,snet最好用

有政府利用根证书设陷阱,拦截通讯,监察民众

$
0
0
问:虽然网络科技日新月异,但个别政府侵犯民众网络私隐的手法亦层出不穷,像最近哈萨克政府推出的新数码根证书,就被发现有可能让政府监视民众的网络活动,因此被苹果、谷歌和Mozilla三大浏览器开发组织联手封锁,只有微软至今仍然态度暧昧。其实哈萨克政府的根证书有甚么问题?
李建军:数码证书看来是很简单的一回事,但实际并非如此,因为要确保整个加密通讯过程,并不会有人可以成功中途拦截资料,数码证书如何发出,必须有一套严谨机制,因此,数码证明的发出机构,一般要投资相当多技术和金钱,去确保整个证书发出过程可靠性,亦会寻求独立的机构,去证明证书发出机构,并不会利用签发证书的机会,暗中设陷阱偷资料。
而哈萨克政府,就滥用政府部门在签发数码证书时,一般被视为可信任机构的假设,暗中在根证书中加入陷阱,可以令哈萨克政府任意拦截加密的通讯,包括浏览脸书、GMail一类网站的通讯,对民众私隐有极大的威胁,因此,哈萨克政府成为中国政府属下CNNIC之后,另一个政府所签发的证书,不被主流浏览器开发组织承认。
问:这次哈萨克政府签出的根证书,与2015年CNNIC签发的证书不被信任,到底又有甚么不同?
李建军:2015年的CNNIC事件,主要是CNNIC签发假的谷歌证书,本身行为太明显有问题,因此被否定,这不涉及在技术上设下陷阱,藉机拦截网络通讯。
但这次哈萨克政府的狡猾程度,比2015年CNNIC事件严重得多,哈萨克是设计一个有缺陷的根证书,只要民众为了享受政府服务,安装哈萨克政府的根证书,哈萨克政府精心设计的监控系统,就因此获授权得到民众通讯的内容,因此,这次哈萨克政府的做法,比起CNNIC那次的做法先进得多。
问:如果政府部门滥用根证书签发权,成为了一种趋势,甚至日后中国都可能会出现类似情况,但使用一些政府网上服务,就难免要安装政府的根证书,那可以怎么办?特别主流浏览器都可能拒绝承认这些政府发出的根证书。
李建军:首先,个别政府可能滥用Chrome或Safari的源码,在加以修改后,推出特殊的浏览器,有可能各大电讯公司只接受使用特殊浏览器的用户通行,达致监视网民活动的效果,因为在各大浏览器开发组织杯葛下,只有政府推出一些奇怪的浏览器,才能够做到强迫民众安装相关的根证书的效果。
而要避免受到硬要安装的根证书和浏览器影响,可能用作翻墙用的电脑,必须与一般使用公共服务用的电脑分开。翻墙用的电脑,不要安装政府强迫的浏览器和根证书,为了避开当局的检查,就平常浏览网页都翻墙,以及避免浏览中国当局的网站,或必须使用当局强逼安装的根证书的网站和程式,相信有相当多国有的网上银行会受影响;而另一部电脑就安装了有问题的根证书,以及主力用作浏览政府网站,处理网上银行或公共服务申请。哈萨克这次事件,其实是警告中国民众,当局要千方百计偷取个人资料,其实是可以做得到,翻墙时不可以对这种技术趋势掉以轻心。

年代向錢看 四大杀手锏

替mac系统设置“系统代理”的程序:global-proxy-cli

$
0
0


Set system proxy for mac and windows platform.
MIT License

Installation

$ npm install -g global-proxy-cli

Usage

  Usage: global-proxy [options]


Options:

-e, --enable ................... enable the system proxy.
-d, --disable .................. disable the system proxy.
-h, --host hostname ............ the hostname of the system proxy.
-p, --port port ................ the port of the system proxy.
-t, --type protocol ............ the protocol of the system proxy.
-s, --status ................... get the status of the system proxy.(mac only)
-V, --version .................. display the current version of this cli.
-H, --help ..................... you're looking at it.

Examples:

$ global-proxy -s
$ global-proxy --enable --host=127.0.0.1 --port=9000
$ global-proxy --disable
from https://github.com/bubkoo/global-proxy-cli

MacOS系统通过gotun2socks实现全局代理(包括智能分流)

$
0
0

安装 go 语言

homebrew 是 Mac 系统下面目前使用最多的管理软件的工具,目前已支持 Go,可以通过命令直接安装 Go,为了以后方便,应该把 git mercurial 也安装上:
  1. 安装 homebrew
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  1. 安装 go
$ brew update && brew upgrade
$ brew install go
$ brew install git
$ brew install mercurial #可选安装
注意要将 $GOPATH/bin 加入 $PATH 环境变量,编辑 /etc/profile
$ vim /etc/profile 
加入以下内容
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
然后执行以下命令使环境变量生效
$ source /etc/profile

安装 gotun2socks

$ go get github.com/yinghuocho/gotun2socks/bin/gotun2socks
这个命令会将 https://github.com/yinghuocho/gotun2socks 仓库克隆下来,并且将 bin/gotun2socks/main.go 编译成可执行二进制文件放到 $GOPATH/bin 目录下,现在你应该理解为什么要将 $GOPATH/bin 加入 $PATH 环境变量了吧。
(从这里开始,看我的补充说明,然后不需要再往下看了。

我的补充说明

sudo gotun2socks -local-socks-addr 127.0.0.1:1080 -tun-address 10.0.1.2 -tun-device tun2 -tun-dns 127.0.0.1 -tun-gw 10.0.1.1

sudo route delete default && sudo route add default 10.0.1.1 && sudo route add vps-ip 192.168.1.1  

sudo networksetup -setdnsservers "Wi-Fi" 127.0.0.1

cd ~/goproxy-by-snail007 && sudo ./proxy dns -S socks -T tcp -P 127.0.0.1:1080 -p :53 

mac机器上,需开着纸飞机。

然后,整台mac机器就处于翻墙状态了。

项目地址:https://github.com/yinghuocho/gotun2socks )

安装 shadowsocks-libev

$ brew install shadowsocks-libev
补充:MacOS 中可以通过 brew 来运行守护进程,命令以及参数如下
#列出当前运行的服务
$ sudo brew services list

dbus stopped
pcap_dnsproxy started root /Library/LaunchDaemons/homebrew.mxcl.pcap_dnsproxy.plist
shadowsocks-libev started root /Library/LaunchDaemons/homebrew.mxcl.shadowsocks-libev.plist

#停止 shadowsocks-libev 服务
$ sudo brew services stop shadowsocks-libev

#启动 shadowsocks-libev 服务
$ sudo brew services start shadowsocks-libev

#重启 shadowsocks-libev 服务
$ sudo brew services restart shadowsocks-libev

获取中国 IP 段

将以下命令写入脚本保存执行(假设保存在 $HOME/bin/routing-table 目录下):
#!/bin/sh

wget -c http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
cat delegated-apnic-latest | awk -F '|''/CN/&&/ipv4/ {print $4 "/" 32-log($5)/log(2)}'| cat >$HOME/bin/routing-table/cn_rules.conf

配置智能 DNS 服务

PS:MacOS 系统可以通过 brew 安装
$ brew install pcap_dnsproxy

配置路由表启动脚本

$ cat /usr/local/bin/start-socksfwd

#!/bin/bash

# SOCKS 服务器的 IP 地址
SOCKS_SERVER=47.52.201.34
#本地SOCKS 服务器的端口
SOCKS_PORT=1080
#家用网关(路由器)的 IP 地址,你也可以手动指定
# GATEWAY_IP=$(ip route|grep "default"|awk '{print $3}')
GATEWAY_IP=192.168.1.1
#选一个不冲突的 tun 设备号
TUN_NETWORK_DEV=tun0
#选一个不冲突的内网 IP 段的前缀
TUN_NETWORK_PREFIX=12.0.0

#启动 gotun2socks
nohup /usr/local/bin/gotun2socks -tun-device "$TUN_NETWORK_DEV" -tun-address "$TUN_NETWORK_PREFIX.2" -tun-gw "$TUN_NETWORK_PREFIX.1" -local-socks-addr "127.0.0.1:$SOCKS_PORT"&>/dev/null &

route add "$SOCKS_SERVER""$GATEWAY_IP"

#特殊ip段走家用网关(路由器)的 IP 地址(如局域网联机)
route add "192.168.0.0/16""$GATEWAY_IP"
route add "10.8.0.0/16""$GATEWAY_IP"

#国内网段走家用网关(路由器)的 IP 地址
foriin$(cat $HOME/bin/routing-table/cn_rules.conf)
do
route add "$i""$GATEWAY_IP"
done

#将默认网关设为虚拟网卡的IP地址
route delete default
route add default "$TUN_NETWORK_PREFIX.1"

配置路由表删除脚本

$ cat /usr/local/bin/stop-socksfwd

#!/bin/bash

# SOCKS 服务器的 IP 地址
SOCKS_SERVER=47.52.201.34
#本地SOCKS 服务器的端口
SOCKS_PORT=1080
#家用网关(路由器)的 IP 地址,你也可以手动指定
# GATEWAY_IP=$(ip route|grep "default"|awk '{print $3}')
GATEWAY_IP=192.168.1.1
#选一个不冲突的 tun 设备号
TUN_NETWORK_DEV=tun0
#选一个不冲突的内网 IP 段的前缀
TUN_NETWORK_PREFIX=12.0.0

route delete default
route add default "$GATEWAY_IP"

foriin$(cat $HOME/bin/routing-table/cn_rules.conf)
do
route delete "$i""$GATEWAY_IP"
done

# route delete "192.168.0.0/16""$GATEWAY_IP"
# route delete "10.8.0.0/16""$GATEWAY_IP"
route delete "$SOCKS_SERVER""$GATEWAY_IP"

TUN2SOCKS_PID=$(ps aux|grep tun2socks|egrep -v "grep"|awk '{print $2}')
kill$TUN2SOCKS_PID
启动流程为:
  • 启动 shadowsocks 服务:
$ sudo brew services start shadowsocks-libev
当然这里不一定得用 shadowsocks 服务,只要是 socks5 协议都可以。
  • 添加路由表
$ sudo bash /usr/local/bin/start-socksfwd
关闭流程为:
  • 删除路由表
$ sudo bash /usr/local/bin/stop-socksfwd
  • 停止 shadowsocks 服务

how to use Assertive Language in English

$
0
0

https://www.speakconfidentenglish.com/

Anyone Can Speak English Like a Native

$
0
0

practice more,copy/simulate more.


mac上的全局代理程序总结

$
0
0
全局(指整台机器的)代理程序方面,snet最好用,见:
https://briteming.blogspot.com/2019/08/snet.html

其他几个稍微繁琐一点,不过其实也不麻烦,就是要运行一下路由命令,详见下面各个文章里的橘黄色文字。
这几个是:
利用全局代理程序-notbevpn翻墙
利用全局代理程序-tun2socks翻墙
利用全局代理程序:quickqservice-tun2socks翻墙
MacOS系统通过gotun2socks实现全局代理

还有https://briteming.blogspot.com/2018/10/reborn-macos.html

以及https://briteming.blogspot.com/2016/02/surge-for-mac.html (其实它并不能使整个mac机器上的所有程序都处于翻墙状态,只是能使部分程序处于翻墙状态,比如Mail.app,所以它实际上是一款'准全局代理’)

https://briteming.blogspot.com/2016/09/macshadowsocksspechtlite.html  (SpechtLite实际上是一款'准全局代理’)

ESNI(Encrypted Server Name Indication)及检测

$
0
0
firefox浏览器为我们带来另一项安全设置加密的SNI,即:加密的服务器名称指示 ESNI(Encrypted Server Name Indication)

一、先说Firefox如何设置ESNI

有了DNS over HTTPS (DoH)之后,进一步设置ESNI,很简单,一个设置完成
打开Firefox浏览器,
在地址栏输入 about:config 后回车,或者点工具栏上的“书签”→其他书签,点里面预设的 about:config
弹出安全警告:点“我了解此风险!”,会进入设置项
在搜索框中输入: network.security.esni.enabled
设为 true

二、检测ESNI是否生效

Cloudflare为大家提供了一个详细的检测网站
Cloudflare ESNI Checker | Cloudflare
https://www.cloudflare.com/ssl/encrypted-sni/
打开网站后:
点中间橘色Check My Browser条块,就会得到检测结果,如下图所示:
结果一目了然,绿色勾表示加密,红色X表示没有加密

三、网络连接中的信息泄露/中间人攻击

众所周知 HTTP 明文协议等于裸奔,但即使用了 HTTPS,还是有一些信息会暴露:
1、TLS证书信息的暴露。这一问题在最新版的 TLS1.3 草案中得到了解决。Firefox 也已经支持了 TLS1.3 [5]。
2、DNS 查询会暴露你查询的域名。DNS 未经加密,有被中间人投毒的风险。这一问题的解决方案是加密 DNS 查询,目前有多种解决方案,DNSSEC,DNSCrypt,DoT,DoH。Firefox支持了其中的 DNS over HTTPS (DoH) [6],并有很详细的科普[7]。
3、访问的 IP 地址会暴露。这个没有办法,封 IP 基本无解。
4、SNI 暴露域名信息。TLS 验证证书需要域名信息,而同一 IP 可能托管多个域名,所以就有了 SNI (Server Name Indication)。在建立 TLS 链接时 SNI 域名会明文发送,中间人就可以知道你访问了哪个域名,然后*河蟹*。ESNI 就是为了解决这个问题。

四、什么是Encrypted SNI(ESNI)

“服务器名称指示”(Server Name Indication,简称SNI)是一个扩展的TLS计算机联网协议,在该协议下,在握手过程开始时客户端告诉它正在连接的服务器要连接的主机名称。这允许服务器在相同的IP地址和TCP端口号上呈现多个证书,并且因此允许在相同的IP地址上提供多个安全(HTTPS)网站(或其他任何基于TLS的服务),而不需要所有这些站点使用相同的证书。它与HTTP/1.1基于名称的虚拟主机的概念相同,但是用于HTTPS。所需的主机名未加密, 因此窃听者可以查看请求的网站
为了使SNI协议起作用,绝大多数访问者必须使用实现它的Web浏览器。使用未实现SNI浏览器的用户将被提供默认证书,因此很可能会收到证书警告。
随着TLS1.3的发布,让该协议成为有史以来最安全、也是最复杂的TLS协议。在该协议之中,有很多的对于以往协议安全漏洞的修复,包括废弃RSA启用新的秘钥交换机制PSK等等。而Encrypted SNI作为一个TLS1.3的扩展协议用来防止传统的HTTPS流量受到ISP或者陌生网络环境的窥探以及一些网络审查。在过去,由于HTTPS协议之中Server Name Indication - SNI的使用,我们的HTTPS流量经常被窥探我们所访问站点的域名。
为了弥补缺陷因应运而生的ESNI
在上述过程之中,存在的问题就是,在ClientHello环节中,TLS会在这个位置以明文的形式讲要请求的Host写在数据包之中,如果在网络路由中有任何的监听节点,那么用户所访问网站的域名将暴露无遗,这将是巨大的用户隐私泄露:
依靠安全DNS的ESNI
上一个问题没有难倒工程师们,他们设计了这样一个办法。首先让网站提供者在DNS提供商上公布一个记录,这个记录包含着一个公钥,这个公钥由网站提供者生成,其私钥存储在Web服务器等待着被Web程序读取。如此,当用户想通过TLS1.3协议访问这个域名的时候,首先读取这个公开的公钥,在用公钥加密其想访问的域名Host,装在Client Hello里面发送给目标服务器,目标服务器再用自己的私钥解密,从而和用户建立HTTPS链接,这样就不会暴露Host信息。
目前来说,有了HTTPS+TLS1.3+ESNI+DoH/DoT的加持,我们的网络隐私的到了极大的保障,最后还有一个问题是访问服务器IP的泄露仍然无法被避免,迫于IP协议设计的机制,他目前还不能被解决。不过我相信,随着网技术不断的趋于保护个人隐私和更快速的发展方向,这个问题可以最终被解决.

幾個特徵說明中共對你統戰成功了

$
0
0


時任加拿大駐華大使的麥家廉(John McCallum )於今年1 月,當中國華為副董事長孟晚舟在溫哥華被逮捕,加中關係陷入僵局時,先後發表兩次講話,先是認為可以幫助孟晚舟反駁引渡的觀點論據,後又提出如果美國放棄對孟晚舟的引渡要求,對加拿大而言有極大好處,兩次失言讓加國總理杜魯多不得不解除他的職務。其後,麥家廉又在接受香港《南華早報》訪問時說出,他曾警告北京不要對加拿大進一步採取制裁行動,否則會變相幫助聯邦保守黨在11 月大選中獲勝。
有豐富歷練的外交官麥家廉為甚麼會一而再地站在中國立場去評說孟晚舟事件,公然地教導中國如何干預聯邦大選,而不是捍衛自己國家的利益?我認為這是中共在他身上施行「統一戰線」政策的結果。
 「統一戰線」(傳統英文譯名United Front,簡稱統戰,漢語拼音直譯Tong Zhan,)是中共自稱的三大法寶之一。毛澤東總結共產黨奪權成功的經驗是:「一個有紀律的,有馬克思列寧主義的理論武裝的,採取自我批評方法的,聯繫人民群眾的黨;一個由這樣的黨領導的軍隊;一個由這樣的黨領導的各革命階級、各革命派別的統一戰線。這三件是我們戰勝敵人的主要武器。」 更多
「統一戰線」是共產主義陣營的鬥爭策略,具有悠久的歷史,其始創人是馬克思、恩格思,經列寧創新後傳入中國。根據《紅太陽是怎樣升起的》一書記載,王明是中共領導層中,倡議轉變政策建立「抗日民族統一戰線」第一人。1935年中共中央政治局在瓦窯堡會議上決議建立「抗日民族統一戰線」的策略。
毛澤東時代的「統一戰線」已經不單只是列寧所倡議的國與國之間,黨與黨之間的結盟或聯盟。他確信由於日本帝國主義的入侵,國民黨營壘在民族危機來臨之時,是會發生破裂的, 共產黨的任務是把紅軍和全國的工人、農民、學生、小資產階級、民族資產階級匯合起來,建立一個廣泛的民族革命統一戰線。他總結:當革命形勢改變時,革命的策略,革命的方式也必須跟着改變。 更多

隨機 實用 功利

毛澤東因應統戰策略可以作出極大的妥協。1937年他提出,為了建立「抗日民族統一戰線」可實行:「1。把陝甘寧革命根據地政府改名中華民國特區政府,紅軍改名國民革命軍,受南京中央政府軍事委員會指導。(請注意:香港特別行政區的設計並非鄧小平首創) 2。在特區政府區域內,實行徹底的民主制度方針。3。停止武力推翻國民黨。4。停止沒收地主的土地。」 更多這裏可以看到毛澤東的統戰政策的隨機性,實用性,功利性,因而是機關計算沒有理想的農民起義本質。
可見,統戰只不過是共產黨在新形勢、新條件下奪權的策略,它可以把原來的死敵變成統戰對象,可以把原來聲稱要打倒資本主義,推翻國民黨政權,建立社會主義和共產主義的最高綱領放下,轉變成建立民主共和國的最低綱領。在統戰的策略下,為了籠絡人心,中共作出有原則,有條件,有限度的讓步,並聲稱要實行自由民主制度,其鬥爭策略的靈活程度,不得不讓人嘆為觀止。
毛澤東堅定地確信,敵人營壘是可分化瓦解的:「頑固勢力以後要逐漸分化,利用他們的矛盾,採取分別對待的政策,用極大的力量去團結中間派和進步派。」 更多 所以統一戰線的任務就是分化和瓦解敵人,講究的是如何利用矛盾,分辨打擊或拉攏的對象,以及採用分別對待各類人物的手法。毛澤東又提出:「拿自己的策略武器去射擊最中心的目標,而不是把目標分散,以至主要敵人沒有打中而浪費彈藥。把極少數的打擊目標驅到狹小的孤立陣地上,把敵人營壘中被裹脅的人們,過去是敵人而今日可能做友軍的人們,都從敵人營壘中拉過來。」 更多
他為「統一戰線」作了歸結:「統一戰線的原則有兩個,第一是團結,第二是批評、教育和改造,為了改造先要團結。」 更多看吧!與統戰對象交朋友投其所好、關心其困難給予利益、邀請委任、高級別上賓款待等都是團結的手法。團結你,溝通你,邀請你,是要改造你,收降你。認清統一戰線的本質,是破解其奸險的首要法門。
「統一戰線」是中共生死攸關的生命線,自上世紀三十年代一直沿用至今沒有改變。現在仍然有一個舉世無雙的中國共產黨中央委員會統一戰線工作部,簡稱「統戰部」(The United Front Work Department of the Central Committee of the Communist Party of China) ,內設民族、宗教工作局,港澳台、海外聯絡局,西藏工作局,新疆工作局等共九局,專門負責統戰國民黨人、少數民族、宗教事務、港澳台商人、海外僑胞以及外國政府官員等。目前的部長是尤權。
中國改革開放之初,鄧小平重建統戰部,明確指示這個時期的統一戰線是「愛國統一戰線」。自中共黨主席習近平上台以來,亦十分重視統戰工作。2017年後,他成立中央統一戰線工作領導小組,把統戰工作融入治國理政新理念、新思想、新戰略之中,並進行機構改組,合併和升級(加掛牌子:國家宗教事務部升級為中央宗教事務主管部,國務院僑務辦公室升級為中央華僑事務主管部)。習近平在一系列統戰工作會議上對「統一戰線」的性質、內容、方式和方法作出新的詮釋,作了多項突出而具體的指示,比如:
「統戰工作是黨的特殊群眾工作,要有特殊的方式方法,講求很強的工作藝術。」
對統戰對象「要建立經常性聯繫渠道,引導其政治觀點,增進其政治認同。要重視和解決他們的政治利益和具體利益,盡心竭力幫助他們解決實際問題。」
「做好新形勢下統戰工作,必需善於聯誼交友,統一戰線是做人的工作,是為了壯大共同奮鬥的力量。」

習近平的「統一戰線」

習近平對「統一戰線」的認識,既沿襲傳統也有新穎的述說,把統戰策略發展成更具國策特色的,精細深入的影響和滲透活動。
當一個人被中共選中成為統戰對象時,他立即面對一連串心理的、感情的、原則性的思想掙扎與及修養和品格的考驗。他會有榮耀感、滿足感,以為自己更被重視。他們既然與中共做朋友,不知不覺中有一份見面情,為中共給予的好處感恩戴德,便開始為中共的罪行開脫,不好意思拒絕中共的要求,不想得罪中共,進而為中共辦事,失去普世價值的底線。 如果被統戰者開始對是非黑白,平等公義閉口不言,不再批評中共,即是說中共統戰成功了。上述前駐華大使麥家廉是一個明顯的例證。
要破解中共的統戰策略,人們要有高瞻遠矚,胸懷坦蕩,無私無求的品格,要有堅定的民主信念和信心,更要認識中共的本質,才能看穿中共的陰謀鬼計,不會上當受騙。西方各國的官員,特別是那些長駐中國的外交官們,定必處於中共統戰磁力場的包圍中,要有堅決拒絕被統戰的決心。在這個過程中,無論是統人者或是被統者均無犯法,這不是間碟活動,而是一場心理戰爭,這就是統戰策略的利害之處。
時至今日,中共靠着廣大市場為餌,乘着大國崛起之勢,又利用人們血濃於水的愛國本能,在香港建立的「愛國統一戰線」,正得心應手地發揮作用。「統一戰線」策略也正在全世界的每一個角落裏推進,其滲透狀況己有新西蘭、加拿大、美國、澳州等國的教授、學者和官員出版了巨細無遺,精彩絕倫的報告或文章,令筆者感到無限驚喜。
最後,「統一戰線」的英文譯名(United Front)是歷史遺留下來的名稱,已經不能表達現代中共統戰工作的特質,本人建議把英文譯名直譯為漢語拼音「Tong Zhan」。
加拿大前駐華大使麥家廉是加入中共「統一戰線」一個明顯的例證。(湯森路透)
※作者為為自由撰稿人,筆名牛虻。1958年畢業於香港香島中學,曾加入地下中國共產黨。被地下黨派去<學友中西舞蹈研究社>(即學友社)開展學生工作,自1962年至1972年擔任學友社主席。林彪事件後於1974年決意移民加拿大,並脫離共產黨。1997年2 月香港回歸前夕,在香港<開放雜誌>發表第一篇關於中共地下黨文章。現年79歲,居加加拿大。

兵团的缩影

$
0
0


若说今日中国是“流沙上的大厦”,兵团便是一个典型的缩影。

石河子是兵团在新疆从无到有造出的城市。石河子市政府门前竖着一块碑,宣称石河子获得了国家评比的“园林城市”称号。没错,这座被沙漠戈壁包围的城市,比很多中国内地城市的绿化程度还高,遍布花草树木。市中心广场是一片围绕兵团创始人王震雕像的巨大绿地,音乐喷泉跳跃,到处喷水浇灌草坪和花卉。周边是现代化建筑。衣着光鲜的人们游玩、漫步、照相或乘凉。广场似乎在用一种高度的反差证明兵团的能力。沙漠不是没水吗?这里就要充满水!不是没草吗?这里就搞一个全国最大的城中草地!仅看石河子的中心广场,会惊叹兵团奇迹和发展的成功,甚至是辉煌!

这景象却和兵团的基层连队反差巨大。搞这样一个“园林城市”,不知得有多少农田失去本可以获得生命和收获的水。当连队的农工在为水焦急,睡不着觉,晚一天灌溉都可能失去下一年生存保证时,大量的水慷慨地浇在这种展示辉煌的绿地上。

兵团最基层的单位是连。所谓的“连”和内地的村没什么区别,只是人的流动性更大,或者应该叫移民村。一般是一百多户人家,三、四百口人。兵团第一代职工早都病的病,死的死。原来能够激励兵团人的信仰已荡然无存。兵团第二代人在农村长大,却普遍自认为是城市人,不愿务农,想方设法或上学或打工,离开土地。原来兵团的集体化组织基本解体。连队现在主要靠出租土地获得收入。兵团就像一个最大的地主,前辈开垦出来的荒地变成了良田,后代靠吃地租过日子。而干活的人多为新移民和所谓的“长工”。

“长工”这个词过去只有在控诉旧社会剥削压迫时才能听到,指的是给地主充当长期雇工的农村无产者。而今问这儿的农工在干什么,全都坦然说给东家当“长工”。东家便是依靠权力和关系能够大量承包连队土地的连队干部和老职工,他们雇佣“长工”耕作。包地要交租金,还要投资买种籽、化肥、农药等,用水和使用机械也要花钱。如果包的土地少是挣不到钱的。一般的劳动者包不起太多的地,又怕担风险,所以只能给那些有钱多包地的大户当长工。长工来此只为挣钱,一般呆个二三年,挣了钱就走。他们和东家的收入差距一般有十数倍甚至更多,劳动强度却大得多,一天要干十多个小时,没有休息日。

连干部的权力很大,连长、指导员、会计、水管员、农机员等构成连队的特权阶层,可以决定给谁好地或不好的地,决定先给谁用水,后给谁用水,差上两天用水,收成就会很不同。所以连长都是当地一霸,也有不少捞外快、收贿赂的机会。

连长常去内地为连队招工,顺便也给自己找“长工”。连长大都是包地大户,少不了干活的人。他们一般不会用老职工或职工的子女,那些人不好欺负,内地招来的临时工却好摆布。某连长就这样弄了一帮内地农民给自己当「长工」,说好年终付工资,等到人家干满了要回家时,却编个理由不给工资,且使用恐吓手段。那些“长工”身在异地,不敢对抗,只好空手回家。等那连长再次去内地招工时,冤家路窄,被曾经没拿到工钱的人碰上,就把他杀了。这个真实故事虽是局部案件,却能反映兵团基层的现实状况。

脱钩就脱钩,有什么大不了的?

$
0
0
大家都在热议钩钩,相当部分人非常担忧,担忧一旦脱了就只能吃糠咽菜。但我认为脱比不脱好,脱一脱也没什么大不了的。
去年战火伊始,我们终于知道了妹果是芯片第一大生产果。中途油荒,我们又知道了妹果是第一大原油生产果。再接着大豆战,我们知道了妹果是大豆第一大生产果。再接着我们知道了妹果是第一大棉花生产果。当下猪肉轮番上涨,我们知道了妹果还是第一大猪肉生产果,这把产猪大果羞辱得无地自容。艾玛呀,原先我们只以为妹果是可乐汉堡的第一大果,再其次还知道妹果是航母第一大果,这一场旷日持久的拉锯战让我们大开眼界,原来什么都是妹果是第一大果。潮退之后,如梦初醒,原来厉害果一直都在裸泳。
裸泳也就罢了,你不要往水里排泄脏东西啊,结果不是,而是想怎么拉就怎么拉,大有不拉白不拉的吞云气势,本来好好的水就这样给搅黄了。不过,这也很好,通过这场拉锯战,我们终于知道了谁是恶脏臭第一生产大果。如果这样的钩还不脱,妹果就是一傻叉,这就是我特别鄙视那金毛总统很窝囊的原因。两个电话就软了,别人明明在把他当猴耍,他还自认为自己很牛叉。
昨天我看见杨连宁的一篇文章,题目有点让人不适,但内容丰富翔实。然而,他在文中连续两次引用老村长的话让我特别恶心,“凡是与妹果搞好关系的果夹都富起来了”,他引用老村长这句的目的是想警示钩一旦脱了就是灭顶之灾。而我,最厌恶的就是这个老村长,他的每一句话都是遗祸人类的剧毒品,但他却成了今天文化人顶礼膜拜的圣人。我前不久写过一篇《圣渣已作古,劣渣在狂奔》,老村长在大多数人眼中是圣人,但在我心中却是一圣渣而已。
中国有句俗语,跟着好人学好人,跟着巫婆跳大神。与妹果搞好关系不是为了向妹果学好,仅仅是为了利用妹果让自己富起来。好人富起来对谁都好,但坏人富起来呢?对好人真叫一个灭顶之灾。老村长一家确实富起来了,大大小小的村长都富起来了,与村长关系好的村民也富起来了,只可惜,害苦了普通村民,好人几乎毫无生机。这样的钩再不脱,还叫好人怎么活?
坏人坏果一旦富起来了,对世界究竟有多糟糕?一般人根本无从知晓。
叙利亚内战已经9年有余,为什么阿萨德能挺得如此硬朗?得有钱啊,钱从哪儿来?没有土豪劣绅源源不断供给行吗?俄罗斯大军进驻叙利亚,普帝的钱从哪儿来?我不多说。伊朗被制裁成狗熊了,还能在中东呼风唤雨,钱从哪儿来?我不多说。委内瑞拉早就民不聊生了,但马杜罗依然坚如磐石,钱从哪里来?我不多说。小邻金被全面封堵成猴子了,但胖哥就是不认怂,钱从哪儿来?我不多说全世界恶棍果夹的天眼和控民系统都堪称世界一流,谁装的?钱从哪里来?我不多说。(都是从中国来的。)
也许窝囊废总统天天都在挠着脑袋纳闷,“为什么我的制裁总是没效果呢?”我说啊,如果不脱钩,他怎么制裁也不会有效果用中国人的血和生命,换取美国的美钞,强大了自己的恶,不但推高了长岛的房价,还撑起了全世界的恶。这就是老村长的大智慧,名叫韬光养晦,这样的大智慧岂是窝囊废总统能幡然醒悟的?
脱有什么不好?脱当然不好。但是,我们一定要明白一个道理,脱,对食物链两端的人没什么影响。对顶端的没影响,原先该吃山珍海味的,脱不脱都一样,再怎么脱,贵州怀仁镇照样灯火通明昼夜不息。对底端也没影响,脱不脱他们都是一个月很难吃一顿肉,脱了对他们来说也许是缩短了生活差距。脱了真正影响最大的是中产,也就是脱之前天天吃肉的,一旦脱了,他们的感受是最强烈的。
只要脱了,在救肚子和救房子之间就再也没得选择,房价必然雪崩。什么是中产?就是有房有车的人嘛,他们一般都不会把现金存银行,他们都会找收益最大的东西投资。房价一旦雪崩,中产阶层才会突然醒悟自己有多穷,这有什么不好?我最讨厌的就是这界的中产,什么鸡都不可能叫醒他们。如果不脱,他们永远都会躺在钩钩上岁月静好。只有脱,他们才会感觉到痛,痛觉是最好的清醒剂。只有让大多数中产在痛觉中醒来,然后,才有然后。
米兰昆德拉:罪恶的纸度并非由罪人建立,而是恰恰由那些确信已经找到了通往天堂之路的积极分子所建立。
如果不脱,中产一直都会沾沾自喜,他们都是读书人,他们的成功在于媚上欺下,他们的幸福源自比下有余。他们是起跑线上的赢家,他们是帝吧出征的主力,他们是《战狼》的观众,他们是广场舞的舞者,他们是红歌会的麦霸,他们是中果模式的传教士,他们是中果故事的演说家。总之,现在的所谓中产,就像70年前奔向延河的积极分子一样,他们的光辉理想就是积极追求进步,他们的专业是顺势而为,他们的信仰是永远站在石头一边。
脱,对于好人来说,更没有什么大不了的。什么是好人,就是海明威所言“内心严肃”的人,也正如莎士比亚所言“理性战胜欲望”的人。好人的好就在于不是靠物质繁华装扮自己的幸福人生,而是以高贵灵魂填满自己的悲悯情怀。不脱,好人本就很俭朴,脱,大不了筚路蓝缕。我相信,好人最希望的是脱。因为只有脱才可能摧枯拉朽,因为只有脱才可能脱胎换骨。

年代向錢看 美/中從地球打到太空! G7聯合挺香港,反送中!中國通膨,苦日子!中企 假財報地雷炸鍋!

年代向錢看 解放軍入香港鎮壓反送中?!江澤民、曾慶紅借香港鬥習?!美蘇軍備競賽重演!人民幣再貶!外資看壞中國


如何给一台单网口电脑安装openwrt软路由系统 为你的网络插上翅膀

mac上,利用全局代理程序ip2socks翻墙

$
0
0
首先在你的本地机器上,访问https://help.github.com/cn/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent ,添加ssh public key到你的github账号。

git clone git@github.com:FlowerWrong/ip2socks.git
cd ip2socks
git submodule update --init --recursive
(这一步耗时一个小时,我是挂着wireguard来操作的。)
cmake .
make
(会在当前目录下,生成可执行文件ip2socks)

yudeMacBook-Air:ip2socks brite$ ./ip2socks -h
options:
-d --debug
-h --help
-c --config
yudeMacBook-Air:ip2socks brite$ wget https://github.com/FlowerWrong/ip2socks/raw/master/scripts/config.darwin.example.yml
yudeMacBook-Air:ip2socks brite$ cp config.darwin.example.yml config.darwin.yml
yudeMacBook-Air:ip2socks brite$ cat config.darwin.yml
ip_mode: tun # tun or tap, default tun
dns_mode: udp # tcp or udp, default tcp
socks_server: 127.0.0.1
socks_port: 1080

remote_dns_server: 8.8.8.8
remote_dns_port: 53
local_dns_port: 53 # if you use your own local dns server, eg: pdnsd, dnsmasg, this is upstream dns server.
relay_none_dns_packet_with_udp: false
#custom_domian_server_file: ./scripts/block.conf;./scripts/custom_domain_server.conf;./scripts/dnsmasq-china-list/google.china.conf;./scripts/dnsmasq-china-list/apple.china.conf;./scripts/dnsmasq-china-list/accelerated-domains.china.conf; # if multi, split with ';'
gw: 10.0.0.1 # gateway of lwip netif
addr: 10.0.0.2 # ip of lwip netif
netmask: 255.255.255.0 # netmask of lwip netif
after_start_shell: './scripts/darwin_setup_utun.sh'
before_shutdown_shell: './scripts/darwin_down_utun.sh'
(你的mac机器上,需开着纸飞机
yudeMacBook-Air:ip2socks brite$ nano scripts/darwin_setup_utun.sh
(把47.52.95.27改为你的vps ip)
yudeMacBook-Air:ip2socks brite$ sudo ./ip2socks -c config.darwin.yml
(不要关闭此terminal)

然后,
sudo networksetup -setdnsservers "Wi-Fi" 127.0.0.1

cd ~/CrappyDNS-by-nekolab/src && sudo ./crappydns --listen 127.0.0.1 --port 53 --good-dns tcp://8.8.8.8:53,tcp://8.8.4.4:53
(关于CrappyDNS的用法,详见https://briteming.blogspot.com/2019/08/crappydnsdns.html )

这样,你的整台mac就处于翻墙状态了。

项目地址:
https://github.com/FlowerWrong/ip2socks/
https://github.com/FlowerWrong/ip2socks/issues/10

Swift 语言指南

$
0
0
这份指南汇集了Swift语言主流学习资源,并以开发者的视角整理编排。
这份指南汇集了 Swift 语言主流学习资源,并以开发者的视角整理编排。对于精选项目及文章,可直接访问《Swift 项目精选》和《Swift 文章精选》。
GitHub:ipader/SwiftGuide| 网站:http://dev.swiftguide.cn欢迎开发者一起维护,或反馈/投稿
@SwiftLanguage更新于 2016-1-5,更新内容详见 Issue 43。往期更新回顾详见《收录周报

目录


Swift 文档

1. Welcome to Swift

苹果针对 Swift 开发者官方文档入口。其中包括: Swift 概括Swift Programming LanguageUsing Swift with Cocoa and Objective-C

2. Swift Programming Language

3. Using Swift with Cocoa and Objective-C

4. App Extension Programming Guide

5. HomeKit Developer Guide

  • HomeKit 开发指南(中文版)(By @CocoaChina):“内容包括:简介、启用HomeKit、创建Home布局、创建Homes和添加Accessories、观察HomeKit数据库的变化、访问服务和特性、测试HomeKitApp、创建动作集(Action Sets)和触发器(Triggers)以及用户管理”。

6. Swift Blog - Apple Developer

"值得一提的是,Swift 博客是苹果官方网站的第一个 Blog,这也代表了苹果对开发者和消费者的态度正变得越来越开放。"
译文译者原文
-N/ANew Playgrounds Part 2 - Sources
Swift Nullability and Objective-CBanningsNullability and Objective-C
-N/ANew Playgrounds
-N/AThe as! Operator
Swift 1.2 和 Xcode 6.3 beta@老码团队Swift 1.2 and Xcode 6.3 beta
-N/ANew Swift Development Courses Available on iTunes U
Swift REPL:一切皆可重定义@MichealGengRedefining Everything with the Swift REPL
Swift 中的 NSMethodSignature 怎么了?@pockry What Happened to NSMethodSignature?
Swift REPL 入门介绍-Introduction to the Swift REPL
可失败构造器@DevTalkingFailable Initializers
N/ABuilding Your First Swift App Video
通过 Playground 展示一些编码模式@DevTalkingPatterns Playground
Swift 中 Optional 类型的使用案例分析:valuesForKeys-Optionals Case Study:valuesForKeys
Swift 中的访问控制与 protected-Access Control and protected
Swift 中的值类型和参照类型-Value and Reference Types
WWDC 2014大会中的 Playground 大炮气球示例-Balloons
在 Swift 中构建布尔类型-Boolean
Swift 中的文件和初始化-Files and Initialization
在 Swift 中使用 C 语言的指针-Interacting with C Pointers
*Swift 新特性 - 访问控制(文档版)-Access Control

7. iOS Human Interface Guidelines


Swift 教程

旧版内容过于庞杂,不再维护,取而代之的是《Swift 文章精选》。P.S. 需要查阅旧版内容的同学,详见Swift 教程(旧版)

Swift 项目

旧版内容过于庞杂,不再维护,取而代之的是《Swift 项目精选》。P.S. 需要查阅旧版内容的同学,详见Swift 项目(旧版)

Swift 网站


相关工具

1. 开发工具

  • Xcode 6 beta下载:苹果应用集成开发环境。支持 C/C++, Objective C, Swift 等。不用购买开发者计划,直接下载。
  • Textmate:Mac OS X 上一个可高度自定义的编辑器,尤其在我想做出一个快速改变但又不想等待 Xcode 加载的时候。该工具目前已经开源
  • Mou:OS X 上一款 Markdown 的编辑器。非常适用于编写自述文件、变更日志以及其他方面的内容。作者:罗晨
  • Sublime Text ($):Mac OS X 上另一款非常受欢迎的轻量级,可高度自定义的编辑器。
  • RunSwift:正在犹豫是否入手苹果电脑开始一段 Swift 编程旅程的同学们,或仅仅为了试验一段简单 Swift 代码又懒得打开 Xcode,可以试试这款 Web 版 Swift 编译环境 RunSwift。
  • InfinitApps - Bezel:“嫌 Xcode 6 目前提供的 Watch 模拟器不够直观?Bezel 是一个用于视觉预览 WatchKit 所开发程序效果的小工具,前提是你安装了 xScope 软件(Mac端)或 xScopeMirror(iPhone端)。 By @WatchKit开发
  • Markdown -> Playground:该开源项目可将内含有 Swift 代码的 Markdown 自动转换为 Xcode Playgrounds 文件。喜欢用 Markdown 编辑的同学很激动吧。P.S. 这款工具写于 NodeJS,原因作者有交待。
  • iOS/Mac Autolayout Constraints:这个工具不错,很直观,布局时可以省不少工夫。推荐者:@荧星诉语
  • 在线生成 AppStore 审核用截图:便捷的生产力工具。免费,易操作,可自定义。

2. 代码管理

  • GitHub:声望日盛的资源分享之地。�
  • GitHub for Mac:一个设计的非常美观的 git 客户端,不能取代你从命令行获得的所有功能,但使用起来非常简单。
  • GitCafe:GitCafe is a source code hosting service based on version control system Git。国内的代码托管服务,基于 Git,值得一提的是最近也推出了和 GitHub Pages 类似的服务 Gitcafe Pages。因为是在国内,所以相比较 GitHub 有速度优势,在网络环境差的情况下也许可以作为 GitHub 的备用。
  • Bitbucket:国外的代码托管服务,不同于 GitHub 的是,Bitbucket 可以免费建立 private 项目。
  • Git:分布式版本控制系统和源码管理系统,其优点是:快和简单易用。对于新手来说,可在此查看免费电子书籍。

3. Xcode 插件

4. 管理工具

  • HomeBrew:OS X 上非常出色的包管理工具。
  • Transmit ($):一个Mac OS X 上 FTP 客户端,有着非常漂亮的用户界面和有用的功能。

5. 调试工具

6. 参考文章

  • iOS 开发工具:"这是我们多篇 iOS 开发工具系列篇中的一篇,此前的文章比如:那些不能错过的 Xcode 插件,iOS 开发者有价值的工具集,iOS/OS X 开发:各种工具快到碗里来!,App 原型设计工具使用心得(上)& App 原型设计工具使用心得(下),你用哪种工具进行 iOS app 自动化功能测试?iOS 开发者必知的 75 个工具" By @CocoaChina
  • IOS 各种调试技巧豪华套餐:讲得很细。对于初学 Xcode 开发的同学值得参考,对于有经验的同学可以略过。作者:@David戴未来
  • 详解Xcode 6的视图调试:教程非常实用,值得学习。另外,教程选用的开源项目(jessesquires/JSQMessagesViewController)也很经典。来源:Ray Wenderlich,译者:@CocoaChina翻译组
from https://github.com/litesuits/SwiftGuide

Awesome-Blockchain-cn

$
0
0
收集所有区块链(BlockChain)技术开发相关资料,包括Fabric和Ethereum开发资料。

 Awesome

收集所有区块链(BlockChain)技术开发相关资料
Please read the contribution guidelines before contributing. 请在为本项目贡献信息前仔细阅读 操作指南
欢迎到Issues提交区块链相关项目,我们会第一时间处理。 提交的项目格式如下: 项目名称:XXXXX 相关介绍: XXXXXX

CONTENTS

INTRO 介绍

Started 入门

Ethereum 以太坊进阶

Fabric 联盟链进阶

TUTORIAL 教程

BitCoin 比特币

Ethereum 以太坊

Fabric 联盟链

Videos 视频

PROJECT 项目

Chain 区块链底层

  • Metaverse原界链源码
  • EOS EOS链源码
  • BYTOM比原链源码
  • NEO NEO链源码
  • CITA cita联盟链的底层源码
  • Nervos公链 Nervos CKB 的底层源码
  • 比特币0.1最原始的比特币代码
  • Quorum来自JP Morgan基于Go-Ethereum数据隐私加强的以太坊实现
  • FISCO-BCOS来自金链盟的聚焦金融行业的区块链底层平台
  • Presto-Ethereum以太坊增加Presto的SQL访问能力
  • IPFS IPFS的GO语言实现 原理

SDK 工具包

  • Remix在线以太坊编译器
  • Truffle以太坊Dapp开发脚手架
  • Zeppelin用于编写安全的以太坊合约框架
  • Web3j以太坊官方Web3轻量级java SDK
  • Embark以太坊Dapp开发框架,支持IPFS、Whisper及Orbit调用
  • Web3Swift一个Web3的swift SDK
  • Porosity反编译以太坊智能合约工具
  • Solidity-Coverage检测Solidity代码覆盖
  • Caliper hyperledger区块链性能测试工具
  • Composer官方可视化Fabric应用开发框架
  • Cakeshop来自JP Morgan的以太坊可视化管理工具

Research 最新研究

  • eWASM让以太坊支持WebAssembly
  • FSolidM可视化智能合约生成工具 源码
  • Maian以太坊智能合约漏洞查找工具
  • Oyente以太坊智能合约分析工具
  • Blockbench区块链性能测试工具
  • Zokrates以太坊使用zkSNARKS工具包(实验用)
  • libsnark zkSNARKS C++库

DOCUMENT 资料

BitCoin 比特币

Ethereum 以太坊

Fabric 联盟链

APPLICATION 应用

Explorer 链浏览

Wallet 钱包

Exchange 交易所

Game 游戏

IM 通信

Social 社会

Cross Chain 跨链

Token 代币

Awesome Ethereum

以太坊相关详细开发资源收集

Awesome Fabric

Fabric联盟链相关详细开发资源收集。

from  https://github.com/chaozh/awesome-blockchain-cn

美国完成对华3000亿美元商品的关税手续 外资手机生产商从中国部分撤出

$
0
0
美中两国贸易摩擦升级,美方已完成对中国商品加征3000亿美元关税的决定,已由文件形式固定,并公布在联邦登记册,相关措施将于9月1日和12月15日实施。美国互联网巨头谷歌据报从夏季开始,将在中国生产的智能手机生产线转移至越南。另外,《人民日报》就美国增加中国货品关税,再度发文。
美国《联邦公报》最新发布美国贸易代表办公室确认计划,将于9月1日与12月15日对中国出口到美国的货品加征额外15%关税。表明特朗普总统早前表示对中国增加新关税的决定,已经由文件形式固定,并进入实施阶段。特朗普的决定是在中国对原产于美国的价值750亿美元进口商品加征额外关税后做出的。
中国官方《人民日报》本周四发布评论员钟声的文章,指美国最新一轮对华关税威胁究竟意味着什么?美国公众心里有一本账——冲击美国消费市场,影响范围扩大到“周末喝的精酿啤酒,到演奏的乐器,再到孩子读的书”……所有的分析都表明,美方一些人妄称“加征关税效果巨大”,“美国消费者对加征关税分文未花”,完全脱离了现实感。文章写道,美方一些人最近妄言“同中国脱钩更好”,但来自清醒者的分析都说,同中国脱钩意味着美国衰退。文章警告,贸易战没有赢家。
另据《日经亚洲评论》周三报道,据知情人士透露,谷歌与合作伙伴合作,今年夏天开始在越南北部北宁省将一家旧诺基亚工厂转变成生产Pixel手机的工厂。三星在十年前曾在该省开发智能手机供应链,因此谷歌将拥有一支经验丰富的员工团队。消息人士透露,谷歌打算最终将其大部分美国硬件生产转移到中国境外,包括Pixel手机及其广受欢迎的智能扬声器。
成本和关税成外资撤离主因
目前,近七成的谷歌智能手机在美国市场出售,分析人士认为,谷歌将手机生产过程转移至越南,应该是出于商业考虑。因为越南的生产成本较中国低,而且避过了美国关税。旅居美国的学者杨占青也这样认为,他对自由亚洲电台说:“像谷歌这一类国际型大公司撤离中国是明智的。在中国,无论是珠三角还是长三角,居住成本高,逐年上升,相应的劳动力成本也就越来越高。对企业来说,哪里成本低就去哪里投资,越南、泰国等地肯定不会有那么高的房价、房租,对工人、工厂来说,成本都低很多。”
越南生产线将成为谷歌推动智能手机市场增长的关键部分。消息人士告诉《日经亚洲评论》,谷歌计划今年出货约800万至1000万部智能手机,比一年前增加一倍。《日经》援引知情人士称,根据目前的计划,谷歌将在今年年底之前将部分Pixel 3A手机生产从中国转移到越南。其智能扬声器的部分生产可能会转移到泰国。但新产品开发和硬件的初始生产仍将在中国。
山东大学毕业的金融学者司令对本台说,谷歌将智能手机生产线转移到越南,从经济学推拉力理论而言,越南的“拉力”非常明显:“它的拉力是非常明显的,就是能够缩短工人的培训时间,节省工人的劳动成本和培训成本。谷歌把他手机生产业务转移到越南,它的推力也是非常明显的,这种推力来自于中国不再具有以前的那种生产优势。而现在随着中美贸易战逐步升级,这种优势已经不复存在。”
司令认为,谷歌作为手机安卓系统的发明者,他的撤离势必影响其他的手机制造商纷纷效仿。从而掀起手机产业撤离中国的海啸。特朗普曾多次公开劝谕中方最好尽快达成经贸协议,赶在美国企业开始撤离中国之前,这样还能留住美企。(可惜,习猪头哪里听得进去
特朗普的建议?)
Viewing all 20523 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>