Tailscale,好!

我之前在用向日葵、todesk和teamviewer一类的工具来远程连接Windows的设备。久而久之,这样做暴露出了很多问题:

  1. 在Linux桌面趋于wayland的大环境下,todesk的客户端并不能很好适配,存在严重的使用问题,在我惯用的ArchLinux+wayland上障碍明显
  2. 同样地,向日葵的Linux客户端日久失修,在我惯用的环境上很难正常连接设备
  3. teamviewer的使用体验不理想,广告多,连接速度并不够快,并且对设备数量等限制严格

对于Linux的服务器,我还习惯用frp把Linux的SSH映射到外网连接,久而久之,这样做也有一些问题:

  1. 安全性问题,有些设备是内网设备,暴露给外网欠妥,这并不是一个靠谱的组网方式
  2. frp的配置虽然较为友好,但是还是有些许繁琐
  3. frp不能很方便的共享一个网段,不能方便地映射出某一个网络环境

对于这样的产品,我始终倾向于用VPN软件。但是之所以很少使用类似wireguard一类的VPN软件组内网,是因为这样的软件还是有一定的使用成本的。并且在学校里,有的时候需要把使用方法告诉给老师或者其他同学,对于不熟悉的同学而言徒增了交流成本,难以铺开。
所以我一直在寻找一个较为方便的VPN组网工具。

前段时间,我的好朋友鬼畜酱@Ghost_Chu 安利了Tailscale,并且给我看了他在很久以前写过的一篇博客文章,还带我体验了一番。在实际使用后,我发现这玩意儿真好使,深深地被鬼畜酱拉入坑内无法自拔。

本文主要写写自己的使用历程。

Tailscale是什么?好在哪里?

Tailscale是一个VPN组网工具。它可以进行虚拟组网,让多个设备连接在同一个虚拟网络中。这样,设备不需要暴露在外网环境,也能实现彼此之间的互联。

在我看来,Tailscale吸引我的地方有这些:

  1. 基本的互联功能,操作十分简单,在设备上安装Tailscale以后登录相同的帐号,就能快速添加设备,基本零配置成本
  2. 配套的客户端设施齐全,涵盖了Linux CLI、Windows、Android、ios、群晖组件等多种设备
  3. 有subnet功能,某个设备开启subnet后,可以将其所在的LAN共享出来
  4. Exit Node功能可以将某一个设备直接当作网络跳板机使用,配置极其简单,十分方便好用
  5. 能够自建DERP服务器(即中转服务器),铺设方式较为简单
  6. MagicDNS提供的主机名别名功能很方便

