跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Headscale 用户使用手册

以官方文档内容为主,> 补充 为实践说明。
官方文档:https://headscale.net/stable/

1. Configuration(配置)

  • Headscale 从 YAML 文件加载配置。
  • 默认搜索路径:
    • /etc/headscale
    • $HOME/.headscale
    • 当前工作目录
  • 用以下方式指定其他路径:
    • 命令行参数 -c / --config
    • 环境变量 HEADSCALE_CONFIG
  • 用 headscale configtest 校验配置文件。
  • 始终选择与所用发布版本相同的 GitHub tag,main 分支可能包含未发布的改动。

补充:

  • server_url 是配置里最关键的项之一,必须和客户端实际访问的地址完全一致(协议、域名、端口)。写错的话,登录回调、OIDC 重定向、gRPC 远程连接都会出问题。
  • 配置文件里的相对路径是相对于配置文件所在目录,不是当前工作目录。证书路径、数据库路径、policy 路径都容易踩这个坑。
  • 大部分配置改动需要重启才生效,但 policy 文件支持热重载,改策略不用重启。
  • 参考样例一定用你当前版本 tag 下的 config-example.yaml,别用 main 分支的,格式可能已经变了。
  • 生产环境建议把配置放 /etc/headscale/,权限收紧(比如 600),因为里面可能有 OIDC client secret、数据库密码等敏感信息。
  • 常见配置段:server_url、listen_addr、metrics_listen_addr、grpc_listen_addr、database、dns、derp、oidc、policy、log。

2. Registration(节点注册)

身份模型

  • 个人节点:由人类用户拥有,通常指终端设备(笔记本、工作站、手机),由单个用户管理。
  • 标签节点:为网络提供服务(Web、数据库服务器),通常由团队管理。有额外限制,例如标签节点不允许 Tailscale SSH 登录个人节点。
  • Headscale 实现 Tailscale 的身份模型:个人节点归 Headscale 用户所有,标签节点归 tag 所有。标签设备归到特殊用户 tagged-devices 下。

补充:

  • 这个身份模型是理解 Headscale 权限体系的基础。个人节点属于「人」,标签节点属于「服务」。
  • 标签节点不能 SSH 进个人节点,是故意的安全设计,不是 bug。目的是防止被攻陷的服务节点横向移动到个人设备。
  • tagged-devices 是内部特殊用户,你在 headscale users list 里可能看不到它,但标签节点都挂在它下面。

注册方式

两种主要方式:Web 认证 和 预认证密钥,都可用于注册个人和标签节点。

Web 认证(默认,交互式)

  1. 创建用户:headscale users create <USER>
  2. 客户端登录:tailscale up --login-server <YOUR_HEADSCALE_URL>
  3. 浏览器打开页面,拿到 Auth ID,批准节点:headscale auth register --user <USER> --auth-id <AUTH_ID>

标签节点需要用户被授权,授权在 policy 的 tagOwners 段配置。客户端加 --advertise-tags tag:<TAG>,批准后节点归 tagged-devices 所有。

预认证密钥(非交互,适合自动化)

  1. 创建用户:headscale users create <USER>
  2. 查看 USER_ID:headscale user list
  3. 创建密钥:headscale preauthkeys create --user <USER_ID>
  4. 注册节点:tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>

标签节点用 headscale preauthkeys create --tags tag:<TAG>,客户端不用再传 --advertise-tags,tag 会自动从密钥读取。

补充:

  • Web 认证适合人工操作的终端设备;预认证密钥适合脚本、CI/CD、无人值守设备、批量部署。
  • 预认证密钥默认一次性、1 小时有效。要复用加 --reusable,要改有效期加 --expiration。
  • 忘了批准,节点会一直处于 pending 状态,headscale nodes list 能看到。
  • Headscale 数据库丢失 = 所有节点要重新认证,所以务必备份数据库。
  • 客户端注册后会保存状态;如果只是重启 Headscale,节点一般不用重新认证。
  • 标签节点注册时,Headscale 会检查 <USER> 是否有权注册该 tag,检查通过后节点归 tagged-devices。

3. OpenID Connect(OIDC)

