Clash透明代理实现方式总结

什么是透明代理呢?

透明代理,全程为透明代理网关,透明就是感觉不到,透明代理就是感觉不到自己使用代理。 至于什么网站地址可以使用代理这样的规则判断都交给了网关去处理。

因此,网关实际上起着流量转发的作用,将需要使用代理的请求中转到代理客户端处理,将不需要使用代理的请求正常处理。

在什么位置实现透明代理?

正常家庭上网的模式是这样的:

              Phone/PC/Pad
                    |
                  1 |
                    |
            +-------v-------+      2      +--------+
            |               |------------->        |
            |  WiFi 路由器   |             |  树莓派 |
            |               <-------------|        |
            +------+--+-----+      3      +--------+
                   |  |
                3.1|  | 3.2
                   |  +---------->  China LAN
                   v
               +---+---+
               | Proxy |
               +---+---+
                   |
                   |
                   v
             Internet WAN

这里的树莓派是可选设备,如果你打算实现旁路由

  1. 透明代理需要接管局域网中所有流量,因此路由器是最适合实现透明代理的位置(这也是为何很多人要刷改版第三方固件原因)。
  2. 路由器的硬件类型和配置千差万别,实现代理软件类型也不同,因此不是所有透明代理实现方案都通用,我们会选择比较通用的方案介绍。

实现透明代理的两个关键点:

  1. DNS转发: 决定哪些域名需要更换更合理的DNS服务器处理。
  2. 代理转发: 决定哪些域名使用代理转发请求。

常见DNS转发服务端:

  • Dnsmasq : 通常路由器默认的DNS服务端,是一个开源的轻量级DNS转发和DHCP、TFTP服务器,使用C语言编写。优点:资源占用低,易于配置。支持的平台包括Linux、BSD、Smoothwall、IP-Cop、floppyfw、Firebox、LEAF、Freesco, fli4l、CoyoteLinux及Android等,并且在dd-wrt、openwrt路由器系统中也有使用,dnsmasq源码地址
  • Clash : Clash内置的比较丰富的DNS转发规则,使用Go语言编写,同时也是一个支持多协议的代理客户端,一个软件具备了透明代理的两个关键功能。

DNS客户端代理客户端的种类比较多,这里无法一一列举。

透明代理的核心是规则Linux系统自带的iptables可以使用Forwarding转发规则来自定义网络请求规则。

iptables实现透明代理

路由器环境:

  • CPU架构:Armv7l 不支持VPF,因此要使用Armv5可执行程序。
  • 路由器固件: KS梅林380版本
  • Clash选择版本: Clash Premium v1.7.0(2021.09.07版)
  • dnsmasq版本: 路由器自带。

实现透明代理大致过程:

  • iptables的作用:
  1. 转发80443目标端口请求到Clash的 1080 端口进行代理中转。
  2. 转发UDP的53端口到Clash1053 端口进行DNS解析

Clash服务的作用:

  1. 根据URL规则判断是直连还是代理透传
  2. 根据DNS规则判断使用哪个DNS服务器进行DNS解析。

接下来,详细介绍每个服务的操作。

iptables配置规则

大部分Linux系统都支持iptables,包括路由器。

因此此方法通用所有Linux系统。

这里要完成的内容:

  1. 定义链表 TCP 端口为80/443 请求转发给 Clash服务的redir-port端口。
  2. 定义链表 UDP 端口为53 请求转发给 Clash服务的 dns.listen端口。

这里没有什么复杂的ipset规则定义,因为规则都交给了Clash实现配置。如果你没有使用Clash,那么这里你需要使用到了ipset定义URL规则保证只转发需要走代理的TCP请求通过Clash处理。

设置iptables命令如下:


lan_ipaddr="192.168.50.1"   # 局域网路由器IP地址
dns_port="1053"             # DNS转发服务端口
redir_port="3333"           # 透明代理转发端口

iptables -t nat -N CLASH_TCP_RULE
iptables -t nat -F CLASH_TCP_RULE

iptables -t nat -A PREROUTING -p tcp -s ${lan_ipaddr}/16 -j CLASH_TCP_RULE
# Fake-IP 规则添加
iptables -t nat -A OUTPUT -p tcp -d 198.18.0.0/16 -j REDIRECT --to-port ${redir_port}


