使用 clash docker 做透明网关

之前一直使用 OpenWrt 旁路由的方式来翻墙,但 OpenWrt 本身不够稳定,并且我长期处于只使用 OpenWrt 其中的一个插件的状态,所以决定开一台虚拟机来体验下使用 Clash 作为透明网关
先给出(从同事那借来的)配置:
version: "3"
services:
# Enable ip_forward - https://askubuntu.com/a/311054
# For Ubuntu Server, you also need to disable systemd-resolved
# 1. sudo systemctl stop systemd-resolved
# 2. sudo systemctl disable systemd-resolved
clash:
image: dreamacro/clash-premium
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
network_mode: "host"
volumes:
- ./clash:/root/.config/clash
restart: "always"
logging:
driver: "json-file"
options:
max-size: "5m"
port: 7890
socks-port: 7891
redir-port: 7892
allow-lan: true
bind-address: "*"
mode: Rule
log-level: info
external-controller: 0.0.0.0:9090
secret: "secret"
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 223.5.5.5
- 223.6.6.6
tun:
enable: true
stack: system
auto-route: true
auto-detect-interface: true
proxies:
- name: "hk"
type: trojan
server: server
port: 443
password: password
proxy-groups:
- name: Proxy-Fallback
type: fallback
proxies:
- hk
- DIRECT
url: 'http://www.gstatic.com/generate_204'
interval: 3
- name: Proxy
type: select
proxies:
- Proxy-Fallback
rule-providers:
apple-proxy:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Clash/Basic/Apple-proxy.yaml"
path: ./ruleset/Apple-proxy.yaml
interval: 86400
apple-direct:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Clash/Basic/Apple-direct.yaml"
path: ./ruleset/Apple-direct.yaml
interval: 86400
china:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/DivineEngine/Profiles@master/Clash/RuleSet/China.yaml"
path: ./ruleset/China.yaml
interval: 86400
global:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/DivineEngine/Profiles@master/Clash/RuleSet/Global.yaml"
path: ./ruleset/Global.yaml
interval: 86400
netflix:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@main/Rulesets/Clash/App/stream/Netflix.yaml"
path: ./ruleset/Netflix.yaml
interval: 86400
disney:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@main/Rulesets/Clash/App/stream/DisneyPlus.yaml"
path: ./ruleset/Disney.yaml
interval: 86400
lan:
type: http
behavior: classical
url: "https://cdn.jsdelivr.net/gh/Hackl0us/SS-Rule-Snippet@master/Rulesets/Clash/Basic/LAN.yaml"
path: ./ruleset/LAN.yaml
interval: 86400
rules:
# Rule sets
- RULE-SET,apple-proxy,Proxy
- RULE-SET,apple-direct,Proxy
- RULE-SET,china,DIRECT
- RULE-SET,global,Proxy
- RULE-SET,lan,DIRECT
# Final rules
- GEOIP,CN,DIRECT
- MATCH,Proxy
然后 docker compose up -d
当然以上只是把 Clash 跑起来,宿主机仍然需要设置转发规则来转发流量到 clash dns:
# https://zhuanlan.zhihu.com/p/423684520
REDIR_PORT="7892"
CLASH_DNS_PORT="1053"
#在nat表中新建一个clash规则链
iptables -t nat -N CLASH
#排除环形地址与保留地址,匹配之后直接RETURN
iptables -t nat -A CLASH -d 0.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 10.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 127.0.0.0/8 -j RETURN
iptables -t nat -A CLASH -d 169.254.0.0/16 -j RETURN
iptables -t nat -A CLASH -d 172.16.0.0/12 -j RETURN
iptables -t nat -A CLASH -d 192.168.0.0/16 -j RETURN
iptables -t nat -A CLASH -d 224.0.0.0/4 -j RETURN
iptables -t nat -A CLASH -d 240.0.0.0/4 -j RETURN
#重定向tcp流量到本机 redir_host
iptables -t nat -A CLASH -p tcp -j REDIRECT --to-port "$REDIR_PORT"
#拦截外部tcp数据并交给clash规则链处理
iptables -t nat -A PREROUTING -p tcp -j CLASH
#在nat表中新建一个clash_dns规则链
iptables -t nat -N CLASH_DNS
#清空clash_dns规则链
iptables -t nat -F CLASH_DNS
#重定向udp流量到本机 clash dns
iptables -t nat -A CLASH_DNS -p udp -j REDIRECT --to-port "$CLASH_DNS_PORT"
#抓取本机产生的53端口流量交给clash_dns规则链处理
iptables -t nat -I OUTPUT -p udp --dport 53 -j CLASH_DNS
#拦截外部upd的53端口流量交给clash_dns规则链处理
iptables -t nat -I PREROUTING -p udp --dport 53 -j CLASH_DNS
之后把各种设置或主路由的 dns 网关设置为宿主机 ip 就可以翻墙了。
但是仍然有一个问题,clash 在跑的情况下宿主机不能联网了,应该是以上路由规则存在问题,正在与 ChatGPT 激情讨论中

