Headscale 单向策略下两个节点为何仍互相出现在 tailscale status 输出中?
【免费下载链接】headscaleAn open source, self-hosted implementation of the Tailscale control server项目地址: https://gitcode.com/GitHub_Trending/he/headscale
你在 Headscale 上配置了一条单向访问策略——比如管理端节点可以访问其他节点,反向不允许——但随后在任意一个节点上运行tailscale status时,发现两个节点互相出现在对方的输出里。这容易让人怀疑策略没有生效。根据 Headscale FAQ,这是 Tailscale 的正常设备可见性行为,不是策略失效:只要流量被允许在某个方向流动,两个节点就会在彼此的tailscale status输出中互相出现。
本文解决的任务是:在确认"互相可见"属于预期行为的前提下,用文档提供的命令核实你的单向策略确实已加载并生效,避免把正常现象误判为故障。
为什么 status 互相可见不等于双向互通
FAQ 对这一现象的结论是:
- 如果流量被允许在一个方向上流动,那么两个节点都会在
tailscale status的输出中看到对方。这是 Tailscale 本身的工作方式,Headscale 作为控制服务器遵循同样行为。 - 实际流量仍按策略过滤,即被拒绝的方向上的流量不会通过。
- 唯一的例外是
tailscale ping:它在两个方向上始终被允许,与策略无关。
由此得到两条判断规则:
- 两个节点在
tailscale status中互相出现,不能证明策略失效,也不能证明双向互通。 - 不要用
tailscale ping能否双向通来判断单向策略是否生效——它本来就是双向必通的。
先确认单向策略真的已加载
在排查"策略不生效"之前,先排除最常见的原因:策略文件根本没有加载。根据 策略文档,Headscale 默认不加载任何策略,此时所有节点间流量全部放行。策略文件通过配置文件的policy.path键指定,配置文件本身的查找位置与校验方式见 配置文档(/etc/headscale、$HOME/.headscale、当前工作目录,或-c参数指定路径,headscale configtest校验配置)。
单向策略的写法
Headscale 使用与 Tailscale 相同的 huJSON 文件格式,文档推荐使用 Grants 而不是已废弃的 ACLs。FAQ 描述的高频场景正是"允许流量只从一个节点流向另一个节点,反向不允许"。按 策略文档 中 grants 的src/dst/ip结构,一条单向规则的示例如下(文档示例格式,<源用户>、<目标用户>需替换为你 tailnet 中的实际用户名,替换对象是发起方与接收方在 Headscale 中的用户):
{ "grants": [ { "src": ["<源用户>@"], "dst": ["<目标用户>@"], "ip": ["*"] } ] }校验策略并重新加载
修改策略文件后,Headscale 需要重新加载才会应用(策略文档 docs/ref/policy.md):
# 1. 校验策略文件,确认语法与引用无误 headscale policy check --file policy.json # 2. 重新加载 Headscale(二选一) sudo systemctl reload headscale # 或 sudo kill -HUP $(pidof headscale)每次 reload 之后,Headscale 会把策略处理的结果记入日志,这是判断本次加载是否成功的第一手依据。
如果你的策略存储在数据库中,FAQ 给出了直接读写数据库的命令,注意这类命令要求提供包含数据库设置的完整服务器配置,仅够远程 CLI 控制的最小配置不够用;可用headscale -c /path/to/config.yaml指定配置路径:
headscale policy get --bypass-server-and-access-database-directly > policy.json headscale policy check --file policy.json headscale policy set --bypass-server-and-access-database-directly --file policy.json验证策略状态与预期现象
确认策略已加载后,从服务端和客户端两侧各做一次核对:
服务端:查看当前生效的策略
# 打印当前 ACL Policy(HuJSON 格式) headscale policy get输出的应当是你刚写入的单向规则。另外,Headscale 的 metrics 和 debug 端点(默认监听 localhost 的 9090 端口)可以查看当前生效的 active policy 和 filters,见 调试文档。在 Headscale 所在服务器上直接访问:
curl http://localhost:9090/debug/该端点应保持内网私有,不要暴露到互联网(调试文档的明确要求)。
客户端:观察 status 输出
在两个节点上分别运行:
tailscale status --json预期现象:双方仍互相出现在输出中。按 FAQ 的结论,这正是策略正确加载时的预期结果,不应视为异常。
边界提醒:tailscale ping双向始终可达,即使策略只允许单向。所以验证单向策略时,"ping 通"不构成任何方向的判断依据;真正的流量方向过滤以策略为准。
策略非法时的相关限制
FAQ 还记录了一个与本场景相邻的故障形态:当策略存储在数据库中且内容非法时,Headscale 在启动阶段校验策略,检测到错误会拒绝启动,错误信息会指明策略中哪一部分非法。恢复路径为:headscale policy get导出策略到文件 → 修正文件 →headscale policy check --file policy.json校验 →headscale policy set写回 → 正常启动 Headscale。
如果核对后发现headscale policy get输出的并不是你预期的单向规则,或者 reload 日志显示策略处理失败,问题出在"策略未正确加载"这一层,应按上文重新走校验与加载流程,而不是继续在客户端侧排查。反之,若策略确认生效,那么tailscale status中的互相可见就是预期行为,无需进一步处理。
【免费下载链接】headscaleAn open source, self-hosted implementation of the Tailscale control server项目地址: https://gitcode.com/GitHub_Trending/he/headscale
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考