# 本地地址请求不转发
iptables -t nat -A CLASH_TCP_RULE -d 10.0.0.0/8 -j RETURN
iptables -t nat -A CLASH_TCP_RULE -d 127.0.0.0/8 -j RETURN
iptables -t nat -A CLASH_TCP_RULE -d 169.254.0.0/16 -j RETURN
iptables -t nat -A CLASH_TCP_RULE -d 172.16.0.0/12 -j RETURN
iptables -t nat -A CLASH_TCP_RULE -d ${lan_ipaddr}/16 -j RETURN

# 服务端口3333接管HTTP/HTTPS请求转发
iptables -t nat -A CLASH_TCP_RULE -s ${lan_ipaddr}/16 -p tcp -m multiport --dport 80,443 -j REDIRECT --to-ports ${redir_port}

# 转发DNS请求到端口 dns_port 解析
iptables -t nat -N CLASH_DNS_RULE
iptables -t nat -F CLASH_DNS_RULE
iptables -t nat -A CLASH_DNS_RULE -p udp -s ${lan_ipaddr}/16 --dport 53 -j REDIRECT --to-ports $dns_port
iptables -t nat -I OUTPUT -p udp --dport 53 -j CLASH_DNS_RULE
iptables -t nat -A PREROUTING -p udp -s ${lan_ipaddr}/16 --dport 53 -j CLASH_DNS_RULE

当不想使用iptables规则时,当然要记得清理掉不需要的配置。否则路由器不知道会出现什么问题。

清除iptables规则的命令如下:

# 清理iptables规则
iptables -t nat -D PREROUTING -p tcp -s ${lan_ipaddr}/16 -j CLASH_TCP_RULE
iptables -t nat -F CLASH_TCP_RULE
iptables -t nat -X CLASH_TCP_RULE

iptables -t nat -D PREROUTING -p udp -s ${lan_ipaddr}/16 --dport 53 -j CLASH_DNS_RULE
iptables -t nat -D OUTPUT -p udp --dport 53 -j CLASH_DNS_RULE
iptables -t nat -F CLASH_DNS_RULE
iptables -t nat -X CLASH_DNS_RULE

就这样,我们实现DNS请求和HTTP/HTTPS协议请求都转发给了Clash的工作。

下一步,我们就要操作Clash完成规则的配置。

Clash配置规则

分两部分说明:

  1. DNS请求转发配置
  2. 代理转发规则配置

DNS请求转发配置

Clash支持两种DNS模式:

  • redir-host: 传统的DNS转发模式,局域网根据规则查询DNS请求获取真实IP地址。
  • fake-ip: 伪造IP模式,内部DNS查询得到的是伪造IP段的某个地址,局域网使用伪IP与Clash通信,Clash会根据伪IP找到真实IP使用SOCKS代理进行通信。

下面是详细的DNS配置:


# 透明代理开启DNS
dns:
  enable: true
  ipv6: false
  listen: 0.0.0.0:1053
  enhanced-mode: redir-host       # redir-host or fake-ip
  # fake-ip-range: 198.18.0.1/16    # Fake IP addresses pool CIDR
  use-hosts: true                 # lookup hosts and return IP record
  nameserver:
    - 119.29.29.29      # DNSpod DNS 17ms
    - 223.5.5.5         # 阿里 19ms
  # 提供 fallback 时,如果GEOIP非 CN 中国时使用 fallback 解析
  fallback:
    - tls://8.8.8.8:853         # Google DNS over TLS 50ms
    - tls://8.8.4.4:853         # cloudflare DNS over TLS 50ms
    - https://1.1.1.1/dns-query # cloudflare DNS over HTTPS
    - https://dns.google/dns-query # Google DNS over HTTPS

  # 强制DNS解析使用`fallback`配置
  fallback-filter:
    # true: CN使用nameserver解析,非CN使用fallback
    geoip: true
    # geoip设置为false时有效: 不匹配`ipcidr`地址时会使用`nameserver`结果,匹配`ipcidr`地址时使用`fallback`结果。
    ipcidr:
      - 240.0.0.0/4

切换使用redir-hostfake-ip模式也很简单, 修改enhanced-mode: fake-ip,去掉fake-ip-range前面的#号。
然后在iptables中增加如下语句:

# Fake-IP 规则添加
iptables -t nat -A OUTPUT -p tcp -d 198.18.0.0/16 -j REDIRECT --to-port ${redir_port}

