GFW

GFW

翻墙服务器选择

电信最好选择 CN2 服务器,例如阿里云香港或新加坡。

翻墙路由器

技术栈:VPN / Shadowsocks + 中国IP路由直连 + DNS国内外域名解析分离

VPN / Shadowsocks

VPN 可以直接修改系统路由表实现全局翻墙。

Shadowsocks 需要配合 ss-redir 等。

中国IP路由直连

有两种方案:

  1. 纯路由表方案: 例如 chnroutes
  2. iptables + ipset 方案

参考 中国 IP

DNS

  • 8.8.8.8, 8.8.4.4

DNS 国内外域名解析分离

同样有几种方案:

  1. ChinaDNS: 原理是同时向国内和国外 DNS 服务器发送解析请求。国内 DNS 直连,国外 DNS 通过 VPN 或代理访问。如果国内 DNS 返回的结果也是 国内 IP 并且不是被 GFW 污染的结果,则采用此结果;否则采用国外 DNS的解析结果。这种方案在实际使用中存在很多问题。
  2. dnsmasq-china-list,实际效果最好的方案。最好不定期更新一下国内网站域名列表。

代理

代理工作在 TCP / HTTP 层。包括 Socket5 / http / https(spdy) 代理等。常见的代理方案包含服务器端和客户端,之间通过加密方式通信以规避审查;客户端对本地 App 提供一个 Socket5 代理(默认通常监听 127.0.0.1:1080)。

Server

优化 / 加速

使用代理时,可以搭配一些网络优化工具以获得更高速度。

  • 锐速 : 单边 tcp 加速,效果拔群。已停止维护,只支持旧的Linux内核版本。
  • bbr : (推荐。部署最简单)tcp阻塞控制算法。效果与锐速类似。较新版Linux内核已包含,可直接启用。
  • kcptun : 基于UDP的双向加速。需要同时安装服务器端和客户端。V2Ray 内置了 kcpkun。
  • udp2raw-tunnel : 将 udp "转换"(伪装)为 raw socket (可模拟为Encrypted UDP/FakeTCP/ICMP)已绕过某些ISP对UDP的QoS。常用于配合 kcptun 使用 (注: 新版的 kcptun 已经内置了 --tcp 用 raw socket 模拟 tcp 包的选项)。
  • UDPspeeder : 在不稳定的网络环境下加速 tcp / udp / icmp。通过将其封装为含有冗余信息的udp流量以对抗(补偿)网络丢包。
  • net-speeder : (不推荐)多倍发包以对抗网络丢包。不推荐因为收益低开销(多耗费的流量)大。优点是对环境要求低,支持OpenVZ;不仅支持代理,同样支持VPN流量加速。

Client

Windows

Shadowsocks-win

  • 在同一端口同时提供 Socket5 和 http 代理。
  • 支持自动设置系统代理 / PAC 设置。支持从GFWList自动生成PAC / 自定义 PAC。

一些命令行(cli)工具默认支持使用 HTTP_PROXY 环境变量设置 Http 代理,格式为 http://localhost:1080

使用 Proxifier 这个小软件可以强制不支持系统代理设置的软件走 Socket5代理,shadowsocks-win 内置了(仅自用的) proxifier。

iOS

  • kitsunebi : V2ray 核心(兼容主流加密方式的 shadowsocks 服务器端)。
  • Surge

Android

代理规则

代理规则一般工作在 TCP / HTTP 层。配合 Shadowsocks 等 Socket5 / HTTP 代理使用。

通常有“黑名单”和“白名单”两种方式。由于中国宽带连接大部分国外网站速度普遍很慢等原因,推荐使用“白名单”模式。

  • 黑名单(Blacklist): 只有指定的(被墙)网站才通过代理连接。GFWList (AutoProxy 规则在线地址)。
  • 白名单(Whitelist): 除了指定的(中国)网站以外,所有网站都通过代理连接。MatcherAny/whitelist.pacpexcn/daily/../whitelist.pac (PAC规则在线地址)。

Chrome 推荐使用 SwitchyOmega 扩展。

iOS 上的一些代理 App 如 Kitsunebi, Surge 等使用自己私有的规则格式,推荐使用在线规则:

ConnersHua/Profiles (Surge、Quantumult、Kitsunebi、Shadowrocket、Pepi(ShadowRay)、Surfboard、Clash 的配置规则文件)

透明代理

透明代理通常跑在路由器(或虚拟机、软路由等)上,这种方式与在路由器上直接跑 VPN 相比更为复杂,而且有一些限制。但是由于实现了 TCP split,通常性能比 VPN 好很多,并且可以很方便实现基于域名的分流规则(VPN的翻墙方案通常只能实现基于IP分流;如果想实现基于域名分流需要配合 dnsmasq ipset 之类,效果和可靠性都不理想。)。