对于VPN和Tailscale的其他内容,鬼畜酱的博客文章里介绍的十分清晰,好评!并且鬼畜酱很有耐心,手把手教导咱配置,说话很好听,关键也很可爱,特殊服务好评(逃

关于我自己的一些实际情况

我的具体使用场景在学校宿舍内,网络环境并不理想。宿舍内登录校园网Web认证网关后NAT类型为Full Cone。

在之前,我经常用一些聊天软件传输和存储文件,十分不方便。我目前在宿舍里部署了一个NAS用来下番看和存一些学校的文件之类的东西。我希望我在外面玩的时候能连接NAS。
同时,我同时希望能够连接实验室里的一些内网服务器,以便开发和调试系统,也方便在校外访问校园网。

由于我自己扪心自问,发现自己自建NAS还是蛮灵车的,所以我跟我的好朋友鬼畜酱签订了奇妙的协♂议,我们互相配置了Cloud Sync通过WebDAV做重要数据备份,以此增强稳定性。鬼畜酱的网络环境也都是Full Cone。

由于学校的奇怪网络环境,为了保证打洞成功,不得不考虑补一些国内的中转服务器,以求连接稳定。

个人的使用方式

对于Tailscale的介绍,咱显然没办法介绍的比鬼畜更详细。
不过对于使用Tailscale的话,这几天也总结了一些心得。

最基本的设备互联

使用Tailscale最基本的需求就是将多个设备连接到同一个网络里。在Tailscale中,这样的虚拟网络被叫做Tailnet。一个帐号下的设备通常组成一张Tailnet。

如果需要将设备加入到Tailnet,只需要在这个设备上安装对应的Tailscale客户端,然后登录帐号就可以了,非常简单。

加入到同一个Tailnet后,Tailscale的MagicDNS可以将它解析到主机名上。
例如,我的群晖NAS的设备名是baka-datastore,我只需要在浏览器里访问http://baka-datastore:5000就能访问NAS了。

同时,每个用户还可以在管理后台设置自己的Tailnet name,如下图

这里我的名字是tail348933.ts.net,那么我使用http://baka-datastore.tail348933.ts.net:5000也可以访问NAS。

除了MagicDNS映射的主机名、主机名与Tailnet name组合的域名地址以外,Tailscale也给每个设备分配了对应的内网IP,可以在后台的Machines查看。

登录状态是有有效期的,有一些常用的设备没啥必要让登录状态过期,可以在Machines里找到那个设备,在右侧的...里打开菜单,点击Disable key expiry,就能让登录状态不过期了。

共享设备

如果想跟别人共享设备,那么这是要氪金的。但是你把某一个特定的设备分享给另一个人是免费的。

只需要在后台Machines里,找到对应的设备,在右侧点击Share,打开分享控制面板生成链接发给好朋友,对方就能点击链接将设备添加到自己的Tailnet列表里了。

例如我的笔记本是这台设备:

这里可以看到下面显示了Shared out +1,这是为什么呢?点击右侧的Share,打开分享控制面板:

诶嘿,答案揭晓了,咱把这台设备分享给了好朋友鬼畜!如果我还想再把设备分享给其他人,点击Copy share link,生成链接,发给别人就可以了。

现在可爱的鬼畜已经加入了咱的分享,就像上图一样,他也可以在自己的Tailnet里连接到咱的baka-laptop了。
只不过他不能通过MagicDNS由主机名访问这台设备(如果想这样,要么自己配hosts,要么氪金买Team版),如果他想链接,需要用主机名+Tailnet name组成的域名来访问,也就是baka-laptop.tail348933.ts.net,或者是鬼畜的管理面板的Machines列表中显示的内网IP访问。

在群晖里使用Tailscale

Tailscale添加设备提示,如下:

打开https://tailscale.com/kb/1131/synology/,可以看到帮助信息:

如果在国内,想要安装Tailscale,需要在套件中心中配置套件源,这样才能下载到Tailscale套件,如下图:

然后就可以在套件中心搜索Tailscale下载安装了。打开后登录即可。

现在,咱已经组好了自己的Tailnet,咱还把自己的NAS设备baka-datastore分享给了鬼畜,鬼畜也把自己的NAS设备barbatos分享给了咱,我们双方的NAS都是群晖。
现在我们彼此之间希望使用Cloud Sync来同步数据,以此来备份关键数据。那应该怎么做呢?

这里有一个需要注意的点,Tailscale套件在群晖系统里并不是sudo运行的,这意味着Tailnet IP地址在群晖系统内是不能使用的(见上述帮助文档的Limitation所述)。为了在群晖系统内使用Tailnet,让咱的NAS通过Cloud Sync连接鬼畜的NAS,我必须做一些修改:

  1. 打开SSH连接,SSH连接到NAS系统上(用户名和密码是NAS的管理员帐号的用户名和密码)
  2. 使用指令sudo tailscale configure-host,配置网络环境
  3. 使用指令sudo synosystemctl restart pkgctl-Tailscale.service,重启Tailscale系统服务

这样,我就可以通过使用鬼畜NAS对应的Tailnet IP地址,在Cloud Sync中配置连接了。

自己搭建DERP服务器

虽然打洞是能打,但是由于Tailscale打洞需要先让彼此连接官方的DERP服务器,然后才能打洞,官方的DERP服务器的节点在咱的网络环境里不算快,思来想去决定搭建一个DERP服务器。

搭建一个自己的DERP服务器需要准备一个公网机器,这台机器要开放一个HTTPS端口,3478 STUN端口,同时还需要准备一个域名。

由于我图懒省事,我直接用了宝塔安装了docker来搭建。
例如我想用的域名是ts-derp.kawaii-neko-cat.abc作为DERP服务器地址,我想开的HTTPS端口是22333,STUN端口维持默认的3478。这个DERP服务器我希望是自己使用,不希望公开。

首先在宝塔里正常创建一个网站,随便选就行了,反正也不是真的想开个网站,按照一个纯静态网站创建就可以了。
新建好网站后,在网站的详情面板的SSL面板里,申领一个Let's encrypt!证书。

然后SSH连接服务器。按照给Linux服务器安装Tailscale的方法,给服务器安装Tailscale,登录帐号将其加入Tailnet中。

下面开一个DERP服务端的docker容器,可以直接用其他人打包好的镜像即可。

docker run -d \
  --name derp \
  --restart=always \
  -p 3478:3478/udp \
  -p 22333:22333 \
  -v /www/server/panel/vhost/cert/ts-derp.kawaii-neko-cat.abc/fullchain.pem:/app/certs/ts-derp.kawaii-neko-cat.abc.crt \
  -v /www/server/panel/vhost/cert/ts-derp.kawaii-neko-cat.abc/privkey.pem:/app/certs/ts-derp.kawaii-neko-cat.abc.key \
  -v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \
  -e DERP_DOMAIN=ts-derp.kawaii-neko-cat.abc \
  -e DERP_ADDR=:22333 \
  -e DERP_CERT_MODE=manual \
  -e DERP_VERIFY_CLIENTS=true \
  fredliang/derper:latest

注意,上面的条目应当根据实际情况进行替换。这里挂载的几个文件是宝塔生成的SSL证书文件,懒得复制了直接挂载了,方便后续在宝塔里直接点续签。

容器顺利启动后,在宝塔里为站点配置反向代理。

然后访问https://ts-derp.kawaii-neko-cat.abc:22333,应当看到这样的内容:

这说明DERP服务端没有问题。如果我们想用上这个DERP服务器,需要在自己Tailscale的管理面板的Access Controls里配置derpMap,如下图:

    "derpMap": {
        "OmitDefaultRegions": false,
        "Regions": {
            "900": {
                "RegionID":   900,
                "RegionCode": "neko-derp-srv",
                "RegionName": "neko-derp-srv",
                "Nodes": [
                    {
                        "Name":     "1",
                        "RegionID": 900,
                        "HostName": "ts.kawaii-neko-cat.abc",
                        "DERPPort": 22333,
                        "STUNPort": 3478,
                    },
                ],
            },
        },
    }

这里的OmitDefaultRegions指是否屏蔽官方的DERP服务器。虽然感觉官方的DERP服务器已经没什么用了,但是我没屏蔽。
如果只希望用自己的DERP服务器,那么应该改为true

根据官方文档所述,RegionID似乎需要是900这一固定值。
RegionCodeRegionName以及Nodes.Name的配置是我瞎写的,任意文档中规定的合理值都可以。
其他项目依次进行合理配置即可。

可以参考官方的帮助文档进行设置。

分享自己搭建的DERP服务器

刚才创建的DERP服务器并不是一个公开的DERP服务器,只有我自己才能用。

然而在Tailscale里,如果想在两个设备之间打洞,必须先经过DERP服务器。DERP服务器择优选取,由于我们自建的DERP服务器不知道比官方的DERP服务器快到哪里去了,咱自己Tailnet中的设备显然渐渐会择优选取自建的DERP服务器。

这个时候鬼畜就尴尬了。我的设备如果自动选取了我们的DERP服务器,那他是没有办法连接我的DERP服务器的(因为是私有的),这会导致打洞失败。

一种解决方法是把爱传染给鬼畜,让鬼畜的Tailnet也用上咱的DERP服务器,只需要做下面这两步

  1. 让鬼畜的Access Controls里添加与我相同的derpMap信息
  2. 把DERP服务器主机分享给鬼畜,让鬼畜添加到自己的Tailnet中

就可以了!
这样鬼畜的Tailnet也能用咱的DERP服务器了,我们就可以愉快打洞了!

利用subnet共享所在网段其他设备

我还需要连接实验室的其他主机做调试。现在实验室有一个路由器,网段是192.168.100.0/24,其中有一台主机A192.168.100.2我装了Tailscale并且加入了我的Tailnet,现在同网段里还有设备192.168.100.3192.168.100.4192.168.100.5,我应该怎么连接它们呢?

一种方案是,我给那些设备都装上Tailscale。你说的对,但是如果那些设备是单片机之类的设备,或者是某些智能家居,那这样做显然是行不通的。
一个好办法是,利用Tailscale的subnet功能,我们可以让主机A做路由,把主机A所在的192.168.100.0/24网段配置subnet,将那些设备映射过来。

首先在主机A上配置映射:

tailscale up --advertise-routes=192.168.100.0/24

然后在管理后台Machines中找到主机A,在右侧...菜单中找到Edit route settings...,点击打开映射管理面板:

如果刚才执行的映射命令成功,那么这里应该显示能够加入的subnet routes条目,勾选即可映射。

然后就可以在自己的电脑上,通过192.168.100.3访问那些设备了。

利用Search Domains给subnet设备变相起别名

刚才利用subnet功能连接到了主机A所在的192.168.100.0/24网段中的192.168.100.3设备。可是这样输入IP感觉很别扭,能不能跟MagicDNS那样用类似主机名一样的东西来代替IP呢?
答案是可以的,但是直接为这个IP配置主机名是没法做到的。不过我们可以用Search Domains变相做到这一点。

首先我们需要有一个域名,例如是kawaii-neko-cat.abc,我们在管理面板的DNS面板里,添加kawaii-neko-cat.abc这个域名:

给这个域名增加一个A解析,把hello.kawaii-neko-cat.abc解析到192.168.100.3

这样,等解析生效的时候,我们直接在自己的主机上使用hello,就能当作192.168.100.3的主机名了,他会被Tailscale处理成主机名hello对域名hello.kawaii-neko-cat.abc的映射,等于自动补全域名后缀。

Exit Node

功能很好用,意思其实很简单就能解释明白,就是把某个设备当作出口节点,让流量都流经这台设备外流,就像是在用这台设备上网一样。

总结

在这几天的使用中,我觉得Tailscale确实让设备组网方便了很多很多,操作很简单,功能很强大,并且免去了之前不必要地对外暴露一些端口的危险操作。

在后续估计我还会继续使用Tailscale。

上一篇