#!/usr/bin/env bash # After applying this script, the system iptables should be like this: #┌─────────┐ ┌─────────┐ #│ │ PREROUTING rule1* INPUT │ │ #│ │ │ │ │ #│ │ ┌─────────────────────────────────┼───┐ ┌────────────────────┐ │ │ #│ │ │ │ │ /───\ │ │ │ │ #│ │ │ ┌───┐ ┌─────────┐ ┌──────┐ ┌─┴─┐ │ / \ │ ┌──────┐ ┌──────┐ │ │ │ #│ ├──┤►│raw├─►│conntrack├─►│mangle├─►│nat├─┼──────►──────┤►│mangle├─►│filter├─┤►│ │ #│ │ │ └───┘ └─────────┘ └┬─────┘ └───┘ │ \ / │ └──────┘ └──────┘ │ │ │ #│ │ │ │ │ \─┬─/ │ │ │ │ #│ │ └──────────────────────┼──────────────┘ │ └────────────────────┘ │ │ #│ │ │ │ │ │ #│ │ ┌──┴──┐ ┌──────────┐ │ │ │ #│ │ │clash│ │ │ │ │ │ #│ │ └─────┘ │ ┌──────┐ │ │ │ │ #│ │ │ │mangle◄─┼─────────┘ │ │ #│ Network │ │ └──┬───┘ │ ┌───────────┐ │ Local │ #│Interface│ │ │ │ FORWARD │clash_local│ │ Process │ #│ │ │ ┌──▼───┐ │ └─┬─────────┘ /───\ │ │ #│ │ ┌───────────────┼─┤filter│ │ │ / \ │ │ #│ │ │ │ └──────┘ │ ├───rule3* ◄─┤ │ #│ │ │ │ │ │ \ / │ │ #│ │ │ └──────────┘ ├───rule2* \─┬─/ │ │ #│ │ │ │ │ │ │ #│ │ ┌────────────┼────┐ ┌──────────────────────┼───────────────────┼────┐ │ │ #│ │ │ │ │ ───── │ │ │ │ │ │ #│ │ │ ┌───┐ ┌───▼──┐ │ / \ │ ┌──────┐ ┌───┐ ┌───┴──┐ ┌─────────┐ ┌▼──┐ │ │ │ #│ │◄─┼─┤nat│◄─┤mangle│◄├──────┼─┤filter│◄─┤nat│◄─┤mangle│◄─┤conntrack│◄─┤raw│ │ │ │ #│ │ │ └───┘ └──────┘ │ \check/ │ └──────┘ └┬──┘ └──────┘ └─────────┘ └───┘ │ │ │ #│ │ │ │ ───── │ │ │ │ │ #│ │ └─────────────────┘ └────────────┼──────────────────────────────────┘ │ │ #│ │ POSTROUTING │ OUTPUT │ │ #│ │ ┌──────┴──┐ │ │ #└─────────┘ │clash_dns│ └─────────┘ # └─────────┘ # # *rule1: iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 1053 # *rule2: iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner clash -j RETURN # *rule3: iptables -t mangle -A OUTPUT -p udp -m owner --uid-owner clash -j RETURN # set -ex options: # -e Exit immediately if a command exits with a non-zero status # -x Print commands and their arguments as they are executed. set -ex # ENABLE ipv4 forward sysctl -w net.ipv4.ip_forward=1 # ROUTE RULES ip rule add fwmark 666 table 666 ip route add local 0.0.0.0/0 table 666 dev lo ################################## ## hijack the dns query traffic ## ################################## # Redirect all dns query traffic from LAN to port 1053 # Later clash will return a fake ip in 198.18.0.1/16 # 转发从局域网收到的所有 DNS 查询流量到 1053 端口 # 此操作会导致所有 DNS 请求全部返回虚假 IP(fake ip 198.18.0.1/16) iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 1053 # same for ipv6 # ipv6 同样配置 ip6tables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 1053 # Redirect dns query traffic from all local processes (except owned by user clash) to port 1053 # Later clash will return a fake ip in 198.18.0.1/16 # 转发从所有本机进程(除去uid为clash的进程)收到的所有 DNS 查询流量到 1053 端口 # 此操作会导致所有 DNS 请求全部返回虚假 IP(fake ip 198.18.0.1/16) iptables -t nat -N clash_dns iptables -t nat -A OUTPUT -p udp --dport 53 -j clash_dns iptables -t nat -A clash_dns -m owner --uid-owner clash -j RETURN iptables -t nat -A clash_dns -p udp -j REDIRECT --to-ports 1053 # same for ipv6 # ipv6 同样配置 ip6tables -t nat -N clash_dns ip6tables -t nat -A OUTPUT -p udp --dport 53 -j clash_dns ip6tables -t nat -A clash_dns -m owner --uid-owner clash -j RETURN ip6tables -t nat -A clash_dns -p udp -j REDIRECT --to-ports 1053 ############################## ## config for `clash` chain ## ############################## # `clash` chain to manipulate traffic from LAN # `clash` 链负责处理来自 局域网 的流量 iptables -t mangle -N clash # skip traffic to LAN or reserved address # reference: # https://en.wikipedia.org/wiki/List_of_assigned_/8_IPv4_address_blocks # https://en.wikipedia.org/wiki/Private_network#IPv4 # 目标地址为局域网或保留地址的流量跳过处理 # 保留地址参考: # 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 # https://zh.wikipedia.org/wiki/%E4%B8%93%E7%94%A8%E7%BD%91%E7%BB%9C # IANA - Local Identification iptables -t mangle -A clash -d 0.0.0.0/8 -j RETURN # IANA - Loopback iptables -t mangle -A clash -d 127.0.0.0/8 -j RETURN # IANA - Private Use 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 # IPv4 Link-Local Addresses iptables -t mangle -A clash -d 169.254.0.0/16 -j RETURN # Multicast iptables -t mangle -A clash -d 224.0.0.0/4 -j RETURN # Future Use iptables -t mangle -A clash -d 240.0.0.0/4 -j RETURN # Forward all the other traffic to port 7893 and set tproxy mark # 其他所有流量转向到 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 # Append the `clash` chain to PREROUTING to enable it # 将 `clash` 链加在PREROUTING链后面使其生效 iptables -t mangle -A PREROUTING -j clash #################################### ## config for `clash_local` chain ## #################################### # `clash_local` chain to manipulate traffic from local process # `clash_local` 链负责处理本机的本地进程发出的流量 iptables -t mangle -N clash_local # rerouting traffic from nerdctl container # 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 # Don't touch traffic to LAN and reserved address # 跳过内网流量 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 # set mark for local traffic # clash_local set mark for the traffic from local process, # the marked traffic will come back to PREROUTING chain. # 为本机发出的流量打 mark # clash_local 链会为本机流量打 mark, 打过 mark 的流量会重新回到 PREROUTING 上 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 # Don't touch traffic from a serving port # 跳过来自服务端口的流量 # https web server # iptables -t mangle -I OUTPUT -p tcp --sport 443 -j RETURN # transmission # iptables -t mangle -I OUTPUT -p tcp --sport 51413 -j RETURN # Don't touch traffic from the user `clash` to prevent looping # 跳过 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 # Append the `clash_local` chain to OUTPUT to enable it # 将 `clash_local` 链加在 OUTPUT 链后面使其生效 iptables -t mangle -A OUTPUT -j clash_local ####################### ## unimportant staff ## ####################### # fix ICMP(ping) # This step does NOT make the ping result validate # (clash doesn't support forwarding ICMP), it just makes ping have a result. # set --to-destination to a accessable address. # 修复 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 #iptables -t nat -A OUTPUT -p icmp -d 198.18.0.0/16 -j DNAT --to-destination 127.0.0.1