From 81e5d331ca856939b002d9b1d9fea1ad745f86e2 Mon Sep 17 00:00:00 2001 From: Citrons <909229731@qq.com> Date: Mon, 17 Aug 2026 12:25:13 +0800 Subject: [PATCH] =?UTF-8?q?docs(FEAT-DS-001):=20=E6=96=B0=E5=A2=9E=20Tails?= =?UTF-8?q?cale=20TDX=20=E5=BC=80=E5=8F=91=E6=93=8D=E4=BD=9C=E6=89=8B?= =?UTF-8?q?=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/deployment/tailscale-tdx-development.md | 377 ++++++++++++++++++ .../implementation-plan.md | 2 +- .../manifest.yaml | 2 +- docs/index.md | 1 + 4 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 docs/deployment/tailscale-tdx-development.md diff --git a/docs/deployment/tailscale-tdx-development.md b/docs/deployment/tailscale-tdx-development.md new file mode 100644 index 0000000..67f272c --- /dev/null +++ b/docs/deployment/tailscale-tdx-development.md @@ -0,0 +1,377 @@ +# Tailscale + SSH 隧道访问 TDX 开发手册 + +## 1. 用途与适用边界 + +本手册用于 Mac 本地开发期间,按需访问家中 Windows 上仅监听回环地址的 TDX HTTP 接口。链路只用于真实字段核验和只读冒烟,不是生产采集、数据上报或公网部署方案。 + +```text +Mac 本地程序 + -> 127.0.0.1:17710 + -> SSH 本地端口转发 + -> Tailscale 私有网络 + -> Windows OpenSSH + -> Windows 127.0.0.1:17709 + -> TDX +``` + +日常开发默认使用仓库内固定样本。只有需要验证 TDX 真实协议和字段时才启动本隧道;Windows 离线不得阻塞普通开发、测试或构建。 + +## 2. 安全边界 + +- 不在路由器上开放或转发 SSH、RDP、`17709`、`17710` 等端口。 +- TDX 继续只监听 Windows `127.0.0.1:17709`,不得改为 `0.0.0.0`。 +- SSH 使用独立 Ed25519 密钥,不在脚本、仓库、文档或远程 URL 中保存密码和私钥。 +- Mac 转发端口只绑定 `127.0.0.1:17710`,不得绑定局域网或所有网卡。 +- 真实返回只用于只读验证。日志和测试报告必须脱敏,不保存家庭网络信息、登录信息或无关原始载荷。 +- 开发隧道不连接生产数据库、不承担生产采集,也不证明数据源具备商业展示或再分发授权。 + +文档中的值均为占位符: + +- ``:Windows 的 Tailscale MagicDNS 名称或 Tailscale IP。 +- ``:用于 SSH 登录的 Windows 用户。 +- ``:Mac 的 Tailscale IP,仅在收紧防火墙来源时使用。 + +## 3. 首次建立 Tailscale 网络 + +### 3.1 Mac + +1. 从 Tailscale 官方渠道安装客户端。 +2. 登录项目使用的同一个 Tailnet。 +3. 确认菜单栏中的 Tailscale 状态为已连接。 +4. 在终端检查本机和节点列表: + +```bash +tailscale ip -4 +tailscale status +``` + +### 3.2 Windows + +1. 从 Tailscale 官方渠道安装客户端。 +2. 登录与 Mac 相同的 Tailnet。 +3. 确认 Windows 节点在 Tailscale 管理后台和 Mac 的 `tailscale status` 中均为在线。 +4. 在 Windows PowerShell 中检查地址和状态: + +```powershell +tailscale ip -4 +tailscale status +``` + +### 3.3 私网连通验证 + +在 Mac 执行: + +```bash +tailscale ping +``` + +只有 Tailscale ping 成功后再排查 SSH。不要用公网 IP 替换占位符,也不要为排障临时开放路由器端口。 + +## 4. 配置 Windows OpenSSH Server + +以下命令在 Windows 管理员 PowerShell 中执行。 + +### 4.1 安装并启动服务 + +```powershell +Get-WindowsCapability -Online | Where-Object Name -Like 'OpenSSH.Server*' +Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 +Start-Service sshd +Set-Service -Name sshd -StartupType Automatic +Get-Service sshd +``` + +如果 OpenSSH Server 已安装,`Add-WindowsCapability` 可以跳过。`Get-Service sshd` 应显示服务正在运行且启动类型为自动。 + +检查端口监听: + +```powershell +Get-NetTCPConnection -LocalPort 22 -State Listen +``` + +### 4.2 确认防火墙规则 + +OpenSSH 安装通常会创建入站规则。先检查,不要重复创建同名规则: + +```powershell +Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue +``` + +首次联调可以保留系统创建的 SSH 规则;链路确认后按第 11 节限制为 Tailscale 来源。不得新增公网端口映射。 + +## 5. 配置 SSH 密钥登录 + +### 5.1 在 Mac 生成项目专用密钥 + +```bash +ssh-keygen -t ed25519 -a 100 -f ~/.ssh/tdx_windows -C "tdx-windows-development" +chmod 600 ~/.ssh/tdx_windows +chmod 644 ~/.ssh/tdx_windows.pub +pbcopy < ~/.ssh/tdx_windows.pub +``` + +私钥 `~/.ssh/tdx_windows` 只保留在 Mac,不发送给 Windows,也不提交仓库。建议为私钥设置口令,并由 macOS 钥匙串或 `ssh-agent` 管理。 + +### 5.2 Windows 管理员账户 + +Windows OpenSSH 默认从 `C:\ProgramData\ssh\administrators_authorized_keys` 读取管理员公钥。必须先创建文件,再设置 ACL;否则 `icacls` 会报“系统找不到指定的文件”。 + +在管理员 PowerShell 中执行,按提示粘贴刚复制的单行公钥: + +```powershell +$authorizedKeys = "$env:ProgramData\ssh\administrators_authorized_keys" +New-Item -ItemType Directory -Force -Path (Split-Path $authorizedKeys) +if (-not (Test-Path $authorizedKeys)) { + New-Item -ItemType File -Path $authorizedKeys +} +$publicKey = Read-Host '粘贴 Mac 的单行 SSH 公钥' +if (-not (Get-Content $authorizedKeys | Where-Object { $_ -eq $publicKey })) { + Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii +} +icacls $authorizedKeys /inheritance:r +icacls $authorizedKeys /grant "*S-1-5-18:F" "*S-1-5-32-544:F" +Restart-Service sshd +``` + +`S-1-5-18` 是 SYSTEM,`S-1-5-32-544` 是本地 Administrators 组。使用 SID 可以避免中文 Windows 的组名本地化问题。 + +### 5.3 Windows 非管理员账户 + +非管理员账户使用用户目录下的 `authorized_keys`。在该登录用户自己的 PowerShell 中执行: + +```powershell +$sshDirectory = "$env:USERPROFILE\.ssh" +$authorizedKeys = "$sshDirectory\authorized_keys" +New-Item -ItemType Directory -Force -Path $sshDirectory +if (-not (Test-Path $authorizedKeys)) { + New-Item -ItemType File -Path $authorizedKeys +} +$publicKey = Read-Host '粘贴 Mac 的单行 SSH 公钥' +if (-not (Get-Content $authorizedKeys | Where-Object { $_ -eq $publicKey })) { + Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii +} +icacls $authorizedKeys /inheritance:r +icacls $authorizedKeys /grant "$($env:USERNAME):F" +Restart-Service sshd +``` + +管理员和非管理员两种方式只选与实际账户匹配的一种。若修改了 `C:\ProgramData\ssh\sshd_config`,先执行 `sshd -t` 校验,再重启服务。 + +## 6. 配置 Mac SSH 别名 + +编辑 Mac 的 `~/.ssh/config`,加入: + +```sshconfig +Host tdx-windows + HostName + User + IdentityFile ~/.ssh/tdx_windows + IdentitiesOnly yes + ServerAliveInterval 30 + ServerAliveCountMax 3 + ExitOnForwardFailure yes + LocalForward 127.0.0.1:17710 127.0.0.1:17709 +``` + +然后修正权限: + +```bash +chmod 700 ~/.ssh +chmod 600 ~/.ssh/config ~/.ssh/tdx_windows +``` + +首次连接先验证密钥登录: + +先在 Windows 管理员 PowerShell 查看主机公钥指纹: + +```powershell +ssh-keygen -lf "$env:ProgramData\ssh\ssh_host_ed25519_key.pub" +``` + +再在 Mac 连接,并确认首次连接提示的 Ed25519 指纹与 Windows 输出一致: + +```bash +ssh -v tdx-windows +``` + +预期可以直接登录,或只要求输入私钥口令。若仍要求 Windows 账户密码,重点检查公钥文件位置、ACL、登录账户是否属于 Administrators,以及 SSH 调试输出中实际使用的密钥。 + +## 7. 启动和停止隧道 + +### 7.1 前台运行 + +适合首次验证,按 `Ctrl+C` 停止: + +```bash +ssh -N tdx-windows +``` + +### 7.2 后台运行 + +使用独立控制套接字启动,便于精确停止本项目隧道: + +```bash +ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows +ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows +``` + +停止后台隧道: + +```bash +ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows +``` + +如果控制套接字残留但进程已不存在,先确认 `17710` 没有监听,再删除该单个套接字文件。不要用宽泛的 `pkill ssh`,以免终止其他 SSH 会话。 + +## 8. 验证 TDX 链路 + +### 8.1 Windows 本机验证 + +先确认 TDX 客户端已启动、已登录,接口监听 `127.0.0.1:17709`: + +```powershell +Get-NetTCPConnection -LocalAddress 127.0.0.1 -LocalPort 17709 -State Listen +``` + +端口没有监听时,应先恢复 TDX 客户端;SSH 和 Tailscale 无法替代 TDX 服务本身。 + +### 8.2 Mac 端口验证 + +隧道启动后在 Mac 执行: + +```bash +nc -vz 127.0.0.1 17710 +lsof -nP -iTCP:17710 -sTCP:LISTEN +``` + +`17710` 的监听进程应为本次 SSH 隧道,不应是其他应用。 + +### 8.3 只读 HTTP 冒烟 + +```bash +curl --fail-with-body --silent --show-error \ + --connect-timeout 3 \ + --max-time 10 \ + -H 'Content-Type: application/json' \ + -X POST 'http://127.0.0.1:17710/' \ + --data '{"id":1,"method":"get_market_data","params":{"stock_list":["600519.SH"],"count":5,"dividend_type":"none","period":"1d"}}' +``` + +链路验收条件:HTTP 返回成功,且 TDX 业务响应中的错误码表示成功。只验证少量公开行情,不调用交易、账户、自选、写入或大批量接口。 + +## 9. 外网场景验证 + +在真正离开家庭网络前,使用 Mac 手机热点或其他外部网络完成一次演练: + +1. 确认 Windows 保持开机、联网,Tailscale 和 `sshd` 在线,TDX 已启动并登录。 +2. Mac 切换到外部网络后重新连接 Tailscale。 +3. 执行 `tailscale ping `。 +4. 执行 `ssh -N tdx-windows` 并保持终端运行。 +5. 依次执行 `nc` 和只读 `curl` 冒烟。 +6. 停止隧道,确认 `127.0.0.1:17710` 不再监听。 + +如果外网演练失败,日常开发继续使用固定样本。不要临时开放公网 SSH、RDP 或 TDX 端口。 + +## 10. Windows 无人值守准备 + +当前链路是开发辅助,不承诺生产级 7x24 可用性。为了减少外出后无法联调的概率,可在 Windows 上做以下准备: + +- 将虚拟机配置为宿主机启动后自动启动,并确认异常关机后的恢复策略。 +- 保持 Tailscale 与 `sshd` 服务自动启动,重启后通过另一台 Tailnet 设备验证在线状态。 +- 接通电源时禁用自动睡眠: + +```powershell +powercfg /change standby-timeout-ac 0 +``` + +- 明确 TDX 是否需要交互式桌面登录、验证码或人工确认。需要人工登录时,不得把它描述为无人值守服务。 +- 安排 Windows 更新和虚拟机重启窗口;更新后重新验证 Tailscale、SSH、TDX 监听和只读请求。 +- 不为自动启动把 Windows 密码、TDX 凭据或 SSH 私钥写入仓库和普通脚本。 + +## 11. 收紧访问范围 + +链路验证通过后,在 Tailscale 管理后台将访问规则限制为指定开发身份或 Mac 到 Windows SSH 端口。具体策略应以当前 Tailnet 的身份和标签设计为准,不在仓库保存真实账户和地址。 + +还可在 Windows 中新增一条仅允许 Mac Tailscale IP 访问 SSH 的规则。先确认 Tailscale 网卡名称,再创建规则: + +```powershell +Get-NetAdapter | Where-Object InterfaceDescription -Match 'Tailscale' +New-NetFirewallRule ` + -DisplayName 'OpenSSH Server - Tailscale Mac Only' ` + -Direction Inbound ` + -Action Allow ` + -Protocol TCP ` + -LocalPort 22 ` + -RemoteAddress '' ` + -InterfaceAlias 'Tailscale' +``` + +新规则必须在外网场景实测通过后,才能禁用范围更宽的旧 SSH 规则。若实际网卡别名不是 `Tailscale`,使用 `Get-NetAdapter` 显示的名称,不凭猜测修改。 + +## 12. 故障排查 + +### Tailscale ping 不通 + +- 检查两端是否登录同一个 Tailnet、节点是否过期、Windows 是否睡眠或断网。 +- 检查 Tailnet ACL 或设备审批状态。 +- 不要先排查 TDX;此时底层私网尚未连通。 + +### SSH 连接超时或拒绝 + +- Windows 执行 `Get-Service sshd` 和 `Get-NetTCPConnection -LocalPort 22 -State Listen`。 +- 检查 Windows 防火墙和 Tailscale 访问规则。 +- Mac 执行 `ssh -vvv tdx-windows`,确认目标是 Tailscale 地址而非家庭公网地址。 + +### SSH 仍要求 Windows 密码 + +- 确认 `IdentityFile` 指向 `~/.ssh/tdx_windows`,并检查 `ssh -vvv` 是否提供了该密钥。 +- 管理员账户确认文件是 `C:\ProgramData\ssh\administrators_authorized_keys`;非管理员账户确认文件是用户目录下的 `.ssh\authorized_keys`。 +- 确认公钥为完整单行文本,文件已先创建,ACL 没有继承无关权限。 +- 执行 `sshd -t` 检查配置,再执行 `Restart-Service sshd`。 + +### Mac 的 `17710` 无法监听 + +- 查看 SSH 前台错误;`ExitOnForwardFailure yes` 会在端口冲突或转发失败时直接退出。 +- 执行 `lsof -nP -iTCP:17710 -sTCP:LISTEN` 查找占用者。 +- 不要把本地端口改成 `0.0.0.0`;需要换端口时同步修改本机开发配置,并保持回环绑定。 + +### 端口可连但 HTTP 失败 + +- 在 Windows 本机确认 TDX `127.0.0.1:17709` 正在监听。 +- 确认 TDX 客户端已登录且当前版本仍支持目标方法。 +- 使用最小只读请求检查 HTTP 状态、TDX 错误码和响应时间,不把协议错误误判为网络错误。 + +### 外出后 Windows 不在线 + +- 无法远程唤醒或恢复交互式 TDX 登录时,切回固定样本继续开发。 +- 不通过新增公网暴露、共享密码或关闭防火墙绕过问题。 +- 待公网部署需求明确后,另立功能实现生产级采集器、心跳、补传和远程运维。 + +## 13. 日常操作速查 + +开始真实 TDX 联调: + +```bash +tailscale ping +ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows +ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows +nc -vz 127.0.0.1 17710 +``` + +结束联调: + +```bash +ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows +lsof -nP -iTCP:17710 -sTCP:LISTEN +``` + +最后一条命令无输出表示本地转发已经停止。 + +## 14. 后续 Provider 接入约束 + +- 平台配置只能引用 Mac 回环地址 `127.0.0.1:17710`,不得保存家庭网络地址。 +- 真实 TDX Provider 必须显式启用;默认仍为确定性的固定样本 Provider。 +- Provider 必须限制请求超时、响应体大小、股票数量和并发,并输出来源、采集时间、交易日期、协议版本、追踪 ID 和陈旧状态。 +- TDX 原始字段仅在 Adapter 内转换,上层市场概览、规则分析和 AI 分析只依赖版本化内部契约。 +- 隧道中断必须返回明确的不可用或陈旧状态,不能把固定样本伪装成实时行情。 +- Windows 采集器、公网接收 API、多目标推送、补传队列和无人值守运维继续延期,实施时单独立项并重新进行安全、性能和合规评估。 diff --git a/docs/features/FEAT-DS-001-tdx-ingestion-poc/implementation-plan.md b/docs/features/FEAT-DS-001-tdx-ingestion-poc/implementation-plan.md index d391ddb..8b4a194 100644 --- a/docs/features/FEAT-DS-001-tdx-ingestion-poc/implementation-plan.md +++ b/docs/features/FEAT-DS-001-tdx-ingestion-poc/implementation-plan.md @@ -4,7 +4,7 @@ 1. 建立与运行时无关的 `DataProvider`、市场事件和数据新鲜度契约。 2. 用固定样本 Provider 支撑市场概览的规则、AI、混合和对照分析开发。 -3. 通过已有 Tailscale SSH 隧道执行真实 TDX 只读请求,保存脱敏字段报告。 +3. 按 [Tailscale + SSH 隧道访问 TDX 开发手册](../../deployment/tailscale-tdx-development.md) 执行真实 TDX 只读请求,保存脱敏字段报告。 4. 对 TDX 字段缺失、协议错误和陈旧数据做 Provider 层降级,不连接生产数据。 5. 暂不新增 Windows 应用、Electron/Tauri、目标推送、补传队列、公网接收 API、RocketMQ 事件或数据库表。 6. 待公网部署需求确定后,另立采集器功能档案,重新评估 Node、Python、Go、Rust 或系统服务方案。 diff --git a/docs/features/FEAT-DS-001-tdx-ingestion-poc/manifest.yaml b/docs/features/FEAT-DS-001-tdx-ingestion-poc/manifest.yaml index 63177c3..0f8afbf 100644 --- a/docs/features/FEAT-DS-001-tdx-ingestion-poc/manifest.yaml +++ b/docs/features/FEAT-DS-001-tdx-ingestion-poc/manifest.yaml @@ -8,5 +8,5 @@ requirements: requirements.md prd: prd.md design: design.md implementation_plan: implementation-plan.md -traceability_note: 当前只完成数据源边界和本地联调规划;Windows 采集器与公网接入延期到公网部署需求确认后单独立项。 +traceability_note: 当前只完成数据源边界和本地联调规划;操作步骤见 ../../deployment/tailscale-tdx-development.md;Windows 采集器与公网接入延期到公网部署需求确认后单独立项。 release: unreleased diff --git a/docs/index.md b/docs/index.md index ac92084..96084e8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,6 +19,7 @@ ## 环境与部署 - [本地开发环境](deployment/local-development.md) +- [Tailscale + SSH 隧道访问 TDX 开发手册](deployment/tailscale-tdx-development.md) - [Ubuntu 源码生产部署(唯一生产方式)](deployment/ubuntu-source-production.md) ## 数据库版本基线