TSLinkTSLink 文档

MCP 服务器托管

如何把 MCP 服务器托管在 TSLink 之后,获得零信任身份校验、加密传输与访问控制

查看 Markdown

为什么 MCP 服务器需要零信任

Model Context Protocol 把 AI 助手连接到外部工具、数据库和 API。MCP 服务器通常运行在 localhost 上,单机使用时这是安全的。安全挑战出现在你需要远程访问的时候:从另一台设备访问自己的 MCP 服务器、把它分享给团队成员,或者把它接入运行在其它机器上的 AI 工作流。

远程访问要求可达的传输与正确授权。具备应用控制的公开 HTTP endpoint 可以适用;所有 client 都能加入网络时,私有 tailnet endpoint 也可适用。本指南使用已运行的 HTTP MCP server,并保留它的应用授权。

关于 MCP 安全风险的详细分析,以及网络层安全为什么重要,请看为什么你的 MCP 服务器不该放在公共互联网上。

TSLink 提供另一条路:把 MCP 服务器托管在你的私有 Tailscale 网络上,每个服务拥有独立的 tailnet 身份、WireGuard 传输,并可为 proxy HTTP 服务选配 --allow 访问控制。默认没有公网暴露。TSLink 不创建任何 DNS 记录;tailnet 连通性仍然取决于 Tailscale 控制面和 DERP 的行为。

本页讲的是跨 tailnet 访问第三方 MCP 服务器。TSLink 自身也内置了一个 MCP 服务器,让 agent 可以直接驱动 TSLink,那部分见 TSLink 作为 MCP 服务器。

快速设置

先确认后端已通过 HTTP 提供 MCP,并记录实际端点路径,例如 http://localhost:8080/mcp。TSLink 代理该 HTTP 传输,不会把 stdio 服务器转换为 HTTP。注册前选择需要的 --allow 限制:

bash
tslink add mcp-tavily --proxy localhost:8080 --json

默认 add 已会确保后台网关运行。检查结果:如 data.status 为 needs_login,人需打开 data.auth_url,完成入网及 tailnet 要求的审批。随后轮询已有网关,取得服务实际 origin:

bash
tslink url mcp-tavily --wait

同时检查 tslink status --json;守护进程存活不代表服务已就绪。客户端应使用实际运行时 origin 加后端的 MCP 路径:后端使用 /mcp 时就在 origin 后保留 /mcp,使用其他路径时保留那个路径。MCP 传输规范定义的是完整端点路径,不只是主机名。

请使用连接实际从 tailnet 内设备发起的 HTTP MCP 客户端,例如支持 HTTP 传输的本地 CLI 客户端。Claude 的账户级 remote connector 从 Anthropic 云端连接,Desktop 中配置的这类 connector 也一样;笔记本可访问不能让云端访问此私有端点。Desktop 的本地 MCP 配置是另一种机制;本地 stdio 需要能启动进程的客户端,不能作为 claude.ai 的替代配置。见 Claude 网络要求。

默认 add 后不要再运行 serve。明确选择手动运行时,使用 --no-daemon-install 并满足手动网关前提。Tailnet 段使用 WireGuard,代理 HTTP 可携带尽力而为的 WhoIs 身份头;后端 MCP 授权仍需保留。

访问控制

用 --allow flag 限制哪些用户或组可以访问某个 MCP 服务器:

bash
tslink add mcp-tavily --proxy localhost:8080 --allow user@example.com

只有指定的用户能访问这个 MCP 服务器。其它所有请求都会收到 403 Forbidden 响应。

团队场景使用 Tailscale 标签:

bash
tslink add mcp-tavily --proxy localhost:8080 --allow tag:ai-team

标签在你的 Tailscale ACL 策略中定义。这样你可以通过已有的 Tailscale 身份基础设施管理 MCP 服务器的访问,无需在 TSLink 中做额外配置。

对 proxy HTTP 服务,TSLink 通过 WhoIs 解析 Tailscale 身份,并可以在每个请求上执行 --allow。MCP 客户端配置里不存放任何 TSLink 会话令牌、cookie 或凭证。MCP 服务器需要工具级策略的地方,请继续保留 MCP 应用层授权。

多个 MCP 服务器

每个 MCP 服务器都获得自己的 TSLink 服务,拥有独立的身份和访问控制:

bash
# Web 搜索工具,整个团队可用
tslink add mcp-tavily --proxy localhost:8080 --allow tag:ai-team

# GitHub 集成,仅限开发者
tslink add mcp-github --proxy localhost:8081 --allow tag:developers

# 数据库访问,仅限数据团队
tslink add mcp-postgres --proxy localhost:8082 --allow tag:data-team

# 内部知识库,仅限特定用户
tslink add mcp-docs --proxy localhost:8083 --allow admin@example.com

每个 MCP 服务器运行在自己的 WireGuard 节点上,拥有不同的 tailnet 身份。这是网络分段,并非主机隔离。攻破一台服务器本身不会让攻击者获得另一台服务器节点的 tailnet 访问权,但被攻破的进程仍然可以通过其它路径触达同一主机上的其它资源。这种按服务的微分段体现了 NIST SP 800-207 零信任架构的一条核心原则(原则 1:所有计算服务都被视为独立资源)。

每次 add 已会确保网关运行。完成可能的 needs_login / auth_url 授权,再对每个服务轮询 tslink url <name> --wait,取得实际运行时 origin,并在客户端端点保留对应后端的 MCP 路径。不要另行启动 serve。

网关运行期间可以随时添加或移除 MCP 服务器。TSLink 监视服务注册表,通过热重载应用变更,其它活跃服务保持运行。

监控:用于 MCP 审计的访问日志

用 tslink access log --app my-mcp --since 24h 查看有界本地 HTTP 历史,WhoIs 可用时提供身份。它记录网关访问,不解析第三方 MCP 工具语义;身份可能缺失,记录可能丢失或有缺口,见访问历史。后端身份传播是另一项行为;tslink logs 读取 stderr daemon 诊断,不替代该查询入口。

bash
tslink logs --source err --last 100
tslink logs --level error

守护进程日志文件存放在 ~/.config/tslink/logs/ 下(tslink.out.log 和 tslink.err.log)。TSLink 没有 serve 的日志格式切换开关;做聚合时请使用 tslink logs 或直接读取日志文件。

TSLink 在网络层和传输层保护 MCP 服务器:

TSLink 提供TSLink 不提供
WireGuard 加密的 tailnet 传输(后端跳转可能是明文)MCP 协议内部的应用层授权
尽力而为的身份检查(WhoIs,缓存 60 秒),通过 --allow 执行MCP 工具调用的输入校验
按服务的 tailnet 身份(网络分段,并非主机隔离)MCP 响应的内容过滤
通过 --allow 的访问控制按 MCP 工具的速率限制(路线图)
有界本地访问历史MCP 专属的协议检查

TSLink 与 OAuth 授权这类 MCP 应用层安全特性是互补关系。网络层安全(加密、身份、分段)和应用层安全(授权、输入校验)都是必需的。单靠任何一层都不够。

目录