其中的${redir_port}需要替换成Clash转发端口例如3333

DNS解析问题已经解决啦! 到这里就解决了DNS污染问题。但还有很多问题导致我们访问的网站链接被重置或无法访问。

因此,接下来,还要使用Clash转发代理进行HTTP/HTTPS请求转发。

Clash代理规则配置

我们之前已经使用iptables80、443端口请求(也就是HTTP/HTTPS)请求都转发给3333端口(Clash的转发端口)。

因此,我们只需要在Clash中设置规则,决定哪些请求走代理转发,哪些直接转发。这些规则在Clash中配置起来非常简单。

我们看下Clash Premium版本支持的rule-providers配置内容:

# 专业版支持 rule-providers
rule-providers:
  reject:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/reject.txt"
    path: ./ruleset/reject.yaml
    interval: 86400

  icloud:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/icloud.txt"
    path: ./ruleset/icloud.yaml
    interval: 86400

  apple:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/apple.txt"
    path: ./ruleset/apple.yaml
    interval: 86400

  google:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/google.txt"
    path: ./ruleset/google.yaml
    interval: 86400

  proxy:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/proxy.txt"
    path: ./ruleset/proxy.yaml
    interval: 86400

  direct:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/direct.txt"
    path: ./ruleset/direct.yaml
    interval: 86400

  private:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/private.txt"
    path: ./ruleset/private.yaml
    interval: 86400

  gfw:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/gfw.txt"
    path: ./ruleset/gfw.yaml
    interval: 86400

  greatfire:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/greatfire.txt"
    path: ./ruleset/greatfire.yaml
    interval: 86400

  tld-not-cn:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/tld-not-cn.txt"
    path: ./ruleset/tld-not-cn.yaml
    interval: 86400

  telegramcidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/telegramcidr.txt"
    path: ./ruleset/telegramcidr.yaml
    interval: 86400

  cncidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/cncidr.txt"
    path: ./ruleset/cncidr.yaml
    interval: 86400

  lancidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/[email protected]/lancidr.txt"
    path: ./ruleset/lancidr.yaml
    interval: 86400

# 黑名单模式,命中规则使用代理
rules:
  - PROCESS-NAME,v2ray,DIRECT
  - PROCESS-NAME,xray,DIRECT
  - PROCESS-NAME,naive,DIRECT
  - PROCESS-NAME,trojan,DIRECT
  - PROCESS-NAME,trojan-go,DIRECT
  - PROCESS-NAME,ss-local,DIRECT
  - PROCESS-NAME,privoxy,DIRECT
  - PROCESS-NAME,leaf,DIRECT
  - PROCESS-NAME,v2ray.exe,DIRECT
  - PROCESS-NAME,xray.exe,DIRECT
  - PROCESS-NAME,naive.exe,DIRECT
  - PROCESS-NAME,trojan.exe,DIRECT
  - PROCESS-NAME,trojan-go.exe,DIRECT
  - PROCESS-NAME,ss-local.exe,DIRECT
  - PROCESS-NAME,privoxy.exe,DIRECT
  - PROCESS-NAME,leaf.exe,DIRECT
  - PROCESS-NAME,Surge,DIRECT
  - PROCESS-NAME,Surge 2,DIRECT
  - PROCESS-NAME,Surge 3,DIRECT
  - PROCESS-NAME,Surge 4,DIRECT
  - PROCESS-NAME,Surge%202,DIRECT
  - PROCESS-NAME,Surge%203,DIRECT
  - PROCESS-NAME,Surge%204,DIRECT
  - PROCESS-NAME,Thunder,DIRECT
  - PROCESS-NAME,DownloadService,DIRECT
  - PROCESS-NAME,qBittorrent,DIRECT
  - PROCESS-NAME,Transmission,DIRECT
  - PROCESS-NAME,fdm,DIRECT
  - PROCESS-NAME,aria2c,DIRECT
  - PROCESS-NAME,Folx,DIRECT
  - PROCESS-NAME,NetTransport,DIRECT
  - PROCESS-NAME,uTorrent,DIRECT
  - PROCESS-NAME,WebTorrent,DIRECT
  - PROCESS-NAME,aria2c.exe,DIRECT
  - PROCESS-NAME,BitComet.exe,DIRECT
  - PROCESS-NAME,fdm.exe,DIRECT
  - PROCESS-NAME,NetTransport.exe,DIRECT
  - PROCESS-NAME,qbittorrent.exe,DIRECT
  - PROCESS-NAME,Thunder.exe,DIRECT
  - PROCESS-NAME,ThunderVIP.exe,DIRECT
  - PROCESS-NAME,transmission-daemon.exe,DIRECT
  - PROCESS-NAME,transmission-qt.exe,DIRECT
  - PROCESS-NAME,uTorrent.exe,DIRECT
  - PROCESS-NAME,WebTorrent.exe,DIRECT
  - DOMAIN,clash.razord.top,DIRECT
  - DOMAIN,yacd.haishan.me,DIRECT
  - RULE-SET,private,DIRECT
  - RULE-SET,reject,REJECT
  - RULE-SET,direct,DIRECT
  - RULE-SET,cncidr,DIRECT
  - RULE-SET,lancidr,DIRECT
  - RULE-SET,tld-not-cn,PROXY
  - RULE-SET,gfw,PROXY
  - RULE-SET,greatfire,PROXY
  - RULE-SET,telegramcidr,PROXY
  - RULE-SET,google,PROXY
  - RULE-SET,proxy,PROXY
  - RULE-SET,apple,PROXY
  - RULE-SET,icloud,DIRECT
  - MATCH,DIRECT

