#macos

macos shadowrocket tailscale conflict

developer

解决macOS上Shadowrocket和tailscale冲突的问题

问题

自从我开始用tailscale以来,我就一直被一个问题困扰:如果打开shadowrocket代理开关,就ssh不上tailscale的设备,只能关掉。我试了以下方法,都失败了:

  • 在shadowrocket规则中加入100.64.0.0/10 DIRECT
  • 换用clash、surge
  • 关闭tailscale的dns功能

至于为什么用shadowrocket,虽然它不是macOS原生的,是因为它最简单、逻辑最明确。我真的受不了clash。

结论

前往Shadowrocket——配置——本地文件——通用——TUN旁路路由。你会发现里面有100.64.0.0/10,把它删掉,就好了。

很奇怪,明明是绕过了代理的虚拟网卡,怎么反而应该删掉这一条呢?这是因为这个TUN旁路设置会把里面的地址全都路由到默认网关:en0,也就是路由器。100.x地址就这么绕过了tailscale的虚拟网卡,相当于在局域网里找100.x地址,当然什么都没有。

下面说说debug用到的工具。不过一直卡住我的其实是Shadowrocket里“TUN旁路路由”那个迷惑的描述,它都说绕过了,那当然很健康了,就没想到原来问题在它身上。

工具箱

查看路由表

netstat -nr | grep -E "100\.|default"
#-n:以数字形式显示地址和端口号,不进行 DNS 反向解析,可以加快输出速度
#-r:route table

Destination, Gateway, Flags, Netif, Expire

default            192.168.31.1       UGScg                 en0
default            link#32            UCSIg               utun6
default            link#33            UCSIg               utun7
100.64/10          192.168.31.1       UGSc                  en0
100.64/10          link#32            UCSI                utun6
100.100.100.100/32 link#32            UCS                 utun6
100.113.229.108    100.113.229.108    UH                  utun6
  • Destination:目标网段
  • Gateway:下一跳地址
    • link#32:直接连接到某个接口(不经过路由器)
    • 192.168.31.1:通过网关路由
  • Flags
    • U:Up(路由有效)
    • G:Gateway(需要通过网关)
    • S:Static(静态路由)
    • C:Connected(直连网络)
    • I:Interface(接口路由)
  • Netif:出口网卡

可以看到100.64有两个项,这就不对,所以需要删了它。

sudo route delete -net 100.64.0.0/10 192.168.31.1

查看虚拟网卡

ifconfig | grep -A 3 utun

试着切换代理状态,就能找出代理对应的utun。在我这里是utun7。utun6是tailscale的网卡ID。

utun6: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280
	options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
	inet6 fe80::9874:2f39:3816:7a73%utun6 prefixlen 64 scopeid 0x20
	inet 100.113.229.108 --> 100.113.229.108 netmask 0xffffffff
	inet6 fd7a:115c:a1e0::c001:e56d prefixlen 48
	nd6 options=201<PERFORMNUD,DAD>
utun7: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 4064
	options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
	inet 198.18.0.1 --> 198.18.0.1 netmask 0xffffff00
	inet6 fe80::9874:2f39:3816:7a73%utun7 prefixlen 64 scopeid 0x21
	inet6 fd00:1234:ffff::10 prefixlen 128
	nd6 options=201<PERFORMNUD,DAD>

DNS

怀疑过是dns问题,所以也试了试。

traceroute -i utun6 <IP>
# -i:指定出口网卡
scutil --dns
# 通过system configuration查看dns配置
DNS configuration (for scoped queries)

resolver #1
  search domain[0] : 114.114.114.114
  nameserver[0] : 114.114.114.114
  nameserver[1] : 202.120.224.26
  nameserver[2] : 61.129.42.6
  if_index : 14 (en0)
  flags    : Scoped, Request A records
  reach    : 0x00000002 (Reachable)

resolver #2
  search domain[0] : tail6fb103.ts.net
  nameserver[0] : 100.100.100.100
  if_index : 32 (utun6)
  flags    : Scoped, Request A records, Request AAAA records
  reach    : 0x00000003 (Reachable,Transient Connection)

resolver #3
  nameserver[0] : 198.18.0.2
  if_index : 33 (utun7)
  flags    : Scoped, Request A records, Request AAAA records
  reach    : 0x00000003 (Reachable,Transient Connection)

可以清晰地看到dns、utun、route的对应关系。关掉tailscale dns后resolver #2就没了。