Prerequisite
- comzyh/clash
- Open sourced tun support
- Debian 10
- Proxy provider
- Shadowsocks or whatever supported by clash, Dler Cloud for example
Steps
1 Setup Tun
TUN_NAME=clash0
sudo ip tuntap add mode tun user clash name $TUN_NAME
sudo ip link set $TUN_NAME up
# or sudo ifconfig utun up
2 Setup iptables
iptables -t mangle -N CLASH # Create Clash Chain
iptables -t mangle -A CLASH -d 0.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 127.0.0.0/8 -j RETURN
iptables -t mangle -A CLASH -d 169.254.0.0/16 -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 224.0.0.0/4 -j RETURN
iptables -t mangle -A CLASH -d 240.0.0.0/4 -j RETURN
# ipset can be enabled optionally.
# iptables -t mangle -A CLASH -m set --match-set CN dst -j RETURN
iptables -t mangle -A CLASH -j MARK --set-xmark 129
iptables -t mangle -A PREROUTING -j CLASH # have traffic come to the CLASH chain
# if you need to have the local machine(the machine clash is running on) traffic to go through clash TUN
# note: you should have clash running under the user `clash', see below systemd script
# iptables -t mangle -A OUTPUT -m owner --uid-owner clash -j RETURN
# iptables -t mangle -A OUTPUT -j CLASH
3 Setup route
ip route add default dev $ table 129
ip rule add fwmark 129 $TUN_NAME lookup 129
4 Checkpoint 1
At this stage, all the traffic routed by this machine will be tagged with fwmark 129
and redirected to $TUN_NAME.
Feel free to change the number 129
to whatever you like.
5 Setup clash
To have clash handle the traffic on $TUN_NAME, we need to setup clash properly.
5.1 Install
Download the binary from https://github.com/comzyh/clash/releases and put it under /usr/bin/clash
. For example:
curl -sL https://github.com/comzyh/clash/releases/download/20210310/clash-linux-amd64 -o /usr/bin/clash
5.2 systemd script
Note The user should match that one speficied in the iptable rules above.
cat /lib/systemd/system/[email protected]
[Unit]
Description=Clash
After=network.target
[Service]
Type=simple
User=%i
Restart=always
ExecStart=/usr/bin/clash -d /home/wtf/clash
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
[Install]
WantedBy=multi-user.target
systemctl enable clash@clash
5.3 clash config
Add this section to your existing config.yaml
Note
The device url should be dev://$TUN_NAME
tun:
enable: true
stack: system
device-url: dev://clash0
# dns-hijack:
# - 10.0.0.5
5.4 Start clash
systemctl enable clash@clash
6 Checkpoint 2
At this stage, you should be able to use this machine as the gateway for you LAN devices.
Note
Don't forget to enable ipv4_forwarding on your machine. In case you need help: https://linuxconfig.org/how-to-turn-on-off-ip-forwarding-in-linux
7 Misc
7.1 Setup ipset
Sometimes you don't really want to route all traffic to the gateway, and that can be done by setting up ipset
. By doing this, you can either to have the iptables RETURN all the traffic that is matching a particular ipset or only mark the traffic when it matches.
In my case, I want to have all the China Mainland traffic to be going though the clash tun, so I'll have the script below to update the ipset everyday.
cat /etc/cron.daily/update-ipset.sh
IPSET_BIN=/usr/sbin/ipset
$IPSET_BIN -L CN-new > /dev/null 2>&1
if [ $? -eq 0 ]; then
$IPSET_BIN destroy CN-new
fi
$IPSET_BIN create CN-new hash:net
curl -sL http://www.ipdeny.com/ipblocks/data/countries/cn.zone | xargs -n1 $IPSET_BIN -A CN-new
$IPSET_BIN -L CN > /dev/null 2>&1
if [ $? -ne 0 ]; then
$IPSET_BIN create CN hash:net
fi
$IPSET_BIN swap CN-new CN
$IPSET_BIN destroy CN-new
And have my mangle table:
iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
RETURN udp -- anywhere anywhere udp dpts:4096:65535
RETURN tcp -- anywhere anywhere tcp dpts:8192:65535
CLASH all -- anywhere anywhere
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain CLASH (1 references)
target prot opt source destination
MARK all -- anywhere anywhere match-set CN dst MARK set 0xc0
7.2 Persistence
iptables/ipset
You'll want to use
iptables-persistent
/ipset-persistent
to have iptables/ipset persistenceroute and tun dev
Use Debian network configuration, an example:
cat /etc/network/interfaces | grep -A 20 clash0 auto clash0 iface clash0 inet manual pre-up ip tuntap add mode tun user clash name $IFACE up ip link set dev $IFACE up post-up ip route add default dev $IFACE table 192 post-up ip rule add fwmark 192 lookup 192 down ip link set dev $IFACE down post-down ip link del dev $IFACE post-down ip route del default dev $IFACE table 192 post-down ip rule del fwmark 192 lookup 192
Summary
You should now be ready to setup the IP of the above machine to be the default gateway on you DHCP service.
Best practive is having a static IP for the above machine and always have a backup gateway in case something went wrong with the second gateway.
All the script sample above are for my personal note and demo purpose only - make sure you understand it and feel free to make any change accordingly.