自建 Headscale(Tailscale 控制服务器)踩坑全记录

从 “Connection was forcibly closed” 到腾讯云备案拦截的完整排查过程

摘要

最近在 Ubuntu 服务器上部署 Headscale + Nginx 作为 Tailscale 的自建控制服务器时,Windows 客户端执行 tailscale up 命令长时间无响应,出现 “An existing connection was forcibly closed by the remote host” 等错误。

经过多轮排查,发现问题层层递进:Nginx 配置缺失 WebSocket 支持 → SSL/TLS 握手失败 → 最终根源是腾讯云对域名的备案拦截

本文完整记录了定位思路、关键命令、修复方案和经验教训,供有同样需求的同学参考。

关键词:Headscale、Tailscale 自建控制服务器、Nginx 反向代理、WebSocket、腾讯云 ICP 备案、webblock.html

一、问题现象

在 Windows 主机使用 Git Bash 执行以下命令时,客户端长时间卡住无反应:

tailscale up --login-server=https://example.ltd \
  --authkey=****** \
  --reset --force-reauth

客户端日志显示类似错误:

An existing connection was forcibly closed by the remote host.  

进一步测试 curl -v https://example.ltd 也报错:

schannel: failed to receive handshake, SSL/TLS connection failed

切换为 HTTP 测试:
curl -v http://example.ltd

返回结果为腾讯云拦截页面:

HTTP/1.1 302 OK
Location: https://dnspod.qcloud.com/static/webblock.html?d=example.ltd

Tailscale 日志同时出现:

invalid character '<' looking for beginning of value
key hex has the wrong size, got 16776 want 64

二、初步分析与排除

TCP 连接能建立,但很快被远端 RST,说明问题不在本地防火墙或网络连通性,而是在服务器端 SSL/TLS 握手或应用层。
Nginx 日志无记录,请求很可能在到达 Nginx 前就被云厂商拦截,或 SSL handshake 在 Nginx 处理前失败。
HTTP 返回腾讯云 webblock.html,这是腾讯云(DNSPod)对未备案或备案不匹配域名的典型拦截页面。流量并未真正进入自己的 Nginx + Headscale 服务。
Tailscale 客户端收到的是 HTML 内容而非 JSON,导致解析失败(< 开头 + key 长度错误)。

结论:问题核心不在 Tailscale/Windows 客户端,也不在 Headscale 本身,而是 域名备案 + Nginx 配置 的双重问题。

三、排查步骤

步骤 1:检查并优化 Nginx 配置(重点修复 WebSocket)

原配置缺少 WebSocket 支持,导致即使流量到达也容易被关闭。推荐在 http {} 块中添加以下配置:

map $http_upgrade $connection_upgrade {
    default      upgrade;
    ''           close;
}

server {
    listen 443 ssl http2;
    server_name example.ltd;
    server_tokens off;
    keepalive_timeout 75;

    ssl_certificate /path/to/your_cert_bundle.crt;   # 使用绝对路径
    ssl_certificate_key /path/to/your_key.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://127.0.0.1:8081;   # Headscale 实际监听端口

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_buffering off;
        proxy_read_timeout 3600;
    }
}

# HTTP 强制跳转到 HTTPS
server {
    listen 80;
    server_name example.ltd;
    return 301 https://$host$request_uri;
}

执行命令测试并重载:
nginx -t && systemctl reload nginx

步骤 2:验证证书与端口监听

# 检查证书文件
ls -l /etc/nginx/*.crt /etc/nginx/*.key

# 检查端口监听
ss -ltnp | grep -E ':80|:443|:8081'

# 查看当前生效配置
nginx -T | grep -A 30 "server_name example.ltd"

步骤 3:临时切换 HTTP 测试(绕过 SSL)

把 443 配置临时注释,只保留 80 端口 proxy 测试。此时发现流量仍被腾讯云拦截,返回 webblock.html。

步骤 4:确认备案情况

访问 https://beian.miit.gov.cn/ 查询域名 example.ltd 的 ICP 备案信息。
常见问题:

备案未通过或未同步
主体/接入商与腾讯云不匹配
仅域名实名,未完成网站备案
备案通过后仍需 24-48 小时生效

四、最终根因与解决方案

根因:
腾讯云服务器 + 未完成有效 ICP 备案的域名,会在网络层直接拦截 80/443 流量,返回 webblock.html 或 RST 连接。Nginx 配置问题(WebSocket 缺失、证书路径)加剧了早期握手失败。
推荐解决方案(优先级排序):

完成 ICP 备案(最彻底)
通过腾讯云控制台提交备案申请(准备身份证/营业执照、网站截图等)。
备案通过并同步后,拦截自动解除。
备案后请在网站底部添加备案号(合规要求)。
临时绕过方案
更换一个已备案的域名。
将域名 A 记录解析到非腾讯云 IP(香港服务器或海外 VPS),绕过大陆 ICP 拦截。
短期可使用 Tailscale 官方控制服务器 login.tailscale.com 作为过渡。

优化 Nginx + Headscale
Headscale config.yaml 中 server_url 必须使用 https:// + 正确域名。
确保 Headscale 监听端口与 Nginx proxy_pass 一致。
建议 ssl_protocols 只保留 TLSv1.2 TLSv1.3。

五、经验教训与建议

自建 Headscale 在国内服务器上,域名 ICP 备案是硬性门槛,不要以为“应该已经备案了”就一定没问题,必须亲自查询验证。
Nginx 代理 Tailscale/Headscale 时,WebSocket 支持是必备(Upgrade + Connection header)。
排查时优先使用 curl -v 测试,结合客户端日志,能快速定位是握手失败、应用层错误还是云拦截。
建议把证书路径改为绝对路径,避免相对路径加载失败。
如果使用腾讯云轻量应用服务器,拦截机制会更严格,提前规划备案时间。

整个排查过程从最初的 “远端强制关闭连接” 到发现腾讯云备案拦截,花了几个小时,但一步步缩小范围后定位非常清晰。希望这篇记录能帮到同样在自建 Tailscale 控制服务器的朋友。

参考资料

Headscale 官方反向代理文档(WebSocket 配置)
腾讯云 ICP 备案指南
Nginx proxy WebSocket 最佳实践

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