看着有点长,但是与直接将每个域名都写进来相比已经很短了。

使用rule-provider的好处就是,规则可以定时更新,而且配置内容很规整。至于使用白名单还是黑名单方式就是最后的规则集设置了。

  • 黑名单模式,意为 「只有命中规则的网络流量,才使用代理」 ,适用于服务器线路网络质量不稳定或不够快,或服务器流量紧缺的用户。通常也是软路由用户、家庭网关用户的常用模式。
  • 白名单模式,意为 「没有命中规则的网络流量,统统使用代理」 ,适用于服务器线路网络质量稳定、快速,不缺服务器流量的用户。

这里的配置方式采用了黑名单规则方式

白名单最后的配置如下:

rules:
    ...
    ...
    ...
  - RULE-SET,private,DIRECT
  - RULE-SET,reject,REJECT
  - RULE-SET,icloud,DIRECT
  - RULE-SET,apple,DIRECT
  - RULE-SET,google,DIRECT
  - RULE-SET,proxy,PROXY
  - RULE-SET,direct,DIRECT
  - RULE-SET,telegramcidr,PROXY
  - GEOIP,,DIRECT
  - GEOIP,CN,DIRECT
  - MATCH,PROXY

如果你想看配置示例,这里可以查看一个支持代理订阅源的配置 config.yaml

完成透明代理配置

到这里,我们就完成了透明代理的所有工作。

再来回顾一下透明代理的实现过程:

  • 配置iptables转发代理规则: 实现HTTP/HTTPS请求转发到Clash转发端口3333
  • 配置iptables转发DNS规则: 实现DNS请求转发到Clash内置DNS服务1053端口。
  • 配置Clash代理转发规则: 根据URL规则集决定哪些URL通过代理转发请求。

希望通过这样的介绍,可以帮到你。

结尾:安全的DNS协议类型

通常普通DNS查询是不安全的,可以被别人跟踪记录的,为了解决安全问题就产生了DoHDoT等协议。

  • DoH(DNS over HTTPS): 一个进行安全化的域名解析方案。其意义在于以加密的HTTPS协议进行DNS解析请求,避免原始DNS协议中用户的DNS解析请求被窃听或者修改的问题(例如中间人攻击)来达到保护用户隐私的目的。Google及Mozilla基金会正在测试此协议,提高网络安全性。 支持DoH的公共DNS列表
  • DoT(DNS over TLS): 通过传输层安全协议(TLS)来加密并打包域名系统(DNS)的安全协议。此协议旨在防止中间人攻击与控制DNS数据以保护用户隐私。RFC 7858RFC 8310定义了DNS over TLS支持DoT的公共DNS列表
  • dns2socks: 这个不是协议,而是将DNS查询请求通过SOCKS代理做了个转发,如果SOCKS代理隧道是安全的,那么这个过程就相对安全一些。到了隧道的另一端(代理服务端)之后是否安全还是看代理服务端是否使用了DoHDoT协议进行转发。