291

使用 clash 和路由表實現透明代理

 3 years ago
source link: https://h-cheung.gitlab.io/zh-tw/post/%E4%BD%BF%E7%94%A8_clash_%E5%92%8C%E8%B7%AF%E7%94%B1%E8%A1%A8%E5%AE%9E%E7%8E%B0%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文內容如有錯誤,請在評論區指出

需要的工具

要進行全局代理,常見的方式是轉發到特定端口、使用 tun 虛擬設備和使用 TPROXY。clash 有 redir port 可以直接轉發實現代理,但是隻支持 TCP,IPv6 的支持也尚未合併。TPROXY 是 v2ray-core 的推薦方式。而另一種方式則是 tun。本文介紹的是使用 tun 的方式

要使用這種方式,首先需要一個使用 tun 轉發流量的工具,目前 clash 主線並不支持 tun,clash 作者有一個支持 tun 的閉源版本,另外 comzyh 有一個支持 tun 的分支,性能不錯,穩定性一般。然後有一個通用的工具 tun2socks,穩定性較好但性能一般。後兩者都不錯。

comzyh 的 clash 分支

go-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。

然後設置路由規則

ip route replace default dev <tun name> table <route table id>
ip rule add fwmark <fwmark id> lookup <route table id>

把有特定 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 也一樣):

iptables -t mangle -N <chain name>
iptables -t mangle -F <chain name>
iptables -t mangle -I OUTPUT -j <chain name>

然後在規則鏈上編寫規則即可,需要打標記走代理就 -j MARK --set-mark <fwmark id>,需要繞過就 -j RETURN,一般建議先寫繞過規則,最後無條件地打標記。注意一定要繞過 clash 的流量(建議 uid/gid 或 cgroup)

使用 cgroup net_cls

cgroup 是 Linux 內核的一個功能,這裏需要用到它的 net_cls 子系統。使用起來簡單,我們首先運行以下命令創建一個組:

mkdir -p /sys/fs/cgroup/net_cls/<cgroup name>
echo <cgroup id> > /sys/fs/cgroup/net_cls/bypass_proxy/net_cls.classid
chmod 666 /sys/fs/cgroup/net_cls/<cgroup name>/tasks

上述命令可以在開機時運行

這樣,如果一個進程的 pid 在 /sys/fs/cgroup/net_cls/<cgroup name>/tasks 中,它就會被 iptables 的 -m cgroup --cgroup <cgroup id> 規則匹配到,並且這些進程的子進程 pid 會自動被添加。如果對安全比較敏感,你可以對該文件進行適當的權限控制。

可以使用一個腳本,以它作爲 wrapper 來運行需要的命令

#!/bin/bash
echo $$ > /sys/fs/cgroup/net_cls/<cgroup name>/tasks
exec "$@"

單獨轉發 DNS

與 v2ray 不同,clash 不能通過其規則把流量轉到 clash 的內置 DNS,且 clash 不支持 sni 解析域名,需要內置 DNS 反查域名。

因此,需要使用 nat 表把 DNS 流量轉發到 clash 的 DNS 端口,對 UDP 53 端口的流量,設置適當的繞過規則過濾後,-j REDIRECT --to-ports <clash dns port> 即可。

tun 工具配置

comzyh 的 clash 分支需要在配置文件中設置以下內容

tun:
  enable: true
  device-url: dev://<tun name>

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


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK