使用 clash 和路由表實現透明代理
本文內容如有錯誤,請在評論區指出
需要的工具
要進行全局代理,常見的方式是轉發到特定端口、使用 tun 虛擬設備和使用 TPROXY。clash 有 redir port 可以直接轉發實現代理,但是隻支持 TCP,IPv6 的支持也尚未合併。TPROXY 是 v2ray-core 的推薦方式。而另一種方式則是 tun。本文介紹的是使用 tun 的方式。
要使用這種方式,首先需要一個使用 tun 轉發流量的工具,目前 clash 主線並不支持 tun,clash 作者有一個支持 tun 的閉源版本,另外 comzyh 有一個支持 tun 的分支,性能不錯,穩定性一般。然後有一個通用的工具 tun2socks,穩定性較好但性能一般。後兩者都不錯。
需要的知識
基本的路由表、iptables 操作
設置轉發路由
首先需要使用 ip tuntap add <tun name> mode tun user <tun user>
創建一個 tun 設備,並使用 ip link set <tun name> up
啓用。
然後設置路由 ip address replace <tun address> dev <tun name>
,tun address 取一個不常用的 IP 段,比如 kr328 的腳本中使用 172.31.255.253/30,又比如 go-tun2socks 默認的 10.255.0.1/24。
然後設置路由規則
|
|
把有特定 fwmark 標記的流量路由到 tun 其中 fwmark 號和 route 表號可以自行設定(不要和其他的規則重複)。
然後用 iptables 在 mangle 表上,把需要代理的流量打上 fwmark 標記,使用 -j MARK --set-mark <fwmark id>
即可
繞過部分流量
利用 iptables 支持的豐富規則,我們可以靈活地繞過各種流量,列出幾個比較常用的:
-m owner --uid-owner <username or uid>
匹配某個用戶的流量,類似的還有--gid-owner
-p <'tcp', 'udp' or 'icmp'>
匹配某種類型流量--dport <port num>
匹配目的端口,類似的--sport
匹配源端口,需要和-p tcp
等連用-d <network name, hostname, subnet(IP CIDR) or IP>
匹配目的網絡/主機名/子網/IP-m set --match-set <ipset name> <'dst' or 'src'>
匹配 ipset,可以用於簡化規則,ipset 用法自行搜索-m cgroup --cgroup <cgroup id>
匹配 cgroup
有較多規則時可以創建規則鏈,並把 OUTPUT 或 PREROUTING 鏈中的流量轉入該鏈(ip6tables 也一樣):
|
|
然後在規則鏈上編寫規則即可,需要打標記走代理就 -j MARK --set-mark <fwmark id>
,需要繞過就 -j RETURN
,一般建議先寫繞過規則,最後無條件地打標記。注意一定要繞過 clash 的流量(建議 uid/gid 或 cgroup)
使用 cgroup net_cls
cgroup 是 Linux 內核的一個功能,這裏需要用到它的 net_cls 子系統。使用起來簡單,我們首先運行以下命令創建一個組:
|
|
上述命令可以在開機時運行
這樣,如果一個進程的 pid 在 /sys/fs/cgroup/net_cls/<cgroup name>/tasks
中,它就會被 iptables 的 -m cgroup --cgroup <cgroup id>
規則匹配到,並且這些進程的子進程 pid 會自動被添加。如果對安全比較敏感,你可以對該文件進行適當的權限控制。
可以使用一個腳本,以它作爲 wrapper 來運行需要的命令
|
|
單獨轉發 DNS
與 v2ray 不同,clash 不能通過其規則把流量轉到 clash 的內置 DNS,且 clash 不支持 sni 解析域名,需要內置 DNS 反查域名。
因此,需要使用 nat 表把 DNS 流量轉發到 clash 的 DNS 端口,對 UDP 53 端口的流量,設置適當的繞過規則過濾後,-j REDIRECT --to-ports <clash dns port>
即可。
tun 工具配置
comzyh 的 clash 分支需要在配置文件中設置以下內容
|
|
go-tun2socks 用以下命令啓動
tun2socks -tunName <tun name> -proxyServer <clash socks server> -tunAddr <tun address> -tunGw <tun gateway> -tunMask <tun mask> -tunPersist -blockOutsideDns
選一個不常用的 subnet,並取該 subnet 內兩個不同地址作爲 tun gateway 和 tun address。
比如要使用 172.31.255.253/30 子網。則 tun mask 爲 255.255.255.252,tun gateway 可以用 172.31.255.253,tun address 可以用 172.31.255.254,默認參數對應的子網是 10.255.0.1/24