I. Notes

In this article, the intranet CIDR is 192.168.0.0/16, that is, all address segment rules and configurations are processed for the current intranet CIDR; clash fake-ip’s CIDR is 198.18.0.0/16, please do not write it wrongly as 192, it is 198.

II. Installing Clash

The transparent proxy method used in this article does not depend on TUN, so it does not matter if it is an enhanced version, please try to use the latest version if possible.

1
2
3
4
5
6
7
8
9
# x86 用户请自行替换
wget https://github.com/Dreamacro/clash/releases/download/v1.9.0/clash-linux-armv8-v1.9.0.gz

# 解压
gzip -d clash-linux-armv8-v1.9.0.gz

# 安装到系统 PATH
chmod +x clash-linux-armv8-v1.9.0
mv clash-linux-armv8-v1.9.0 /usr/bin/clash

Create a dedicated clash user.

1
useradd -M -s /usr/sbin/nologin clash

Writing the Systemd configuration file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat > /lib/systemd/system/clash.service <<EOF
[Unit]
Description=Clash TProxy
After=network.target

[Service]
Type=simple
User=clash
Group=clash
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
Restart=on-failure

ExecStartPre=+/usr/bin/bash /etc/clash/clean.sh
ExecStart=/usr/bin/clash -d /etc/clash
ExecStartPost=+/usr/bin/bash /etc/clash/iptables.sh

ExecStopPost=+/usr/bin/bash /etc/clash/clean.sh

[Install]
WantedBy=multi-user.target
EOF

III. Adjusting the configuration

In this article, Clash configuration files and scripts are stored in the /etc/clash directory, for Clash configuration files, we will highlight the key configurations, please copy the full configuration from the official Wiki: https://github.com/Dreamacro/clash/wiki/configuration#all-configuration-options

3.1. Port configuration

Please keep the port configuration as default as possible, if you need to adjust the port, please change the port in the related script (TProxy):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 注释掉 port 端口配置, 使用 mixed-port
#port: 7890

# 注释掉 socks-port 端口配置, 使用 mixed-port
#socks-port: 7891

# 注释掉 redir-port 端口配置, 因为全部采用 TProxy 模式
#redir-port: 7892

# TProxy 的透明代理端口
tproxy-port: 7893

# mixed-port 端口将同时支持 SOCKS5/HTTP
mixed-port: 7890

# 允许来自局域网的连接
allow-lan: true

# 绑定到所有接口
bind-address: '*'

3.2. DNS Configuration

Please enable DNS in Clash configuration, and use fake-ip mode, sample configuration is as follows:

1
2
3
4
5
6
7
8
dns:
  enable: true
  listen: 0.0.0.0:1053
  ipv6: false
  default-nameserver:
    - 114.114.114.114
    - 8.8.8.8
  enhanced-mode: fake-ip

3.3. Firewall rules

To ensure that the firewall rules are not broken, this article uses script brute force, if the host has other iptables control programs, it is recommended to execute them manually and persist them with tools such as iptables-persistent;

/etc/clash/iptables.sh : responsible for adding iptables rules at boot time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env bash

set -ex

# ENABLE ipv4 forward
sysctl -w net.ipv4.ip_forward=1

# ROUTE RULES
ip rule add fwmark 666 lookup 666
ip route add local 0.0.0.0/0 dev lo table 666

# clash 链负责处理转发流量 
iptables -t mangle -N clash

# 目标地址为局域网或保留地址的流量跳过处理
# 保留地址参考: https://zh.wikipedia.org/wiki/%E5%B7%B2%E5%88%86%E9%85%8D%E7%9A%84/8_IPv4%E5%9C%B0%E5%9D%80%E5%9D%97%E5%88%97%E8%A1%A8
iptables -t mangle -A clash -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A clash -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A clash -d 169.254.0.0/16 -j RETURN

iptables -t mangle -A clash -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A clash -d 240.0.0.0/4 -j RETURN

# 其他所有流量转向到 7893 端口,并打上 mark
iptables -t mangle -A clash -p tcp -j TPROXY --on-port 7893 --tproxy-mark 666
iptables -t mangle -A clash -p udp -j TPROXY --on-port 7893 --tproxy-mark 666

# 转发所有 DNS 查询到 1053 端口
# 此操作会导致所有 DNS 请求全部返回虚假 IP(fake ip 198.18.0.1/16)
iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 1053

# 如果想要 dig 等命令可用, 可以只处理 DNS SERVER 设置为当前内网的 DNS 请求
#iptables -t nat -I PREROUTING -p udp --dport 53 -d 192.168.0.0/16 -j REDIRECT --to 1053

# 最后让所有流量通过 clash 链进行处理
iptables -t mangle -A PREROUTING -j clash

# clash_local 链负责处理网关本身发出的流量
iptables -t mangle -N clash_local

# nerdctl 容器流量重新路由
#iptables -t mangle -A clash_local -i nerdctl2 -p udp -j MARK --set-mark 666
#iptables -t mangle -A clash_local -i nerdctl2 -p tcp -j MARK --set-mark 666

# 跳过内网流量
iptables -t mangle -A clash_local -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A clash_local -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A clash_local -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A clash_local -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A clash_local -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A clash_local -d 169.254.0.0/16 -j RETURN

iptables -t mangle -A clash_local -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A clash_local -d 240.0.0.0/4 -j RETURN

# 为本机发出的流量打 mark
iptables -t mangle -A clash_local -p tcp -j MARK --set-mark 666
iptables -t mangle -A clash_local -p udp -j MARK --set-mark 666

# 跳过 clash 程序本身发出的流量, 防止死循环(clash 程序需要使用 "clash" 用户启动) 
iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner clash -j RETURN
iptables -t mangle -A OUTPUT -p udp -m owner --uid-owner clash -j RETURN

# 让本机发出的流量跳转到 clash_local
# clash_local 链会为本机流量打 mark, 打过 mark 的流量会重新回到 PREROUTING 上
iptables -t mangle -A OUTPUT -j clash_local

# 修复 ICMP(ping)
# 这并不能保证 ping 结果有效(clash 等不支持转发 ICMP), 只是让它有返回结果而已
# --to-destination 设置为一个可达的地址即可
sysctl -w net.ipv4.conf.all.route_localnet=1
iptables -t nat -A PREROUTING -p icmp -d 198.18.0.0/16 -j DNAT --to-destination 127.0.0.1

/etc/clash/clean.sh : responsible for cleaning up iptables rules before/ after starting/stopping (brute force cleaning)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env bash

set -ex

ip rule del fwmark 666 table 666 || true
ip route del local 0.0.0.0/0 dev lo table 666 || true

iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X clash || true
iptables -t mangle -X clash_local || true

3.4. Final directory structure

After all the configurations are written, the directory structure is as follows:

1
2
3
4
5
root@openrpi # ❯❯❯ tree -L 1 /etc/clash
/etc/clash
├── clean.sh
├── config.yaml
└── iptables.sh

Finally, you need to fix the /etc/clash directory permissions, because Clash writes to other files when it starts :

1
chown -R clash:clash /etc/clash

IV. Startup and Testing

If all the configuration and files are installed correctly, you can boot directly from Systemd:

1
2
3
4
5
# 启动
systemctl start clash

# 查看日志
jouranlctl -fu clash

If the start-up is successful, then the intranet device will set the gateway to the current Clash machine to complete the transparent proxy; if the Clash machine is stable enough, you can also directly fill in the gateway issued by the DHCP setting of the intranet router as the Clash machine IP in one step (Clash machine needs to use static IP).