参考:clash

TCP (iptables DNAT)

需要代理程序支持,clash 内置支持;shadowsocks 需要跑个单独的 ss-redir。然后把 TCP 请求重定向到代理程序的本地透明代理转发监听端口。需要先添加局域网地址白名单规则。

iptables -t nat -A PREROUTING -d 0/8 -j RETURN
iptables -t nat -A PREROUTING -d 127/8 -j RETURN
iptables -t nat -A PREROUTING -d 10/8 -j RETURN
iptables -t nat -A PREROUTING -d 169.254/16 -j RETURN
iptables -t nat -A PREROUTING -d 172.16/12 -j RETURN
iptables -t nat -A PREROUTING -d 192.168/16 -j RETURN
iptables -t nat -A PREROUTING -d 224/4 -j RETURN
iptables -t nat -A PREROUTING -d 240/4 -j RETURN
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 1234

REDIRECT 即 DNAT 到 127.0.0.1 的本地对应端口。ss-redir 收到 DNAT 后的 TCP 包后,通过 netfilter 的 conntrac 机制接口获取TCP包原始 dst 的 IP和端口,然后通过代理服务器向其发起连接即可。

以上仅对于路由器“转发”的TCP流量生效。如果需要拦截路由器本机程序发出的TCP连接,还需要在 -t nat OUTPUT 里加同样规则。

本地透明代理监听端口程序

  • clash: 内置支持
  • ss-redir: 配合 ss-local 使用
  • REDSOCKS2: REDSOCKS2 与 ss-redir 类似,但可以使用任何 Socket 5 代理作为后端实现透明代理。(新版的REDSOCKS2好像还直接支持 shadowsocks 协议,这样跑一个 REDSOCKS2 = ss-local + ss-redir)。

UDP (iptables TPROXY)

由于Linux conntrac 机制 和/或 udp 协议限制,在 Linux 里如果 udp 包做了 DNAT,无法获取到其原始的 dst 信息。所以无法通过 DNAT 来透明代理 udp 流量。

如果需要透明转发 udp 流量,需要安装 iptables 的 TPROXY 内核模块(openwrt package: iptables-mod-tproxy),然后在 -t mangle 的 PREROUTING 里加规则。

关于 TPROXY:

TPROXY 是在 Kernel 2.6.28 引进的全新的透明代理技术,TPROXY 的原理完全不同于传统的 DNAT 方式。TPROXY 实现透明代理的特点:

  • 不对 IP 报文做改动(不做 DNAT);
  • 应用层可用非本机 IP 与其它主机建立 TCP/UDP 连接;
  • Kernel 通过 iptables-tproxy 和策略路由将非本机流量送到 socket 层;
  • 仍需要通过其它技术拦截到做代理的流量到代理服务器(WCCP 或 PBR(策略路由))。

TPROXY 挂在 -t mangle PREROUTING 里,可以透明代理所有路由器收到并转发的 udp 流量。因为不做 DNAT,因此可以将它应用于 ss-redir 的 UDP 透明代理,这样就不需要担心数据包原目的地址和原目的端口的问题了。 但是,由于 Netfilter 限制,TPOXY 只能放在 -t mangle PREROUTING 链,不能挂在 -t mangle OUTPUT 里,所以只能透明代理来自内网的 UDP 流量,对于本机发出的 UDP 则无能为力。但似乎有 workaround 能够解决:

iptables -t mangle -A OUTPUT -p udp -j MARK --set-mark 1

由于 Netfilter 的特性,在 OUTPUT 链打标记会使相应的包重路由到 PREROUTING 链上,所以只要在 -t OUTPUT 里打标记,然后再 -t mangle PREROUTING 里正常做 TPROXY 即可。(信息来源与网上,未验证)

iptables -t mangle -N SS-UDP

iptables -t mangle -A SS-UDP -d 0/8 -j RETURN
iptables -t mangle -A SS-UDP -d 127/8 -j RETURN
iptables -t mangle -A SS-UDP -d 10/8 -j RETURN
iptables -t mangle -A SS-UDP -d 169.254/16 -j RETURN
iptables -t mangle -A SS-UDP -d 172.16/12 -j RETURN
iptables -t mangle -A SS-UDP -d 192.168/16 -j RETURN
iptables -t mangle -A SS-UDP -d 224/4 -j RETURN
iptables -t mangle -A SS-UDP -d 240/4 -j RETURN

iptables -t mangle -A SS-UDP -d SS_SERVER_IP -j RETURN

iptables -t mangle -A SS-UDP -p udp -j TPROXY --tproxy-mark 0x2333/0x2333 --on-ip 127.0.0.1 --on-port 60080
iptables -t mangle -A PREROUTING -p udp -s 192.168/16 -j SS-UDP

UDP 透明代理后端端口监听程序同样可以使用 Clash, ss-redir 或 REDSOCKS2。

