tailscale + openclash(tun + fakeip) 在软路由上共存的解决方案
- 内容介绍
- 文章标签
- 相关推荐
和 gpt 折腾了两天,终于实现了 tailscale + openclash 在我家软路由上的共存
他解决了什么问题呢?
- tailscale 没有分流。手机上也没法同时开 tailscale + stash/singbox。用起来贼麻烦,要切来切去
- 我把我家路由器下的设备都暴露给 tailscale 组的网了。用起来非常省心,不用在 lan 下每台设备再开 tailscale 了。出门在外手机就能用 termius + tmux 控制家里电脑上的 agent 开始干活了。
下面是 ai 帮我整理的文章,和大家分享一下
在 OpenWrt 上让 OpenClash 和 Tailscale 共存
我折腾这套东西的原因其实很简单。
Tailscale 很好用,组网、穿透都省心。但它的 Exit Node 太“粗暴”——
- 开了 Exit Node:所有流量都走出口。如果出口在国内,你懂的,如果出口在国外,国内的流量要绕一大圈
- 不开 Exit Node:又什么都过不去
没有分流概念。
而我家里一直用 OpenClash(开着 Fake-IP)做精细分流。所以我的目标很明确:
用 Tailscale 负责“回家”,用 Clash 负责“怎么上网”。
远程连回家之后,依然按 Clash 规则分流,而不是全局代理或全局直连二选一。
最后打通了,而且挺稳定。
现在的结构
- OpenWrt 同时运行 OpenClash(Fake-IP + tun 开启)
- 同时运行 Tailscale, 而且 advertise subnet
- OpenWrt 作为 Subnet Router + Exit Node
当我在外面把 OpenWrt 选成 Exit Node 时,流量路径是:
我的手机/电脑
↓
Tailscale
↓
家里 OpenWrt
↓
OpenClash 分流
效果就是:
- 仅多一跳,就享受和家里软路由一样的分流功能
关键点就三个
解决 DNS 冲突
Fake-IP 会接管 DNS。
Exit Node 模式下,Tailscale 不走 MagicDNS。
在 OpenClash 里开启第二 DNS, 里面填:100.100.100.100
这是 Tailscale 内置 DNS。
目的就是别把 Tailnet 域名 fake 掉。
然后指定 你的 Tailnet 域名使用这个 dns. (这里似乎不支持+这个通配符,必须把你的 Tailnet 域名全部写出来,挺蛋疼的)
然后在 fake-ip-filter 里加
+.ts.net, 让 tailscale 不解析 tailscale 域名
(这个似乎没有必要了)
启动顺序
必须:
OpenClash → Tailscale
不然路由会被覆盖。
我就是简单在 /etc/init.d/tailscale 里加了个:
sleep 10
让 Tailscale 延迟启动, 保证 clash 启动且把iptables 和 ip route 配置完
给 Tailnet 单独一条高优先级路由
这是最关键的。
Clash 本质上在用策略路由 + fwmark。
如果不处理,100.64.0.0/10 可能会被它抢走。
我在 /etc/config/network 里加:
config route
option interface ‘tailscale’
option target ‘100.64.0.0/10’
option ‘200’
config rule
option dest ‘100.64.0.0/10’
option lookup ‘200’
option priority ‘100’
重点是 priority 要够小(数字越小优先级越高)。
Clash 通常插在 1000+,我设成 100,就是为了保证:
100.64.0.0/10 → 直接走 table 200 → tailscale0
优先级必须高过 Clash 的策略规则。
可以用:
ip rule show
确认顺序。
现在的体验
- 在家里:正常 Clash 分流
- 在外面:连回家,依然 Clash 分流
- 不需要公网 IP
- 不需要端口映射
- LAN 设备也能直接访问 Tailnet
- 开了 Tailscale 就可以访问 LAN 下的设备。然后 Termius + tmux 就可以指挥家里电脑上的 agent 开始工作了
Tailscale 解决连接问题,
Clash 解决策略问题。
职责分清之后,它们其实并不冲突。
如果你也觉得 Tailscale 的 Exit Node 太简单粗暴,又不想放弃 Fake-IP 分流,这个方案是可行的,而且不复杂。
流量实际怎么走?
很多人关心的其实是:
到底经过了哪些虚拟网卡?有没有绕圈?有没有双重代理?
我把两种情况拆开说。
一、软路由外的节点(选择 Exit Node)
假设我在外面,把家里的 OpenWrt 设为 Exit Node。
流量路径是:
外部设备
↓
Tailscale 虚拟网卡(tailscale0)
↓
WireGuard 隧道
↓
家里 OpenWrt 的 tailscale0
↓
进入内核主路由表
↓
被 OpenClash 的策略路由匹配
↓
Clash 虚拟网卡(通常是 utun)
↓
eth0 / pppoe-wan 出口
关键网卡:
- 客户端:tailscale0
- OpenWrt:
tailscale0 - Clash:
utun - 实际出口:
eth0/wan
也就是说:
Tailscale 负责“把流量带回家”,
Clash 再决定“这包流量该怎么出去”。
不是双代理,而是串联两层逻辑。
二、软路由下的 LAN 设备
情况 1:正常上网
LAN 设备
↓
br-lan
↓
utun
↓
OpenClash 策略路由
↓
wan
经过的虚拟网卡:
br-lanutun(Clash)wan
这是标准透明代理流程。
情况 2:LAN 访问 Tailnet(100.x.x.x)
因为我们加了高优先级 rule:
LAN 设备
↓
br-lan
↓
匹配 100.64.0.0/10
↓
table 200
↓
tailscale0
↓
远程 Tailnet 节点
经过的网卡:
br-lantailscale0
不会经过 tun0。
这就是为什么一定要抢优先级。
总结一下路径
外部 → 回家 → 上网
tailscale0 → tailscale0 → utun → wan
LAN → 上网
br-lan → utun → wan
LAN → Tailnet
br-lan → tailscale0
逻辑非常清晰:
- tailscale0 只负责 100.64.0.0/10
- utun 负责公网分流
- 两者通过策略路由分界
这一点其实是整个方案稳定的根本原因。
不是靠运气能跑,而是流量边界非常明确。
网友解答:--【壹】--:
image1681×936 108 KB
dae benchmark
This Sheet is private
tproxy是防火墙转发只走一次协议栈,tun类似于虚拟网卡,数据包会走多次协议栈。
--【贰】--:
挺早就知道了利用fakeip的方案,一直没空自己部署试试
通篇看下来还是有些需要人工维护的配置,蹲一个新思路..
--【叁】--:
tproxy 比 tun 还不稳。 要一堆 iptables 的规则,和 tailscale 更容易冲突。 虚拟网卡反而是简洁的方案
--【肆】--:
能动就行,反正家宽上行就给那么一点
--【伍】--:
需要解决的问题是手机上开了 tailscale 就没法开 clash。 所以用 exit node 多一跳回家,然后经过软路由的 openclash 分流出去。
--【陆】--:
我用openclash+wg,完美实现安卓端的翻墙+回家,flclash支持wg
--【柒】--:
性能这块我倒是没有思考过。 但问题是只要进了 clash,都是用户态的 l3 转发吧, 理论上都差不多?
--【捌】--:
缺点就是网速受限家宽的上传带宽了=v=
--【玖】--:
感谢大佬!
--【拾】--:
你要解决的问题是?
--【拾壹】--:
牛逼厉害
--【拾贰】--:
佬太棒了,我最近也碰到这个问题在和cc battle,就看到你的帖子
但是我没有现成的软路由,cc搜索后推荐Termux proot Ubuntu方案,在termux里面装一个ubuntu,在ubuntu里面装tailscale执行,不知道这个方案佬折腾过吗
--【拾叁】--:
和你一样的问题,但是我没有软路由
--【拾肆】--:
没想到 tun 的性能这么差。。。
--【拾伍】--:
想了一下,确实没必要用tproxy,家宽的速度瓶颈不在tun
--【拾陆】--:
Tailscale 回家不用 ExitNode 的吧?不应该是设置好Subnet,指定好内网的CIDR就能自动转发对应IP段的路由吗?
--【拾柒】--:
MARK一下,改天再研究研究
--【拾捌】--:
看似简单,实则需要付出大量精力折腾
--【拾玖】--:
用tproxy模式就好了, 通过tailscale流进软路由的流量直接丢给openclash, 搞两虚拟网卡有点麻烦了。
和 gpt 折腾了两天,终于实现了 tailscale + openclash 在我家软路由上的共存
他解决了什么问题呢?
- tailscale 没有分流。手机上也没法同时开 tailscale + stash/singbox。用起来贼麻烦,要切来切去
- 我把我家路由器下的设备都暴露给 tailscale 组的网了。用起来非常省心,不用在 lan 下每台设备再开 tailscale 了。出门在外手机就能用 termius + tmux 控制家里电脑上的 agent 开始干活了。
下面是 ai 帮我整理的文章,和大家分享一下
在 OpenWrt 上让 OpenClash 和 Tailscale 共存
我折腾这套东西的原因其实很简单。
Tailscale 很好用,组网、穿透都省心。但它的 Exit Node 太“粗暴”——
- 开了 Exit Node:所有流量都走出口。如果出口在国内,你懂的,如果出口在国外,国内的流量要绕一大圈
- 不开 Exit Node:又什么都过不去
没有分流概念。
而我家里一直用 OpenClash(开着 Fake-IP)做精细分流。所以我的目标很明确:
用 Tailscale 负责“回家”,用 Clash 负责“怎么上网”。
远程连回家之后,依然按 Clash 规则分流,而不是全局代理或全局直连二选一。
最后打通了,而且挺稳定。
现在的结构
- OpenWrt 同时运行 OpenClash(Fake-IP + tun 开启)
- 同时运行 Tailscale, 而且 advertise subnet
- OpenWrt 作为 Subnet Router + Exit Node
当我在外面把 OpenWrt 选成 Exit Node 时,流量路径是:
我的手机/电脑
↓
Tailscale
↓
家里 OpenWrt
↓
OpenClash 分流
效果就是:
- 仅多一跳,就享受和家里软路由一样的分流功能
关键点就三个
解决 DNS 冲突
Fake-IP 会接管 DNS。
Exit Node 模式下,Tailscale 不走 MagicDNS。
在 OpenClash 里开启第二 DNS, 里面填:100.100.100.100
这是 Tailscale 内置 DNS。
目的就是别把 Tailnet 域名 fake 掉。
然后指定 你的 Tailnet 域名使用这个 dns. (这里似乎不支持+这个通配符,必须把你的 Tailnet 域名全部写出来,挺蛋疼的)
然后在 fake-ip-filter 里加
+.ts.net, 让 tailscale 不解析 tailscale 域名
(这个似乎没有必要了)
启动顺序
必须:
OpenClash → Tailscale
不然路由会被覆盖。
我就是简单在 /etc/init.d/tailscale 里加了个:
sleep 10
让 Tailscale 延迟启动, 保证 clash 启动且把iptables 和 ip route 配置完
给 Tailnet 单独一条高优先级路由
这是最关键的。
Clash 本质上在用策略路由 + fwmark。
如果不处理,100.64.0.0/10 可能会被它抢走。
我在 /etc/config/network 里加:
config route
option interface ‘tailscale’
option target ‘100.64.0.0/10’
option ‘200’
config rule
option dest ‘100.64.0.0/10’
option lookup ‘200’
option priority ‘100’
重点是 priority 要够小(数字越小优先级越高)。
Clash 通常插在 1000+,我设成 100,就是为了保证:
100.64.0.0/10 → 直接走 table 200 → tailscale0
优先级必须高过 Clash 的策略规则。
可以用:
ip rule show
确认顺序。
现在的体验
- 在家里:正常 Clash 分流
- 在外面:连回家,依然 Clash 分流
- 不需要公网 IP
- 不需要端口映射
- LAN 设备也能直接访问 Tailnet
- 开了 Tailscale 就可以访问 LAN 下的设备。然后 Termius + tmux 就可以指挥家里电脑上的 agent 开始工作了
Tailscale 解决连接问题,
Clash 解决策略问题。
职责分清之后,它们其实并不冲突。
如果你也觉得 Tailscale 的 Exit Node 太简单粗暴,又不想放弃 Fake-IP 分流,这个方案是可行的,而且不复杂。
流量实际怎么走?
很多人关心的其实是:
到底经过了哪些虚拟网卡?有没有绕圈?有没有双重代理?
我把两种情况拆开说。
一、软路由外的节点(选择 Exit Node)
假设我在外面,把家里的 OpenWrt 设为 Exit Node。
流量路径是:
外部设备
↓
Tailscale 虚拟网卡(tailscale0)
↓
WireGuard 隧道
↓
家里 OpenWrt 的 tailscale0
↓
进入内核主路由表
↓
被 OpenClash 的策略路由匹配
↓
Clash 虚拟网卡(通常是 utun)
↓
eth0 / pppoe-wan 出口
关键网卡:
- 客户端:tailscale0
- OpenWrt:
tailscale0 - Clash:
utun - 实际出口:
eth0/wan
也就是说:
Tailscale 负责“把流量带回家”,
Clash 再决定“这包流量该怎么出去”。
不是双代理,而是串联两层逻辑。
二、软路由下的 LAN 设备
情况 1:正常上网
LAN 设备
↓
br-lan
↓
utun
↓
OpenClash 策略路由
↓
wan
经过的虚拟网卡:
br-lanutun(Clash)wan
这是标准透明代理流程。
情况 2:LAN 访问 Tailnet(100.x.x.x)
因为我们加了高优先级 rule:
LAN 设备
↓
br-lan
↓
匹配 100.64.0.0/10
↓
table 200
↓
tailscale0
↓
远程 Tailnet 节点
经过的网卡:
br-lantailscale0
不会经过 tun0。
这就是为什么一定要抢优先级。
总结一下路径
外部 → 回家 → 上网
tailscale0 → tailscale0 → utun → wan
LAN → 上网
br-lan → utun → wan
LAN → Tailnet
br-lan → tailscale0
逻辑非常清晰:
- tailscale0 只负责 100.64.0.0/10
- utun 负责公网分流
- 两者通过策略路由分界
这一点其实是整个方案稳定的根本原因。
不是靠运气能跑,而是流量边界非常明确。
网友解答:--【壹】--:
image1681×936 108 KB
dae benchmark
This Sheet is private
tproxy是防火墙转发只走一次协议栈,tun类似于虚拟网卡,数据包会走多次协议栈。
--【贰】--:
挺早就知道了利用fakeip的方案,一直没空自己部署试试
通篇看下来还是有些需要人工维护的配置,蹲一个新思路..
--【叁】--:
tproxy 比 tun 还不稳。 要一堆 iptables 的规则,和 tailscale 更容易冲突。 虚拟网卡反而是简洁的方案
--【肆】--:
能动就行,反正家宽上行就给那么一点
--【伍】--:
需要解决的问题是手机上开了 tailscale 就没法开 clash。 所以用 exit node 多一跳回家,然后经过软路由的 openclash 分流出去。
--【陆】--:
我用openclash+wg,完美实现安卓端的翻墙+回家,flclash支持wg
--【柒】--:
性能这块我倒是没有思考过。 但问题是只要进了 clash,都是用户态的 l3 转发吧, 理论上都差不多?
--【捌】--:
缺点就是网速受限家宽的上传带宽了=v=
--【玖】--:
感谢大佬!
--【拾】--:
你要解决的问题是?
--【拾壹】--:
牛逼厉害
--【拾贰】--:
佬太棒了,我最近也碰到这个问题在和cc battle,就看到你的帖子
但是我没有现成的软路由,cc搜索后推荐Termux proot Ubuntu方案,在termux里面装一个ubuntu,在ubuntu里面装tailscale执行,不知道这个方案佬折腾过吗
--【拾叁】--:
和你一样的问题,但是我没有软路由
--【拾肆】--:
没想到 tun 的性能这么差。。。
--【拾伍】--:
想了一下,确实没必要用tproxy,家宽的速度瓶颈不在tun
--【拾陆】--:
Tailscale 回家不用 ExitNode 的吧?不应该是设置好Subnet,指定好内网的CIDR就能自动转发对应IP段的路由吗?
--【拾柒】--:
MARK一下,改天再研究研究
--【拾捌】--:
看似简单,实则需要付出大量精力折腾
--【拾玖】--:
用tproxy模式就好了, 通过tailscale流进软路由的流量直接丢给openclash, 搞两虚拟网卡有点麻烦了。

