所需设备
- 主路由选择以下三种路由设备之一,基础版面向的普通用户(一般买的家用无线路由器都支持),进阶版与linux系列路由器可定制一些高级功能,并且能在旁路由不稳定的情况下,保证家中不断网。
- 基础版(支持关闭DHCP功能的路由器均可)
- 进阶版(能修改路由表、配置DHCP Option的路由器均可)
- Openwrt/Padavan/RouterOS 等底层是linux的路由器
- 旁路由选择性能比较好的设备,安装linux系统或以linux为底层的路由器系统。
- 基础版:斐讯N1、树莓派等微型计算机
- 进阶版:x86软路由,虚拟机等
网络拓扑结构
旁路由设备与普通电脑、手机、电视设备一样接入到主路由的LAN网络中。
旁路由建议网线连接。
设计目标
- 访问国内IPv4/IPv6地址段直连,其余流量走旁路由设备
- 旁路由设备运行Clash TUN模式,由TUN网卡接管流量,交由Clash进一步分流处理。
- 双栈域名解析,IPv4优先(IPv6路由太差,不够稳定)
- 根据用户设备分为两类,一类正常上网,一类走旁路由设备分流代理。
- 不需要在每台设备挂代理与配置静态IP,客户端零配置,直接接入家庭网络即可。
运营商光猫与主路由默认配置
- 光猫改桥接
- 主路由PPPoE拨号
方案一(主路由为基础版)
因为主路由的功能有限,尤其是网上买的普通家用无线路由器。
这种情况下,如果不更换主路由就需要由旁路由设备来代管一些功能。
要求旁路由设备与主路由设备同样稳定,避免影响家里其他用户正常上网。
主路由配置
关闭DHCP即可,其他参照默认配置。
旁路由配置
旁路由需要开启路由转发。
DHCP配置(dnsmasq)
设计目标
根据用户设备分为两类,一类走主路由,主路由提供的DNS正常上网,一类走旁路由设备分流代理。
实施方法
对于需要透明代理的设备下发以下DHCP配置:
DHCP Options 3(默认网关):旁路由IP地址
DHCP Options 5(DNS):旁路由IP地址
对于不需要透明代理的设备默认配置即可,即网关为主路由,DNS为主路由或运营商下发的DNS。
那么问题来了,怎么做到针对不同的设备下发不同的DHCP配置呢?
这里可以通过配置dnsmasq来实现,参考底部参考文献[2]的文章
大致是通过MAC地址或者IP段来匹配,从而下发不同的DHCP配置。
缺点
- 需要提前搜集用户设备的MAC地址,如果用户设备的MAC地址发生变化,那么就会导致DHCP配置失效,需要重新配置。
- 多网卡设备,像笔记本电脑既可以插网线,又能连wifi,这是两个独立的网卡,因此两个mac地址都要配置。
- 不够安全,知道套路的人,可以自己配置静态ip使用代理。
- 不够灵活,每次修改DHCP配置,都需要等待用户设备重新获取IP地址,才能生效。
DNS服务器配置(mosdns)
mosdns的介绍和二进制可执行文件,参考项目官方地址[3].
设计目标
- 针对解析结果为国内IP的域名,转发至国内DNS,解析结果为海外IP的域名,转发至Clash DNS。
- 针对DNS解析结果分流,解析结果为国内IP的正常返回,解析结果为海外IP的返回fake-ip。
- 针对纯IPv6的域名解析,直接返回。(机场一般不支持v6,v6直连最好)
实施方法
我写了一份配置文件,参考了这个配置[4],有以下几点需要注意:
- forward_remote部分填写Clash的DNS地址。
- china_ip中的文件自己从网上搜索[6],主要是排除国内IP段与本地网络。是否排除本地网段[7]看自己需求,GFW有将IP污染到保留地址的先例。
- 纯IPv6的域名解析,我希望能直接直连,因此专门增加了规则。不需要可以删除。
- 转发至国内的DNS,建议填写国内的加密DNS,避免因配置防火墙53端口劫持的时候污染到结果。
- 添加fallback插件,当forward_remote挂了,自动回滚到forward_local。
- 设置ttl为1,方便clash恢复时能尽快拿到fake-IP。
/etc/mosdns/config.yaml1 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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| log: level: error file: "/tmp/mosdns.log"
plugins: - tag: cache type: cache args: size: 1024 lazy_cache_ttl: 86400 - tag: china_local_ip type: ip_set args: ips: - "192.168.0.0/16" - "10.0.0.0/8" - "172.16.0.0/12" - "127.0.0.0/8" - "100.64.0.0/10" - "::1/128" - "fc00::/7" - "fe80::/10" - "fd00::/8" files: - ./all_cn.txt - ./all_cn_ipv6.txt
- tag: forward_local type: forward args: concurrent: 2 upstreams: - addr: "https://223.5.5.5/dns-query" - addr: "https://120.53.53.53/dns-query" - tag: forward_remote type: forward args: concurrent: 2 upstreams: - tag: CLOUDFLARE addr: "https://gd.lyz05.cn/dns-query" bootstrap: "223.5.5.5" - tag: ALIYUN addr: "https://sub.lyz05.cn/dns-query" bootstrap: "223.5.5.5"
- tag: forward_clash type: forward args: concurrent: 1 upstreams: - addr: udp://192.168.2.10:1053
- tag: "fallback" type: fallback args: primary: forward_clash secondary: forward_remote threshold: 100 always_standby: false
- tag: main_sequence type: sequence args: - matches: qname &./proxy-list.txt exec: $forward_clash - matches: has_resp exec: accept
- matches: qname &./direct-list.txt exec: $forward_local - matches: has_resp exec: accept - exec: prefer_ipv4 - matches: "!qname lyz05.cn" exec: $cache - matches: has_resp exec: accept - exec: $forward_local - matches: - "has_resp" - "resp_ip $china_local_ip" exec: accept - matches: - "!has_wanted_ans" - "qtype 1" exec: accept - matches: - "has_wanted_ans" - "qtype 28" exec: accept - exec: $fallback
- tag: udp_server type: udp_server args: entry: main_sequence listen: :1053
- tag: tcp_server type: tcp_server args: entry: main_sequence listen: :1053
|
Clash
参考Clash的官方项目[5],下载二进制文件并使用。注意下载Permium版本的。
配置文件参考项目的示例文件,根据自己的需求修改即可。
大体上就是增加dns的配置
TUN模式的auto-route需要关闭,原因是:auto-route会默认添加默认路由到TUN网卡。这样国内直连的IP就会走TUN网卡,被Clash接管。对于性能弱的设备不好,影响网速。
所以也就带来了个缺点:对于不用域名解析只用IP访问的软件,会连不上,像Telagram,所以我们要单独加静态路由,让Telegram的IP[8]走TUN网卡。
/etc/clash/config.yaml1 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
| mixed-port: 7890 socks-port: 7891 redir-port: 7892 tproxy-port: 7893 allow-lan: true mode: rule log-level: warning external-controller: :9090 external-ui: ui profile: store-selected: true
dns: enable: true enhanced-mode: fake-ip listen: :1053 nameserver: - "https://223.5.5.5/dns-query" - "https://120.53.53.53/dns-query" fake-ip-filter: - +.stun.*.* - +.stun.*.*.* - +.stun.*.*.*.* - +.stun.*.*.*.*.* - "*.n.n.srv.nintendo.net" - +.stun.playstation.net - xbox.*.*.microsoft.com - "*.*.xboxlive.com" - "*.msftncsi.com" - "*.msftconnecttest.com" - WORKGROUP
tun: enable: true stack: system dns-hijack: - tcp://8.8.8.8:53 - 8.8.8.8:1053 auto-detect-interface: true auto-route: true
|
模拟访问过程
设备为透明代理用户
访问国内网站(百度)
- 查
baidu.com
的域名,发送查询请求给DHCP下发的DNS(旁路由)。 - mosdns查询国内公共DNS后,发现
baidu.com
是国内IP,直接返回此IP。 - 发送访问请求到
baidu.com
的真实IP,此IP不是局域网IP,将数据包发给网关(旁路由)。 - 旁路由收到数据包,检查本机路由表,此IP不属于TUN网段
198.18.0.0/16
,走默认路由即物理网卡(主路由)。
全程没有经过Clash,但流量会从旁路由饶一下,最终旁路由还是会把数据包原封不动(指网络层以上)交给主路由。
访问海外网站(Google)
- 查
google.com
的域名,发送查询请求给DHCP下发的DNS(旁路由)。 - mosdns查询国内公共DNS后,发现
google.com
是双栈海外IP。 - mosdns查询Clash的DNS,获得Clash的fake-ip,IP属于TUN网段
198.18.0.0/16
。 - Google域名是双栈IP,mosdns设置了ipv4_prefer,会忽略IPv6结果。避免系统拿到IPv6走物理网卡出。
- 发送访问请求到
google.com
的fake-ip,此IP不是局域网IP,将数据包发给网关(旁路由)。 - 旁路由收到数据包,检查本机路由表,此IP属于TUN网段
198.18.0.0/16
,走Clash的TUN网卡。 - Clash根据配置的规则,选择一个合适的代理或直连,发送数据包。
流量经过clash,会经过设备CPU处理,代理也有加解密的部分,会比直连的转发性能差。
方案二(主路由为进阶版或类linux系统)
主路由配置
添加TUN网段198.18.0.0/16
的静态路由,让TUN网段的流量走旁路由。
对于不适用域名解析,直接使用IP联网的应用,如:Telegram[8],需要进一步添加静态路由到旁路由。
DHCP下发的DNS根据需要,分两种情况:
- 正常上网用户:运营商下发的DNS
- 走透明代理用户:旁路由的IP
实际上就是将旁路由的DHCP功能放到主路由上,旁路由只做透明代理。
旁路由配置
mosdns和Clash部分跟方案一一样。
因为主路由能够控制DHCP了,所以旁路由不在需要是DHCP服务器了。
对于不适用域名解析,直接使用IP联网的应用,如:Telegram,需要打开auto-route
,让旁路由自动添加默认路由到Clash的TUN网卡。
模拟访问过程
设备为透明代理用户
访问国内网站(百度)
与方案一不同的地方是,拿到国内IP会走主路由直接出去,进一步减轻了旁路有的负担。
唯有拿到TUN网段198.18.0.0/16
的IP才会走旁路由。(因为设置了静态路由)
全程没有旁路由,跟正常上网一模一样,缺点是依赖旁路有的DNS,即mosdns。
如果旁路由挂了,域名解析不了。
访问海外网站(Google)
与方案一不同的地方是,数据包会先到主路由,做一次路由选择,再到旁路由。
附录
systemd配置
Clash
/etc/systemd/system/clash.service1 2 3 4 5 6 7 8 9 10 11
| [Unit] Description=Clash daemon, A rule-based proxy in Go. After=network-online.target
[Service] Type=simple Restart=always ExecStart=/usr/local/bin/clash -d /etc/clash
[Install] WantedBy=multi-user.target
|
mosdns
/etc/systemd/system/mosdns.service1 2 3 4 5 6 7 8 9 10 11
| [Unit] Description=MosDNS DNS Server After=network-online.target
[Service] Type=simple Restart=always ExecStart=/usr/local/bin/mosdns start -c /etc/mosdns/config.yaml -d /etc/mosdns
[Install] WantedBy=multi-user.target
|
自动更新订阅并下载分流规则
/root/sub.sh1 2 3 4 5 6 7
| #!/bin/bash mv /etc/clash/config.yaml /etc/clash/config.yaml.bak wget "订阅地址" -O /etc/clash/config.yaml wget "https://ispip.clang.cn/all_cn.txt" -O /etc/mosdns/all_cn.txt wget "https://ispip.clang.cn/all_cn_ipv6.txt" -O /etc/mosdns/all_cn_ipv6.txt systemctl restart clash systemctl restart mosdns
|
查看Clash中WARN级别漏网之鱼日志
当设置漏网之鱼为直连时,可能会有一些域名无法正常解析,这时候就需要查看日志,找到这些域名,然后添加到自定义代理域名中。
/root/log.sh1 2 3
| #!/bin/bash journalctl -u clash > /tmp/clash.log grep -P 'WRN(?=.*漏网之鱼)' /tmp/clash.log | less
|
参考文献