DNS

因为 GFW DNS 污染存在,必须通过代理服务器解析某些国外网站 IP。由于上面提到的 TPROXY UDP 透明代理无法适用于路由器本机 outcoming 流量的限制,因为通常局域网里的 DNS 服务器就是路由器本身,需要在路由器上跑专门的 DNS 程序来解决这个问题,有几种方式:

  • dnsforwarder, DNS Proxy 或其它类似支持设置上游 TCP / DoT (DNS over TLS / DNS over HTTPS) DNS 服务器地址的程序,配合TCP透明代理。一般配合 dnsmasq 使用。在 dnsmasq 里设置 CN 和中国域名直接走本地 DNS (114.114.114.114),其他域名通过本地 dnsforwarder 监听的端口解析。(为什么不直接只使用 dnsmasq ? 因为 dnsmasq 不支持设置 tcp / DoT 协议的上游 DNS 服务器。为什么不只使用 dnsforwarder ? 因为 dnsmasq 各种功能更强大。)

  • SmartDNS: 这个功能很强大并且性能很好。具有 dnsmasq 里 DNS 相关的大部分功能(分域名指定DNS解析,域名本地解析结果,ipset等都支持),并且支持 TCP / DoT 解析功能。对于大部分DNS相关的需求应该都可以单独使用,无需再配合 dnsmasq。但不能完全替换路由器里的 dnsmasq,因为 dnsmasq 还有 DHCP 等功能无法替代。

  • 通过 ss-tunnel 在本机上跑一个 UDP 端口转发。将本地某个 udp 端口通过 ss 隧道转发到 8.8.8.8:53 端口(需要 ss-server 开启 -u UDP 转发支持)。一般同样配合 dnsmasq 使用。

  • 在路由器上额外跑个 VPN (tun 设备),将 dst 是 udp 53 的 DNS 查询请求通过 VPN 转发。增加额外的复杂性和故障点。

  • clashFake IP 模式:Fake-IP 模式在客户端发起DNS请求时会立即返回一个保留地址(198.18.0.1/16),同时向上游DNS服务器查询结果,如果判定返回结果为污染或者命中代理规则(这种情况下本地不再发起DNS请求),则直接发送域名至代理服务器进行远端解析 (Socks5 CONNECT domain.com)。此时客户端立即向Fake-IP发起的请求会被快速响应。这种思路非常独特,并且保证通过代理访问的网站都直接通过代理服务器远端解析域名(避免了访问一些部署了全球CDN的网站因为DNS解析请求和访问请求可能使用不同代理而可能导致的速度不理想)。

  • clash 自带了一个(支持 DoT 的) DNS 服务器。Redir-Host (传统) 模式下会通过 Dns Over TLS 向 tls://8.8.8.8:853 解析域名来避免 DNS 污染。(相当于集成了 dnsforwarder 的功能)。Clash for Windows 还有其他机制在绝大多数情况下可以避免DNS污染。具体说明:当 clash 规则配置了DNS服务器 (dns - nameserver, dns - fallback) 并且其他设备使用clash 的DNS服务器 (dns - listen)进行解析时,Clash 工作流程(Redir-host 模式)如下:从nameserver和fallback里的DNS进行并发请求,并且选取nameserver中最先响应的结果作为基准, 使用GEOIP判断此IP的所属区域,如果属于国内(CN)或保留地址则直接响应给客户端。其他情况则把fallback中的结果响应给客户端

  • Chinadns 等工具,无需代理服务器,本地直连 8.8.8.8 解析域名并返回无污染的 DNS 结果。其原理有多种手段,本质上是利用 GFW 对于 DNS 解析协议栈与端到端协议栈差异所产生的漏洞。例如:(注意:随着GFW不断升级,以下方法基本上全部失效或不能稳定可用。目前仍有人维护的 OpenWrt版本Chinadns 只是提供智能DNS分流,仍然需要配合代理以避免GFW的DNS污染)
    • 过滤掉过快返回的DNS响应(ChinaDNS):因为被污染的域名都在国外,解析结果返回所需时间不可能少于某个阈值;
    • 在全部DNS请求包中构造指针(ChinaDNS):GFW以前无法识别DNS请求中的一些指针压缩方式,但少数国外递归DNS服务器(如8.8.8.8)却可以;
    • 过滤掉GFW返回的固定IP:之前GFW返回的污染IP是固定的几十个国外IP;
    • TCP查询国外DNS:GFW之前只污染使用UDP的DNS查询;
    • 使用非标准端口查询国外DNS:GFW之前只污染对国外DNS服务器标准53端口的查询;
    • 丢弃国内 IP DNS 返回的国外 IP 解析结果。因为 GFW 之前曾对国外域名的污染仅返回国外IP。

Last update: 2021-03-03 09:03:44 UTC