Tailscale/Headsacle
Tailsacle是一款基于Wireguard的虚拟组网工具,可以实现在公网、内网间建立基于Wireguard的Full Mesh虚拟网络。区别于传统的VPN, Tailscale 没有中心服务器,所有节点以全互联方式连接,在保证安全的前提下尽可能提高速度,是下一代的VPN产品。
Tailscale解决的问题是内网间、内网与云、公网混合的虚拟组网和安全问题。我们常见的问题如:公司内部开发环境从外部访问不方便、多个云、不同内网之间互联困难、内网中存在大量不符合安全规范的服务、传统VPN配置复杂,效率低下。Tailscale以虚拟组网的方式把不同云、内网的设备连接起来,使用起来逻辑上等于在同一内网中,全互联又提高了速度,并且不需要复杂的VPN设置。
Tailsacle是一款收费服务,免费版受到一定限制。如果你想完全实现“自主可控”的同时还不用花费成本,可以使用开源的Headscale,它与Tailscale的客户端兼容。
Headscale & Headscale webui 安装前准备
下面以Headscale服务器 + Web UI控制面板为例,设置一组示例的Headsacle服务器和客户端,实现虚拟组网。
下面案例至少需要3个服务器和2个域名:
1,Headscale 控制服务器,仅从事控制用途,本身不承载流量(不开启流量转发)
2,内网服务器 192.18.2.1,位于公司内部,可以与公司内网中的其他机器连接
3,公网服务器 12.34.56.78
两个域名都解析到headscale控制服务器上。
域名A,headscale控制服务器API headscale.mydomain.com
域名B,headscale 控制面板 headscalewebui.mydomain.com
客户端(用户)可以在Internet上的任意位置。
首先安装Headsacle控制服务器。
在翻阅了大量的网上“教程”后,我认为由于开源软件的特性,必然会存在很多问题,需要进行一些改动。以下内容都是基于最新版(Headsacle 0.22.1)。
首先进行一些准备:这个Headscale的控制器有一些问题,很多东西需要进行不必要的操作。在Linux下直接安装可以参考这篇教程(云原生实验室)。Docker版的安装教程也很多,但同样麻烦。经过实验,我认为还是docker版好点,至少错了方便改,一次成功几乎不可能。
最可笑的是先要手工建立目录:假设加载volume的目录是 /docker/headscale
, 在后面手工添加config子目录。然后在config子目录里添加一个空白的sqlite文件。
mkdir -p ./headscale/config touch ./config/db.sqlite
接下来下载配置文件模板到config目录中
wget -O ./config/config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml
修改以下配置文件,其中不需要修改的部分没有列出。还有一部分(DNS相关)会在下部中列出。
server_url: https://headscale.mydomain.com #使用外部的nginx反代和申请免费的SSL,如果需要在这里直接做https,要预先准备证书。 listen_addr: 0.0.0.0:8080 # Address to listen to /metrics, you may want # to keep this endpoint private to your internal # network metrics_listen_addr: 0.0.0.0:9090 #这个是调试工具,不需要看的话设为127.0.0.1 grpc_listen_addr: 127.0.0.1:50443 #不需要的话不要改 ip_prefixes: #虚拟IP的范围 # - fd7a:115c:a1e0::/48 #没有IPV6的话关闭,有的话可以打开。 - 100.64.0.0/10 derp: server: # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place enabled: false #中转服务,不需要的话关闭 randomize_client_port: true #这里需要改成true
配置文件中关于DNS的部分在下篇中再说,这里先按照默认值不做改动。
docker 安装 headscale 和 headscale webui
起一个 docker compose
version: '3.1' services: headscale: image: headscale/headscale container_name: headscale volumes: - /home/docker/headscale/config:/etc/headscale - /home/docker/headscale/data:/var/lib/headscale - /home/docker/headscale/run:/var/run/headscale environment: - VIRTUAL_HOST=headscale.mydomain.com - VIRTUAL_PORT=8080 - LETSENCRYPT_HOST=headscale.mydomain.com - [email protected] networks: - interconnect ports: - 9090:9090 #调试工具,可以不开 - 8080:8080 #nginx反代443,实际上不需要从8080访问。 command: headscale serve restart: unless-stopped networks: interconnect: external: true
解释: Docker环境已经预先配置好了nginx-proxy 和 acme companion,可以自动反代容器的http请求并自动申请acme.sh 的LE证书。指定的networks是为了将这个容器与nginx连接。
*这里把headscale的8080反代到nginx的443,但是配置文件中的地址是https协议,配置文件中并未指定证书,实际上docker 0.0.0.0:8080 仍然是http协议。会报错缺少证书,但不影响使用。
9090如果不需要可以不映射。
如果headscale运行成功,那么就可以安装webui控制台了。我们还需要做一点准备:
生成两个key:
1,headscale API KEY
docker exec -it headscale headscale apikeys create
得到的API KEY 形如: 148BCRqjsg.5uhNpBohlpRRExxgxAsrR2I2c_Q4OIG0435522x
2, headscale webui encryption key
openssl rand -base64 32
得到一个字符串如: tPosHiEni60fXnyxxxxxNCUE362pexAlDzPxxxxLqKpo=
然后按照说明安装headscale webui,还是采用docker方式:
起一个docker compose 文件:
version: "3" services: headscale-webui: image: ghcr.io/ifargle/headscale-webui:v0.6.1 #latest 0.7.0 have bugs 这里无法使用0.7.0,暂时存在bug container_name: headscale-webui environment: - TZ=Asia/Tokyo - COLOR=red # Use the base colors (ie, no darken-3, etc) - - HS_SERVER=https://headscale.mydomain.com # headscale控制服务器的地址 - DOMAIN_NAME=https://headscalewebui.mydomain.com # 这个webui的地址. - SCRIPT_NAME=/admin # 启动位置 /admin 可以自己改 Remove if you are hosing at the root / - KEY="tPosHiEni60fXnyxxxxxNCUE362pexAlDzPxxxxLqKpo=" # Generate with "openssl rand -base64 32" - 刚才第二个key - AUTH_TYPE=basic # AUTH_TYPE is either Basic or OIDC. Empty for no authentication - 身份验证 - LOG_LEVEL=info # Log level. "DEBUG", "ERROR", "WARNING", or "INFO". Default "INFO" # ENV for Basic Auth (Used only if AUTH_TYPE is "Basic"). Can be omitted if you aren't using Basic Auth - BASIC_AUTH_USER=user # Used for basic auth 用户名 - BASIC_AUTH_PASS=password # Used for basic auth 密码 # ENV for OIDC (Used only if AUTH_TYPE is "OIDC"). Can be omitted if you aren't using OIDC #- OIDC_AUTH_URL=https://auth.$DOMAIN/.well-known/openid-configuration # URL for your OIDC issuer's well-known endpoint #- OIDC_CLIENT_ID=headscale-webui # Your OIDC Issuer's Client ID for Headscale-WebUI #- OIDC_CLIENT_SECRET=YourSecretHere # Your OIDC Issuer's Secret Key for Headscale-WebUI - VIRTUAL_HOST=headscalewebui.mydomain.com - VIRTUAL_PORT=5000 #容器内端口5000,反代出去 - LETSENCRYPT_HOST=headscalewebui.mydomain.com - [email protected] volumes: - /home/docker/webui:/data # Headscale-WebUI's storage. Make sure ./volume is readable by UID 1000 (chown 1000:1000 ./volume) - /home/docker/headscale/config/:/etc/headscale/:ro # 这里是headscale的config目录位置 ports: - 5000:5000 #经过测试无问题后可以不需要暴露HTTP 5000端口 networks: - interconnect restart: always networks: interconnect: external: true
是否需要把配置文件改成chown 1000,我不知道,如果不改可能也没事。
*最新版本存在bug,只能使用0.6版本,后续可以升级。
这里容易出错的地方很多,详细按照说明进行安装。
安装完毕后如果运行无误,就可以通过 https://headscalewebui.mydomain.com/admin 来进行设备管理了。
进入后输入刚才设置的用户名/密码,再输入headscale 的API KEY,就可以通过webui进行管理了。
首先第一件事是建立网络,在user里面增加一个用户。 同一个用户,就是同一个网络。同一个username名下的设备可以互通,否则不可以。
注册设备并加入网络
下面注册设备并加入网络。上面所说的两台服务器,一台在内网,一台在公网。先设置内网的服务器。
内网服务器内网地址为 192.168.2.1,可以与内网其他机器连接,要求加入网络,并作为192.18.2.0/24的路由,转发所有通往 192.168.2.0/24的信息。
假设服务器都是Ubuntu系统。
设备使用的客户端程序,直接使用tailscale的客户端(两者是兼容的)。
按照tailsacale公司的教程在Ubuntu上安装程序。
tailscale up --login-server=https://headscale.mydomain.com --accept-routes=true --accept-dns=true
等终端出出现以下内容:
To authenticate, visit: https://headscale.mydomain.com/register/nodekey:2d71ab2822852a458e320…..
复制这个URI,用浏览器访问一下。访问后 会提示:
headscale
Run the command below in the headscale server to add this machine to your network:headscale nodes register –user USERNAME –key nodekey: 2d71ab2822852a458e320….
Machine registration
此时直接回到WebUI,选择设备,添加设备,选择网络名,把 nodekey:2d71ab2822852a458e320……
. 输入到后面的nodekey里面,就可以激活设备了。注意 “nodekey:
”不能省略。
后面的key就是nodekey.
添加完毕后终端会显示Success,这样设备就添加完毕了。添加完毕后,设备应该可以在设备列表中可见,并被分配了虚拟网络地址。
开启路由转发和出口节点功能
接下来把这个设备设置为路由,向192.168.2.0/24网段转发。
*所有作为转发或出口的服务器都要开启IP转发 sysctl net.ipv4.ip_forward
回到Ubuntu的终端:
tailscale up --accept-dns=true --accept-routes --advertise-routes=192.168.2.0/24 --login-server=https://headscale.mydomain.com
回到headscale webui控制台,选择“Routes”, 可以看到上面的route: 192.168.2.0/24, click on the dot right side to enable the route.
这样这台机器就具有了向内网转发的功能*。
客户端连接headscale网络后,可直接访问 192.168.2.2,路由会自动从192.168.2.1服务器转发。
在另一台服务器(公网 12.34.56.78)上,开启出口节点功能,使能将客户端全部(不含虚拟内网中)的流量转发到该服务器并通过该服务器路由出去,实现代理上网功能。
在该服务器上安装tailscale并注册网络后,输入以下命令开启出口节点:
tailscale up --advertise-exit-node --accept-dns=true --accept-routes --login-server=https://headscale.mydomain.com
同样再回到webui控制台,route下面有 exit node,看到申请的服务器已经出现,点右边的点 enable。
客户端连接headscale网络后,选择Exit node,就可以将全部非内网流量转发到该exit node,实现通过该exit node 代理上网的目的。
客户端安装
按照headscale github 上的要求安装客户端。
这里说一下windows客户端的问题:
访问控制服务器的URI, https://headscale.mydomain.com/windows 会出现安装提示。
新版的tailscale windows client 已经不需要修改注册表,只要按照提示的要求输入命令即可。同样输入命令注册机器,访问授权代码,在webui中粘贴nodekey授权。
tailscale windows 安装后可以在 Windows console 里面输入命令,但可以从右键菜单上直接选择 exit node和dns控制方式,不需要每次都输入。
Reference & bugs
*nginx ssl 反代后可以使用https 访问headscale 控制服务器,但注册机器不能使用https uri的问题
参考了以下内容:
Setting up Tailscale on Ubuntu 20.04 LTS