Headscale 支持通过外部身份提供商进行 OIDC 认证。

配置

  • Headscale 侧:配置文件的 oidc 段包含所有可用选项、描述和默认值。
  • IdP 侧:参考你的身份提供商官方文档,下方也有各 IdP 的具体配置提示。

基本配置通常需要:

  • Issuer URL(Headscale 用 OpenID Connect Discovery 1.0 自动获取配置)
  • Client ID
  • Client Secret
  • Redirect URI(如 https://headscale.example.com/oidc/callback)

启用 PKCE(推荐):为 OAuth 2.0 授权码流程增加一层安全,防止授权码拦截攻击。Headscale 和 IdP 都要配。

用户过滤:可按域名、邮箱地址、群组成员资格过滤,多个过滤器需全部通过。默认禁用,认证成功即允许加入。

  • 按域名:只允许 example.com 域名的邮箱
  • 按邮箱:只允许 allowed_users 列表里的邮箱
  • 按群组:只允许特定群组成员

要求已验证邮箱,除非禁用邮箱验证。

控制邮箱验证:Headscale 使用 email_verified: true claim。IdP 不发送该 claim 或不需要验证时,可允许未验证邮箱。

自定义节点过期:通过顶层 node.expiry 配置。可手动让节点立即过期:

headscale node expire -i <NODE_ID>

在 policy 里引用用户:可用邮箱、用户名、提供商标识。用户标识必须包含单个 @。Headscale 用户名若不含 @,需在末尾追加,如 ssmith 写成 ssmith@。确保用户名本身不以 @ 结尾。

注意:很多 IdP 允许用户改自己资料,用户名或邮箱可能变,可能导致 policy 失效,或用户通过抢占已有用户名/邮箱获得更多权限。

提供商标识(providerId)唯一标识 OIDC 用户,行为良好的 IdP 保证它永不变。它是通常不透明的长字符串,目前只能从 API、数据库或 IdP 获取。可用 /api/v1/user 端点获取,在 policy 里引用时记得追加 @。

支持的 OIDC claims

Headscale 字段OIDC claim
邮箱email(仅同步已验证邮箱,除非禁用验证)
显示名name
用户名preferred_username
头像picture
提供商标识iss, sub
群组仅用于过滤

限制

  • 只提供有限的 IdP 特殊行为支持。
  • OIDC groups 不能用于 policy 规则。
  • 用户名需符合:至少两个字符、只含字母数字连字符点下划线和最多一个 @、以字母开头。

已知兼容的 IdP

Authelia、Authentik、Google OAuth、Kanidm、Keycloak、Microsoft Entra ID。

  • Authelia:完全支持。
  • Authentik:完全支持。Headscale 不支持 JSON Web Encryption,Encryption Key 留空。
  • Google OAuth:不发送 preferred_username,Headscale 里用户名会是空的。只需认证自己域名的用户可跳过验证流程。
  • Kanidm:完全支持。允许组过滤需用完整 SPN。默认发完整 SPN 作为 preferred_username,可配成短用户名。
  • Keycloak:完全支持。用组过滤需额外建 groups client scope 和 mapper。
  • Microsoft Entra ID:需注册 App,配正确 scope 和 redirect URI。用组过滤时不要 groups claim,组要用组 ID(UUID)。

切换 OIDC 提供商

Headscale 只支持单个 OIDC 提供商,但存储每个用户的 provider identifier。切换时所有用户详情可能相同但标识不同,会导致无法创建新用户。需手动更新 users 表的 provider_identifier 列,值由 ID token 的 iss 和 sub 组成。

补充:

  • OIDC 的核心价值是让用户自助注册,免去管理员手动 users create + 批准,适合多用户环境。
  • 启用后,用户首次登录会自动在 Headscale 里创建。
  • 用户名冲突是常见问题,尤其 Google 不返回 preferred_username 时。
  • 换 IdP 很痛,因为 provider_identifier 变了,得手动改数据库,这是已知痛点。
  • 建议生产开 PKCE,并配 allowed_domains / allowed_users / allowed_groups 做访问控制。
  • OIDC 的 groups 只能用于过滤,不能写进 policy 规则,官方明确限制。

4. Routes(路由)

Headscale 支持路由通告,可管理子网路由器和出口节点。

  • 子网路由器:把现有网络(VPC、本地网络)接入 tailnet,用于访问装不了 Tailscale 的设备,或逐步 rollout。
  • 出口节点:把另一个 Tailscale 节点的全部互联网流量路由出去,用于不可信 Wi-Fi 或需要固定出口 IP 的场景。

子网路由器

需要双端同意:节点端 + 控制服务器端。可选 autoApprovers 自动批准。

配置节点:

sudo tailscale up --login-server <URL> --advertise-routes=10.0.0.0/8,192.168.0.0/24

已注册节点用:

sudo tailscale set --advertise-routes=10.0.0.0/8,192.168.0.0/24

最后开启 IP 转发。

控制服务器批准:

headscale nodes list-routes
headscale routes enable -r <ROUTE_ID>

使用方:

sudo tailscale set --accept-routes

用 policy 限制:默认无策略时所有节点可用这些路由,配 policy 可明确管理。示例策略定义三台主机,允许普通节点通过子网路由器访问内部服务的 80/443 端口,拒绝访问路由器本身。

自动批准:policy 的 autoApprovers 段可自动批准带特定 tag 的路由器宣告的路由。

出口节点

同样双端同意,可选自动批准。

配置节点:

sudo tailscale up --login-server <URL> --advertise-exit-node

已注册节点:

sudo tailscale set --advertise-exit-node

最后开启 IP 转发。

控制服务器批准:

headscale nodes list-routes

出口节点特征:宣告 0.0.0.0/0 和 ::/0。批准 IPv4 或 IPv6 任一即可,另一个自动批准。

使用方:

sudo tailscale set --exit-node myexit

用 policy 限制:用 autogroup:internet 控制谁能用出口节点,也可按用户/组分配特定出口节点。示例:alice 只能用 tag:exit1 的出口节点,bob 只能用 tag:exit2。

自动批准:autoApprovers 的 exitNode 段可自动批准带特定 tag 的出口节点。

高可用

多个子网路由器或出口节点可提供高可用。至少两个节点宣告相同前缀时默认启用。详见配置项 node.routes.ha。

故障排查

子网路由器或出口节点需要 IP 转发,参考官方 Tailscale 文档。

补充:

  • 出口节点本质就是宣告 0.0.0.0/0 和 ::/0。
  • IP 转发没开是这类问题最高频的故障原因。Linux 上一般是 net.ipv4.ip_forward=1 和 net.ipv6.conf.all.forwarding=1。
  • 双端同意(double opt-in)是安全设计:节点宣告 + 服务器批准,避免节点擅自转发流量。
  • 多个节点宣告相同前缀时,客户端会自动选一个,这就是高可用的实现。
  • 策略里 autogroup:internet 是控制出口节点使用的关键。
  • 官方 Tailscale 文档有各系统开启 IP 转发的方法,可直接参考。

5. TLS

Headscale 可通过 TLS 暴露 Web 服务。

自带证书

设置 tls_cert_path 和 tls_key_path。相对路径相对于配置文件所在目录。证书应包含完整链,否则部分客户端(如 Android)会拒绝。

Let’s Encrypt / ACME

设置 tls_letsencrypt_hostname,该名称必须解析到 Headscale 可达的 IP(即对应 server_url)。证书和账号凭据存在 tls_letsencrypt_cache_dir。相对路径相对于配置文件所在目录。

挑战类型:只支持 HTTP-01(默认)和 TLS-ALPN-01。

  • HTTP-01:Headscale 需在 80 端口可达,默认监听所有本地 IP 的 80 端口。可用 tls_letsencrypt_listen 改,但 Let’s Encrypt 只连 80,需额外转发。适合非 root 用户或不能 setcap 的场景。
  • TLS-ALPN-01:Headscale 监听 listen_addr,Let’s Encrypt 只连 443,需额外转发。

技术说明

Headscale 用 autocert(Go 库)通过 Let’s Encrypt 做 ACME 验证:

  • 证书有效期 3 个月。
  • 剩余 30 天或更少时才尝试续期。
  • 续期尝试随机间隔 30–60 分钟。
  • 跳过或成功续期时无日志输出。

检查证书到期:浏览器打开看,或用 openssl 远程检查。

autocert 日志:如 missing server name 或 host not configured in HostWhitelist,通常是对 IP 或错误主机名的无效请求。这些日志来自 autocert 库,不是 Headscale 本身。

补充:

  • 生产环境强烈建议启用 TLS,否则客户端可能拒绝连接或出现安全警告。
  • 用反向代理终止 TLS 时,Headscale 可关自带 TLS,但要配 trusted_proxies。
  • 证书续期不用管,autocert 会自动处理,你只要保证 80 或 443 端口可达。
  • 证书要包含完整链,不然 Android 等客户端会拒。
  • 自签证书客户端可能不信任,需要手动加信任或(不推荐)禁用验证。

6. Policy(策略)

Headscale 实现了 Tailscale 大部分策略功能,包括基于 ACL 和 Grants 的访问控制,以及 Tailscale SSH。限制见下。

Headscale 用与 Tailscale 相同的 huJSON 格式。默认不加载策略 = 允许所有节点间流量。 启用需在配置文件设 policy.path。

改策略后需重载:sudo systemctl reload headscale 或 sudo kill -HUP $(pidof headscale)。重载后 Headscale 会记录策略处理结果。

参考 Tailscale 策略文档:policy file、ACLs、Grants。

入门

支持 ACL 和 Grants。推荐用 Grants,ACL 已被 Tailscale 视为 legacy,不再有新功能。

  • Allow All:定义策略文件但省略 "acls" 或 "grants" 段,默认允许所有。{}
  • Deny All:"grants" 为空数组。{ "grants": [] }
  • 更多示例见 Tailscale 文档。

限制

  • 不支持 device postures 及相关段(postures、srcPosture)。
  • 不支持 IP sets。
  • 只支持部分 Autogroups。

Autogroups

  • autogroup:internet:经出口节点访问互联网,只能用于目的地。
  • autogroup:member:所有成员。
  • autogroup:tagged:所有至少有一个 tag 的设备。
  • autogroup:self:源和目的地是同一用户的设备,不含标签设备,只能用于目的地。
  • autogroup:nonroot:Tailscale SSH 规则中允许访问除 root 外的任意用户,只能用于 SSH 规则的 users 字段。
  • autogroup:danger-all:解析为所有 IP(0.0.0.0/0 和 ::/0),包括 Tailscale IP 范围外的,只能作为源。

节点属性

支持的节点属性:

  • drive:access、drive:share:Taildrive 支持。
  • nextdns:<profile>、nextdns:no-device-info:NextDNS 集成,需在配置里设 NextDNS 为全局解析器。
  • magicdns-aaaa:在本地 MagicDNS 解析器 100.100.100.100 上响应 AAAA 查询。
  • disable-ipv4:为特定节点禁用 IPv4,可绕过 CGNat 冲突。
  • randomize-client-port:为 WireGuard 流量分配随机端口,而非默认 41641。
  • disable-captive-portal-detection:禁用自动 captive portal 检测。

网络级策略选项

  • randomizeClientPort:为 WireGuard 流量分配随机端口,而非默认 41641。

Headscale 也允许把策略存在数据库里,通常只有用 Web 界面时才需要。

补充:

  • 默认无策略 = 允许所有流量,多用户环境这是安全隐患,别长期这样。
  • 策略文件支持热重载,改完不用重启,这是它的一大优点。
  • 格式与 Tailscale 兼容,可直接参考 Tailscale 文档。
  • 常见用法:限制谁能访问谁、谁能用出口节点、谁能用子网路由、Tailscale SSH 规则。
  • Grants 比 ACL 新,建议新配置直接用 Grants。
  • 策略写太严是常见故障原因之一,排障时可以临时放宽验证。

7. DNS

Headscale 支持 Tailscale 大部分 DNS 功能。DNS 设置配在 dns 段。

设置额外 DNS 记录

可通过 MagicDNS 提供额外 DNS 记录,两种方式:

  • 静态:配置文件的 dns.extra_records,启动时处理,改动需重启。
  • 动态:dns.extra_records_path 指向 JSON 文件,Headscale 持续监视变化。适合运行时增删改,或脚本生成。

典型用例:同一主机上用反向代理(如 NGINX)跑多个应用,比如 Prometheus 监控栈,用 http://grafana.myvpn.example.com 代替 http://host:3000。

注意:

  • dns.extra_records_path 要指向 JSON 文件。
  • 脚本生成时排序键、输出稳定,Headscale 用校验和检测变化,稳定输出避免无谓处理。

用 DNS 查询工具验证记录是否正确。

可选:配置反向代理,示例中的 NGINX 片段用于不带端口访问内部监控服务。

补充:

  • MagicDNS 让节点用主机名互访,不用记 IP,这是 Tailscale 体验的核心之一。
  • 还可配全局 DNS 解析器、搜索域、split DNS。
  • 验证可用 dig / nslookup,或 tailscale dns status --all。
  • 动态记录适合配合自动化脚本,比如容器启动后自动注册 DNS。

8. DERP

DERP(Designated Encrypted Relay for Packets)用于无法直连时中继流量。Headscale 提供嵌入式 DERP 服务器。

配置

DERP 设置配在 derp 段,下面只用部分设置,全部选项见示例配置。

启用嵌入式 DERP:默认禁用,需启用。还应配 Headscale 的公网 IPv4 和 IPv6 地址以提高稳定性。DERP 还需额外端口,除中继外还用 STUN(udp/3478)帮助客户端发现公网 IP 和 NAT 穿透。检查 DERP 连通性确认。

移除 Tailscale 的 DERP 服务器:启用后 Headscale 的嵌入式 DERP 会加到 Tailscale 提供的免费 DERP 列表。想只用嵌入式,禁用默认 DERP 地图加载。

单点故障警告:移除 Tailscale DERP 意味着只剩一个 DERP 服务器,是单点故障,可能影响连通性。移除前先验证嵌入式 DERP 可用。

自定义 DERP 地图:用专用 YAML 文件,可修改通过 URL 获取的 DERP 地图,或提供自己的 DERP 服务器。免费 DERP 按 region ID 组织,可把某 region ID 设为 null 显式禁用。示例 derp.yaml 可禁用纽约(region ID 1),或引用两个自定义 region(ID 900、901)各一个自定义 DERP 服务器,每个提供 tcp/443 HTTPS 中继、tcp/80 captive portal 检查、udp/3478 STUN。全部选项见 DERPMap、DERPRegion、DERPNode 定义。可独立启用嵌入式 DERP 并自动加到自定义地图。

验证客户端:DERP 访问可限制为 tailnet 成员,未知客户端拒绝中继。Tailscale 的 derper 有两个参数:

  • -verify-client-url 指向 Headscale 的 /verify 端点(如 https://headscale.example.com/verify)。客户端连接时 DERP 查询 Headscale 是否允许。
  • -verify-client-url-fail-open 控制 Headscale 不可达时的行为,默认允许访问。

检查 DERP 连通性

  • 显示 DERP 地图:tailscale debug derp-map
  • 检查嵌入式 DERP 连通性:tailscale debug derp headscale

更多 DERP 指标和信息见 metrics 和 debug 端点。

限制

  • 嵌入式 DERP 不能用于 Tailscale 的 captive portal 检查,因为不支持 tcp/80 的 /generate_204。
  • 没有速度或吞吐优化,主要目的是协助节点连通性。

补充:

  • DERP 是兜底中继:能直连就走直连,不能才走 DERP。
  • 启用嵌入式 DERP 需开放 udp/3478 和 tcp/443。
  • 别急着关 Tailscale 官方 DERP,官方明确警告单点故障。先确认自己的能用再说。
  • DERP 只管连通性,不做速度优化,别当高速通道。
  • tailscale netcheck 能看到各 DERP 的延迟,帮助判断连通性。

9. API

Headscale 提供 HTTP REST API 和 gRPC 接口,用于集成 Web 界面、远程控制、自定义工具。

两者都需要有效 API key。创建(默认 90 天过期):

headscale apikeys create

保存输出,无法再次获取。丢失就过期旧的、建新的。

headscale apikeys list
headscale apikeys expire --prefix <PREFIX>

REST API

  • 端点:/api/v1,如 https://headscale.example.com/api/v1
  • 文档:/swagger
  • 版本:/version
  • 认证:Authorization: Bearer <API_KEY>

在 /swagger 看你自己服务器的 API 文档。

gRPC

用于从远程机器用 headscale 二进制控制实例。

前提:

  • 工作站运行 headscale(任意支持平台)
  • Headscale 服务启用 gRPC
  • gRPC 端口(默认 50443)放行
  • 远程访问需 TLS 加密连接
  • API key

设置远程控制:

  1. 从 GitHub release 下载 headscale 二进制,版本与服务器一致。
  2. 放到 PATH,如 /usr/local/bin/headscale。
  3. chmod +x /usr/local/bin/headscale。
  4. 在服务器创建 API key。
  5. 通过最小 YAML 配置或环境变量提供连接参数,让 headscale 连远程而非本地。
  6. 测试:headscale nodes list。

代理后面:gRPC 远程端点可放反向代理后(如 Nginx),与 Headscale 同端口。非官方支持,NixOS 示例见文档。

故障排查:

  • 版本一致
  • gRPC 端口放行
  • TLS 证书有效可信
  • 无受信证书时:加信任,或设 cli.insecure: true / HEADSCALE_CLI_INSECURE=1(不推荐)

补充:

  • REST API 适合集成 Web UI、写脚本、自动化。
  • API key 创建后只显示一次,务必保存。丢了只能删了重建。
  • /swagger 是开发集成的好入口,能直接看到所有端点和参数。
  • gRPC 用于远程用 headscale 命令控制服务器,版本必须一致。
  • 自签证书时要么加信任,要么(不推荐)禁用验证。

10. Tags

Headscale 支持 Tailscale tags。详见 Tailscale tag 文档。

Tags 可在节点注册时应用:

  • --advertise-tags,见 Web 认证的标签设备
  • 带标签的预认证密钥

管理员可用 Headscale CLI 或 API 管理 tags。

常用操作

管理节点 tags:

headscale nodes list
headscale nodes tag -i 1 -t tag:server,tag:prod

至少一个 tag,多个用逗号分隔。

个人节点 → 标签节点:

headscale nodes tag -i <NODE_ID> -t <TAG>

节点归 tagged-devices 用户所有。

标签节点 → 个人节点:

tailscale up --login-server <URL> --advertise-tags= --force-reauth
headscale auth register --user <USER> --auth-id <AUTH_ID>

旧 tag 全部移除,节点归指定用户。

补充:

  • Tags 是服务型节点的核心机制,配合 policy 做细粒度控制。
  • 标签节点在策略里用 tag:xxx 引用,适合表达「服务器」「生产环境」等语义。
  • 转回个人节点需要 --force-reauth 并重新批准,旧标签会被清空。
  • Tags + 策略是 Headscale 做细粒度访问控制的主要方式。

11. Reverse proxy(反向代理)

⚠️ 社区文档:非 Headscale 作者维护,未经开发者验证,可能过时或漏步骤。

同一服务器跑多个应用、复用外部 IP 和端口(通常 tcp/443)时有用。

配置

取决于你要用哪些功能。注意端口使用部分,了解 Tailscale 客户端期望什么。示例只覆盖 HTTP 和 HTTPS,STUN 等需直接暴露或只在 localhost。

WebSocket:Tailscale 客户端用自定义协议(Tailscale Control Protocol)与控制服务器通信。反向代理必须支持 WebSocket,并处理两个特殊点:

  • 用 POST 方法升级 WebSocket 连接。
  • Upgrade 头的值是 tailscale-control-protocol。

TLS:Headscale 可不用 TLS,交给反向代理。配置:

server_url: https://<SERVER_NAME>
tls_cert_path: ""
tls_key_path: ""

启动时 Headscale 会记录 WRN listening without TLS but ServerURL does not start with http://,这是预期的,表示反向代理负责终止 TLS。

受信任代理:Headscale 忽略 True-Client-IP、X-Real-IP、X-Forwarded-For,除非请求的 TCP peer 匹配 trusted_proxies。设为反向代理连接的 CIDR:

trusted_proxies:
  - 127.0.0.1/32
  - ::1/128

反向代理负责替换客户端传来的这些头。Headscale 按顺序取第一个有效 IP:True-Client-IP → X-Real-IP → X-Forwarded-For。

限制

  • 反向代理增加复杂度,需正确处理 Tailscale 控制协议。先不用代理测试再提 issue。
  • STUN(嵌入式 DERP)需公开 udp/3478。
  • gRPC(远程控制)可能无法代理。

各代理配置

基础 Headscale 配置(假设:443 HTTPS、代理终止 TLS 并重定向 HTTP、同主机、metrics 和 gRPC 不代理走 localhost):

server_url: https://<SERVER_NAME>
listen_addr: 127.0.0.1:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
trusted_proxies:
  - 127.0.0.1/32
  - ::1/128
tls_cert_path: ""
tls_key_path: ""
  • Apache:ProxyPass / http://127.0.0.1:8080/ upgrade=any(upgrade=any 必需,转发 Upgrade 头不是 WebSocket 的流量)
  • Caddy:自动证书、强制 HTTPS、代理 WebSocket
  • Cloudflare:不支持,Cloudflare 不支持 Tailscale 协议所需的 WebSocket POST
  • Envoy:需加 upgrade_type: tailscale-control-protocol
  • Istio:同 Envoy,用 EnvoyFilter 加 upgrade_type: tailscale-control-protocol
  • Nginx:proxy_http_version 1.1、设 Upgrade/Connection、proxy_buffering off

补充:

  • 核心难点就是 POST 升级 WebSocket,很多代理默认不认。
  • Caddy 最省心,证书和 WebSocket 都自动处理。
  • 先无代理跑通再加代理,便于定位问题。
  • 别忘了 /generate_204,客户端的连通性检测。
  • 代理必须替换客户端传来的 True-Client-IP、X-Real-IP、X-Forwarded-For,否则可能被伪造。
  • gRPC 和 STUN 一般不走代理,让它们走 localhost 或单独端口。

12. Web UI

⚠️ 社区贡献:非 Headscale 作者维护。

Headscale 不提供内置 Web 界面,用户可自选。

可用选项:

  • headscale-ui:Web 前端
  • HeadscaleUi:静态管理 UI,无需后端
  • Headplane:受 Tailscale 启发的高级前端
  • headscale-admin:简单现代的 Web 界面
  • ouroboros:面向用户管理自己设备,而非管理员
  • unraid-headscale-admin:Unraid 用,支持本地(docker exec)和 API 模式
  • headscale-console:基于 WebAssembly 的客户端,支持 SSH、VNC、RDP,可选自助服务
  • headscale-piying:支持可视化 ACL 配置
  • HeadControl:Go + HTMX 极简管理仪表板
  • Headscale Manager:Android 版
  • Headscale UI:在线及自托管

支持可在 Discord 的 web-interfaces 频道咨询。

补充:

  • 都是社区项目,非官方维护,质量活跃度参差。
  • 都通过 REST API 交互,先建 API key。
  • 用前评估项目活跃度、安全性、权限范围。
  • Web UI 不改变 Headscale 核心行为,只是管理界面。

13. Tools(工具)

⚠️ 社区贡献:非 Headscale 作者维护。

第三方工具、客户端库、脚本集合:

  • headscale-operator:Kubernetes Operator
  • tailscale-manager:动态管理 Tailscale 路由通告
  • headscalebacktosqlite:从 PostgreSQL 迁回 SQLite
  • headscale-pf:基于 Jumpcloud 或 Authentik 的用户组填充
  • headscale-client-go:Headscale HTTP API 的 Go 客户端
  • headscale-zabbix:Headscale 服务的 Zabbix 监控模板
  • tailscale-exporter:用 Headscale API 提供网络级指标的 Prometheus 导出器

补充:

  • 用前评估维护状态。
  • tailscale-exporter + Prometheus 适合监控。
  • headscale-client-go 适合二次开发。
  • headscale-operator 适合 K8s 环境。

14. Debug(调试与故障排查)

Headscale 和 Tailscale 提供调试和自省能力,帮助定位问题。另见 Tailscale 故障排查指南。

Tailscale 客户端

  • 本地网络状况:tailscale netcheck
  • 客户端状态:tailscale status --json
  • DNS 状态:tailscale dns status --all
  • 客户端日志:tailscale debug daemon-logs
  • 客户端 netmap:tailscale debug netmap
  • 测试 DERP 连接:tailscale debug derp headscale
  • 更多:tailscale debug --help

Headscale

应用日志:debug 和 trace 级别可获取更多信息。

log:
  level: debug

数据库日志:数据库 debug 模式记录所有查询,需应用日志级别为 debug 或 trace。

database:
  debug: false
log:
  level: debug

Metrics 和 debug 端点:可自省 Go 运行时信息、内存统计、已连接节点、待处理注册、活动策略、过滤器、SSH 策略、当前 DERPMap、Prometheus 指标。

保持私有:监听地址和端口由 metrics_listen_addr 配置,默认 localhost:9090。保持在内网,别暴露到互联网。 设 metrics_listen_addr: null 可完全禁用。

查询指标:http://localhost:9090/metrics,调试概览:http://localhost:9090/debug/。指标可从 localhost 外查询,但 debug 接口有额外保护。

访问方式:

  • 直接访问:在 Headscale 服务器上 curl http://localhost:9090/debug/
  • SSH 端口转发:ssh <HEADSCALE_SERVER> -L 9090:localhost:9090,本地浏览器打开 http://localhost:9090/debug/
  • 调试密钥:环境变量 TS_DEBUG_KEY_PATH 指向密钥文件,请求带 debugkey 参数,如 http://<IP>:9090/debug/?debugkey=<DEBUG_KEY>

补充:

  • 排查顺序:客户端状态 → 网络状况 → DERP 连通性 → Headscale 日志 → 数据库 → 策略。
  • tailscale netcheck 快速看 NAT 类型和 DERP 延迟。
  • debug/trace 日志信息量大,排障后记得调回。
  • debug 端点含敏感信息(节点、策略、DERPMap),务必只在内网开。
  • 常见故障:IP 转发没开、server_url 不匹配、TLS 证书问题、反向代理不支持 WebSocket、策略过严。
  • metrics 端点可接 Prometheus + Grafana 做长期监控。

15. 附录:常用命令速查

功能命令
校验配置headscale configtest
创建用户headscale users create <USER>
列出用户headscale user list
批准节点headscale auth register --user <USER> --auth-id <AUTH_ID>
创建预认证密钥headscale preauthkeys create --user <USER_ID>
列出节点headscale nodes list
列出路由headscale nodes list-routes
启用路由headscale routes enable -r <ROUTE_ID>
管理标签headscale nodes tag -i <ID> -t <TAG>
创建 API 密钥headscale apikeys create
重载策略sudo systemctl reload headscale
作者

老丹

关注我
其他文章
上一个

深入解读 udevadm info 输出:一块 Realtek RTL8851BU USB 无线网卡的完整身份档案

下一个

在 Ubuntu 上用 Docker Compose 手动搭建 Nextcloud:从基础到扩展的完整指南

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • 在 Windows 里养一只 Linux:WSL 完整指南 2026年10月24日
  • Paho MQTT C 与 C++ 客户端库完全指南:从概念到 Ubuntu 26.04 下的编译、安装与使用 2026年10月23日
  • Mosquitto $SYS 主题详解:Broker 自监控指南 2026年10月23日
  • 应用级 MQTT 服务搭建完全指南:Mosquitto + 宿主机 Nginx 2026年10月22日
  • OpenWrt 固件签名三剑客:usign、ucert 与 fwtool 深度解析 2026年10月21日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (21)
  • Linux服务配置 (53)
  • Linux系统 (16)
  • MQTT技术 (6)
  • OpenWrt路由 (5)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 问题解决 (3)
  • 防火墙 (6)
  • 音视频技术 (6)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号