Subnet routers
问题
- 如何让 tailnet 访问那些无法/不便安装 Tailscale 客户端的设备?
- 快速将一个子网加入 tailnet
tailscale 解决方案
在目标物理网络中, 指定一台已经安装 tailscale 的设备作为 “网关 / 代理”. 这台设备向 tailnet 宣告 (Advertise) 自己能够代表整个子网 (例如: 192.168.1.0/24)
当 Tailnet 中的其他设备需要访问该子网内任意设备时, 流量会被自动导向这个”网关”, 再由它转发到目标设备
工作流程
- 宣告: 指定一台 tailscale 客户端通过
--advertise-routes参数向 tailscale 的协调服务器宣告它可路由的子网 - 批准: 管理员必须在 tailscale 管理后台批准该路由, 它才生效
- 路由注入: 批准后, 协调服务器会将此路由信息注入到 Tailscale 中所有已启用接收子网路由
--accept-routes的客户端 (默认启用) - 访问: 当客户端访问目标子网时, 系统会根据路由表将流量通过加密隧道发送给”网关”, 再由其转发至目标
注意
-
默认无限制, 任意 tailnet 客户端都可以访问宣告的子网, 可在 ACL 配置权限
-
同子网冲突:
- 若你的 tailscale 客户端所在的本地网络与它接收到的子网路由完全重叠 (例如: 都是 192.168.1.0/24)
- 这时候客户端路由表会出现两条完全相同的路由, 操作系统可能会错误地将本地设备的流量发到远程的子网路由器, 导致本地网络访问失败
-
Linux 必须开启 IP forwarding: 内核默认不转发跨网卡的包, 不开的话”宣告了、后台也批准了、就是 ping 不通”. Exit Node 同理
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf sudo sysctl -p /etc/sysctl.d/99-tailscale.conf -
默认开启 SNAT: 子网内设备看到的源 IP 是子网路由器自己, 而不是发起访问的那台 tailnet 设备的 100.x 地址. 若子网侧要按原始 IP 做访问控制/审计, 用
--snat-subnet-routes=false关闭 (关闭后需自行保证子网侧有回程路由指向路由器)
使用示例
注意: 需要在管理后台批准该路由后才生效
- tailscale 客户端A, 位于网段 192.168.1.0/24
- 共享整个网段:
tailscale set --advertise-routes=192.168.1.0/24 - 仅共享单个子网设备:
tailscale set --advertise-routes=192.168.1.213/32
- 共享整个网段:
- tailscale 客户端B, 位于网段 192.168.31.0/24
- 启用接受子网路由:
tailscale set --accept-routes - 测试连通性:
tailscale ping 192.168.1.213 - 随后直接访问
192.168.1.213即可
- 启用接受子网路由:
# 查看路由表
C:\Users\25868>route PRINT -4
IPv4 路由表
===========================================================================
活动路由:
网络目标 网络掩码 网关 接口 跃点数
...
192.168.1.213 255.255.255.255 100.100.100.100 100.78.210.111 5
Exit Node
Info
默认情况下, tailscale 只路由 tailnet 之间的流量, 不会影响设备的公共互联网流量. 部分场景下, 你可能希望路由所有互联网流量:
- 你在咖啡店/机场/图书馆, WIFI 不受信任
- 你需要将 公司网络 / 家庭网络作为流量出口
此时, 可以将 tailnet 中的指定设备设置为 Exit Node (出口节点), 然后配置其他设备访问公共互联网的流量由该节点发出
工作流程
Exit Node 的启用与 Subnet Routers 相似, 但在路由注入上具有最高优先级
- 宣告: Exit 节点通过
--advertise-exit-node向协调服务器宣告自己作为公网出口角色 - 批准: 管理员必须在后台批准, 它才生效
- 路由注入: 协调服务器将默认路由 (IPv4 的
0.0.0.0/0与 IPv6 的::/0) 注入到 tailnet 中所有开启使用 exit node (--exit-node=<ip|name>) 选项的客户端 - 全流量劫持与转发: 客户端操作系统根据新的路由表, 将所有非本地局域网 (LAN) 的流量通过加密隧道发给 Exit 节点, Exit 节点收到后, 进行源地址转换(SNAT), 用自己的公网 IP 发出请求, 收到响应后原路加密返回
关键机制
Exit Node 能够不依赖复杂代理协议 (如 HTTP CONNECT) 而直接工作, 依赖如下两个关键机制:
- 默认路由覆盖与策略路由
- tailscale 利用操作系统 策略路由/优先级最高的路由条目, 精准将公网流量指向 tailscale0 虚拟网卡
- 确保只有访问互联网的流量被代理, 访问本地局域网/Tailnet 的流量直连
- NAT 与 反向路径过滤
- 公网服务器看到的请求源 IP 是 Exit 节点的公网 IP, 服务器回包只能到 Exit 节点
- 因此, Exit 节点必须对发出的数据包执行 Masquerade (伪装/SNAT), 并维护连接跟踪表 (Conntrack), 才能将收到的回包正确还原并转发给对应客户端
注意
- 本地局域网访问阻断: 配置 exit node 后, Tailscale 会劫持所有流量, 包括访问本地局域网(如 192.168.1.1)的流量. 若需访问本地设备, 必须显式开启
--exit-node-allow-lan-access
使用示例
注意: 需要在管理后台批准该 exit node 后才生效
- tailscale 客户端A, 位于家庭宽带网络 (具备稳定的公网出口能力)
- 宣告为出口节点:
tailscale set --advertise-exit-node
- 宣告为出口节点:
- tailscale 客户端B, 位于网段 192.168.31.0/24 (例如咖啡厅或公司网络)
- 指定客户端A为默认公网出口:
tailscale set --exit-node=<客户端A ip|name> --exit-node-allow-lan-access - 访问公网 (例如
curl ifconfig.me), 检查出口 IP 地址
- 指定客户端A为默认公网出口:
命令含义见 2.常用命令