命令行远程协助工具:通过中转服务器(或 LAN 内直连 / NAT 穿透 P2P)建立安全隧道。既支持传统 SSH 远程协助,也支持让本地 Claude Code 通过 MCP 工具通道直接调试远端机器。
- 两种协助通道:经典 SSH 隧道;Claude Code MCP 工具通道(12 个远程工具,含文件上传/下载)。
- 三种连接方式:公网 relay 中转;LAN 内
--standalone进程内 relay 直连;NAT 穿透 P2P 直连(STUN 打洞,失败自动回落中转)。 - 分层加密:relay 链路 TLS;MCP 工具通道额外以协助码派生密钥做 XChaCha20-Poly1305 AEAD —— 即使 relay 被攻破,也看不见、无法伪造工具内容。
- 护栏:exec 命令黑/白名单;可选
--root把文件工具限制在某子树内(防手滑,非安全边界 —— exec 不受其约束)。 - relay 加固:连接数限流(全局 + 每 IP)、读/写超时、单消息大小上限,抵御资源耗尽型 DoS / slowloris。
脚本会从 GitHub 最新正式 Release 下载当前系统与架构对应的客户端,并安装为
~/.local/bin/remote(Windows 的 Git Bash / MSYS2 / Cygwin 中为 remote.exe):
curl -fsSL https://raw.githubusercontent.com/kegechen/remote-assist-tool/master/install.sh | sh也可以使用 wget,或通过 REMOTE_INSTALL_DIR 指定安装目录:
wget -qO- https://raw.githubusercontent.com/kegechen/remote-assist-tool/master/install.sh | sh
REMOTE_INSTALL_DIR=/usr/local/bin sh install.sh支持 Linux、macOS 和 Windows(Git Bash / MSYS2 / Cygwin)的 amd64、arm64 架构;
Linux/macOS 下载后会自动添加可执行权限;Windows 中 curl / wget 下载失败时会自动回退到
系统 PowerShell。
安装前脚本会拉取同一个 Release 的 SHA256SUMS 核对下载到的二进制,对不上就中止,不会留下
任何文件。校验拿不到清单时同样中止 —— 需要绕开时显式设 REMOTE_INSTALL_SKIP_CHECKSUM=1。
手工下载的话,可以自己核对:
curl -fLO https://github.com/kegechen/remote-assist-tool/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing # macOS: shasum -a 256 -c SHA256SUMS --ignore-missing需要说明的是,SHA256SUMS 和二进制来自同一个 Release、走同一条 HTTPS,所以它挡的是"下到的
东西不完整/被中途换掉",而不是"Release 本身被换掉" —— 后者要靠签名,本项目暂未提供。
用仓库自带脚本,产物输出到 bin/(Windows 为 .exe):
# Windows
build.bat
# Linux / macOS
./build.sh
# 在 Windows 上交叉编译 Linux 产物
build-linux.bat产物都带平台后缀(<组件>-<os>-<arch>),一眼看得出这个二进制给谁跑,也不会跟 PATH 里
别的东西撞名:
| 产物 | 说明 |
|---|---|
bin/remote-assist-cli-windows-amd64.exe |
客户端,share / help 两种角色,也是 MCP 入口 |
bin/remote-assist-webui-windows-amd64.exe |
浏览器控制台(会去同目录/bin/ 找上面那个 cli) |
bin/remote-assist-relay-windows-amd64.exe |
中转服务器 |
bin/remote-assist-{cli,relay}-linux-{amd64,arm64} |
build-linux.bat 交叉编译产出 |
Windows 产物内嵌产品信息(右键属性可见产品名/描述/版本),由 goversioninfo 按
git describe 生成。该工具已用 tools.go 钉进 go.mod:go mod download 一次之后
离线也能构建,不必每次联网。
提示:纯编译检查用
go build ./...(不产出文件);要产物务必-o bin/或用上面的脚本,别让可执行文件散落到仓库根。
Web UI 连接后会比较 help 与 share 的版本;确认 share 较旧时,顶部显示升级提示。选择与 远端系统和架构匹配的 CLI 二进制后,后端按“先建后断”完成交接:
- 经 old 通道探测 PID、原可执行文件路径、系统与架构;上传前检查候选文件的 ELF/PE
machine,确认 Linux/Windows 与 amd64/arm64 均匹配后才分块上传,再在远端执行
--version验证。 - 复用 old 的 share 参数,以隔离
HOME(独立 ClientID)和固定--code-file启动 new。 升级默认实例时,隔离HOME不改变其单实例锁:old 持锁期间 new 排队等待接管,因此 升级交接过程中再次启动默认 share 仍会直接报错。 - 仍经 old 通道读取 new code,主动连接 new 并核对版本。
- Linux 在 new 验证成功后原子替换原文件,再按 PID 终止 old。Windows 先把运行中的 old 改成备份名、让候选文件占回原路径,再启动 new;new 验证成功后按 PID 终止 old 并删除 备份,切换失败则经 old 通道恢复原文件。
切换前任一步失败都不会终止 old;连接 new 失败会尝试自动回连 old。当前仅支持使用外部
relay 的 Linux/Windows amd64/arm64 share,--standalone / --no-auth 会被拒绝。
如果配置了 --allow-exec,升级所需的 sh/powershell.exe、mkdir、chmod、kill 及候选二进制也必须
获准执行。原路径替换后,已有 systemd/开机启动配置无需改文件名;当前临时接管进程继续
使用隔离 ClientID,下一次由原路径正常启动时恢复标准 HOME/ClientID。
被协助端(分享本机 SSH):
remote share --server relay.example.com:8443程序显示协助码,例如:
协助码已生成: ABCD-EFGHIJ
有效期至: 2026-02-28 18:30:00
等待协助端连接...
同一用户下默认只允许一个 share。需要额外分享不同 SSH 服务或不同工具策略时,显式创建 独立实例:
remote share --ssh 127.0.0.1:22 --server relay.example.com:8443
remote share --new-instance --ssh 127.0.0.1:2222 --server relay.example.com:8443默认实例重复启动会直接报错,不会断开已运行的实例。每次使用 --new-instance 都会创建
独立协助码;在协助码有效期内,该进程网络断线重连时保持原码,但进程退出后再次启动会
生成新码。连接外部 relay 时 share 只建立出站连接,无需为每个实例分配本地监听端口;
--ssh 端口只是其代理的本地 SSH 服务。standalone 模式下每个实例内嵌一个 relay,因此
还必须分别设置不同的 --standalone-listen 端口。
协助端(用协助码连接,默认走 MCP 模式;要传统 SSH 隧道加 --legacy-ssh):
remote help --server relay.example.com:8443 --code ABCD-EFGHIJ --legacy-ssh
# 然后在另一个终端:
ssh -p 2222 user@127.0.0.1
--insecure默认 true:内置/standalone relay 使用自签证书,开箱即用。对接装有受信 CA 证书的 relay 时,请显式传--insecure=false启用证书校验。跳过校验不等于没有身份认证:首次连上某个 relay 地址时会把它的证书指纹记到
~/.remote_assist_known_hosts(TOFU,同 SSH 的 known_hosts),之后指纹变了就拒连。relay 确实换过证书时加--trust-new-cert重新信任,或删掉文件里对应的那一行。连localhost/127.0.0.1不做钉扎(回环没有中间人可防,且本机上多个 relay 会共用同一个地址键)。
被协助端进程内启动一个自签 TLS relay 并监听 LAN,help 端直接连这台机器,全程不依赖任何外部服务器:
remote share --standalone --standalone-listen :8443控制台会打印 help 端连接命令(自动探测 LAN IP):
================ standalone (LAN) mode ================
Relay (TLS, self-signed) listening at: 192.168.1.23:8443 (LAN reachable)
Help side connects exactly like a normal relay (no --plain needed):
remote help --server 192.168.1.23:8443 --code <code> --p2p disabled
=======================================================
standalone 自签证书只覆盖
localhost,LAN 场景请保持默认--insecure=true(勿用--insecure=false,会因证书 SAN 不含 LAN IP 而失败)。该证书存放在
~/.remote_assist_standalone_certs/,跨次启动复用(临近过期才重新生成),这样 help 端的指纹钉扎才能稳定命中。删掉这个目录会换新证书,届时老的 help 端需要--trust-new-cert。
让本地 Claude Code 直接调试远端机器,无需在远端开 openssh-server。
首次接入可直接把 MCP_SETUP.md 交给 Claude Code 或 Codex,自动完成
remote 下载与 remote-debug MCP 配置。
远端启动 share(带沙箱):
remote share --server relay.example.com:8443本地配置 Claude Code(项目根 .mcp.json 或 ~/.claude/mcp.json):
注意 不带 --code —— 这是 bootstrap 模式,MCP server 启动时还不知道协助码。
每次调试会话:
- 远端跑
remote share,拿到协助码ABCD-EFGHIJ; - 在 Claude Code 里直接说:“协助码 ABCD-EFGHIJ,连上去”;
- Claude 调用
remote-debug:connect("ABCD-EFGHIJ")完成握手;若是 standalone/LAN,可加地址:connect("ABCD-EFGHIJ", server="192.168.1.23:8443"); - 之后所有调用直接走真实工具,无需重启 Claude。
旧用法(写死协助码)仍支持:在 args 里加 "--code", "ABCD-EFGHIJ" 跳过 bootstrap。
若
connect直接报Transport closed,且没有返回session_id/peer_host,请求通常 尚未到达remoteCLI。不要据此判断协助码失效或 relay 故障;先重启受影响的 Claude Code / Codex 进程,再用同一码重试。旧 stdio 句柄一旦被宿主取消,反复调用connect无法恢复。详细证据与排查步骤见MCP_SETUP.md和remote-debugMCP 接入参考。
┌──────────────────────────────────────────┐
│ 公网 Relay(TLS)/ standalone 进程内 │
│ 仅转发;工具通道内容对 relay 不可见 │
└───────────────┬──────────────┬────────────┘
│ │
┌───────────────┘ └───────────────┐
│ (NAT 穿透成功则 P2P 直连,跳过 relay) │
┌──────────▼──────────┐ ┌────────────▼─────────┐
│ 被协助端 (Share) │ ◀── 工具通道 AEAD ──▶ │ 协助端 (Help) │
│ remote share │ / SSH 隧道 │ remote help │
└──────────┬──────────┘ └────────────┬─────────┘
│ │
┌──────────▼──────────┐ ┌────────────▼─────────┐
│ 沙箱内文件/exec │ │ 本地 SSH :2222 / │
│ 或本地 SSH :22 │ │ Claude Code MCP │
└─────────────────────┘ └──────────────────────┘
| 选项 | 默认值 | 说明 |
|---|---|---|
--listen |
:8443 |
监听地址 |
--cert / --key |
- | TLS 证书 / 私钥文件 |
--ttl |
30m |
协助码有效期 |
--length |
10 |
协助码长度 |
--audit |
audit.log |
审计日志文件 |
--stun |
空 | STUN/UDP relay 监听地址;例如 :3478,空则禁用 |
--trust-source-ip |
true |
Relay 是否能从 TCP 连接看到真实来源 IP;SNAT 后端设为 false |
--limits-file |
$REMOTE_RELAY_LIMITS_FILE |
JSON 限流配置文件;未设置则使用安全默认值 |
--print-default-limits |
false |
输出完整默认限流 JSON 后退出 |
--no-auth |
false |
固定码无鉴权模式,仅限完全可信私网 |
--plain |
false |
非 TLS 模式(仅开发测试) |
--gen-certs |
false |
生成自签证书后退出 |
--certs-dir |
./certs |
证书目录(未指定 cert/key 时自动在此生成自签证书) |
--version |
false |
显示版本 |
Relay 的来源 IP 判断、完整限流参数、默认值依据、公共 STUN 行为和部署监控方法见 Relay 来源 IP、限流与监控指南。
Windows 下直接双击无参数的 relay 会打开服务管理菜单。也可以使用非交互命令安装和管理原生 Windows 服务:
remote-assist-relay-windows-amd64.exe service install
remote-assist-relay-windows-amd64.exe service start
remote-assist-relay-windows-amd64.exe service status
remote-assist-relay-windows-amd64.exe service stop
remote-assist-relay-windows-amd64.exe service uninstall服务程序安装到 C:\Program Files\RemoteAssistRelay,配置、证书和审计文件位于 C:\ProgramData\RemoteAssistRelay,运行日志写入 Windows Application Event Log。服务模式、配置格式、权限和卸载行为见 Windows Relay 服务部署。原有前台参数保持兼容;显式使用 run 可避免与服务管理命令混淆:
remote-assist-relay-windows-amd64.exe run --listen :8443 --ttl 1h| 选项 | 默认值 | 说明 |
|---|---|---|
--server |
localhost:8443 |
中转服务器地址(也可用环境变量 REMOTE_RELAY_SERVER 覆盖) |
--insecure |
true |
跳过 TLS 校验(自签 relay 用;对接受信 CA relay 改 false) |
--ca |
- | CA 证书文件 |
--trust-new-cert |
false |
接受与首次连接时不一致的 relay 证书指纹并重新记录(relay 确实换了证书时用) |
--ssh |
127.0.0.1:22 |
本地 SSH 地址(SSH 隧道模式) |
--new-instance |
false |
额外启动独立 share;生成新协助码且不影响默认实例 |
--p2p |
auto |
P2P 模式:disabled / auto / required |
--stun |
- | STUN 服务地址(默认同 relay 的 :3478) |
--bind-ip |
- | 指定 UDP 绑定 IP(绕过 TUN 代理自动探测) |
--standalone |
false |
进程内启动 relay 并监听 --standalone-listen,LAN 直连场景 |
--standalone-listen |
:8443 |
standalone relay 监听地址 |
--code-file |
- | 注册后把协助码+有效期以 JSON 原子写到该文件(供宿主程序读取) |
--root |
- | 可选:把文件工具限制在该子树(未设 = 不限制)。防手滑,非安全边界 |
--allow-exec |
- | exec 命令白名单(逗号分隔,空=仅受黑名单约束) |
--deny-exec |
rm,shutdown,reboot,mkfs,dd |
exec 命令黑名单 |
--elevate |
false |
Windows:启动时经 UAC 请求管理员权限 |
--unsafe-exec |
false |
危险:关闭 exec 黑/白名单,任意命令可跑(启动有 5 秒红色确认倒计时)。不影响 --root |
--plain |
false |
非 TLS(仅开发) |
| 选项 | 默认值 | 说明 |
|---|---|---|
--server |
localhost:8443 |
中转服务器地址(可用 REMOTE_RELAY_SERVER 覆盖) |
--code |
- | 协助码(SSH/直连模式必填;MCP bootstrap 模式留空,由 connect 工具提供) |
--insecure |
true |
跳过 TLS 校验(同 share) |
--ca |
- | CA 证书文件 |
--trust-new-cert |
false |
同 share |
--listen |
127.0.0.1:2222 |
本地监听地址(SSH 隧道模式) |
--p2p |
auto |
P2P 模式:disabled / auto / required |
--stun |
- | STUN 服务地址 |
--bind-ip |
- | 指定 UDP 绑定 IP |
--mcp-stdio |
false |
作为 MCP stdio server 运行(供 Claude Code) |
--legacy-ssh |
false |
强制传统 SSH 隧道模式(不加 --mcp-stdio 时即此模式) |
--plain |
false |
非 TLS(仅开发) |
| 工具 | 说明 |
|---|---|
connect |
用协助码与远端配对,必须先调用;可选 server= 覆盖 relay 地址(用于 standalone/LAN) |
exec |
远端按 argv 运行命令(不过 shell) |
read_file / write_file |
读 / 写远端文件(设了 --root 则限于该子树;单次最多 1 MiB) |
list_dir / stat / glob / grep |
远端文件系统探索 |
process_list |
列远端进程 |
tail_log |
读远端日志末尾 N 行 |
upload_file |
把本地文件分块(512 KiB)推送到远端 —— DLL/EXE/zip 等二进制 |
download_file |
把远端文件分块拉到本地 —— crash dump / 日志归档等 |
upload_file / download_file 为 host 端复合工具,内部循环调用 write_file / read_file,share 端零改动。
- relay 链路 TLS(自签或受信 CA);
--insecure控制是否校验。跳过校验时退化为 TOFU 指纹钉扎(~/.remote_assist_known_hosts),把中间人窗口从「永远」压到「仅首次连接」;回环地址不钉扎。 - MCP 工具通道以协助码派生 session key(HKDF-SHA256)做 XChaCha20-Poly1305 AEAD:relay 仅转发密文,看不见也无法伪造工具内容。
- 工具通道协议 v2 在 AEAD 之上补了三件事(与 v1 不兼容,见下):
- AAD 绑定明文字段:
tool/id/deadline_ms、响应的ok/error_code/error_msg、流帧的seq/stream都是外层明文。它们进 AAD 之后,把一条捕获的密文改挂到别的工具(比如把read_file的参数挂到write_file,让远端把文件截断成 0 字节)、改 ID、改超时、把成功翻成失败、把流帧重排或跨流投递,全部会解密失败。 - 每条响应都要加封(包括结果为空的错误响应),接收侧先验真再看
ok。否则中间人只要把一次成功的read_file的result清空,调用方就会拿到「空结果 + 成功」—— AI 会据此得出「这个文件是空的」,而它没有任何别的办法察觉。 - 握手后 args 必须是密文:包括「没有参数」的调用,host 也封一个
{}。此前的判据是「有 args 才解密」,等于留了后门 —— 发一条不带 args 的tool_req{tool:"process_list"}就能绕过全部解密直接触发远端执行。现在没有合法密文一律在 Dispatch 之前拒掉。 - 抗重放:nonce 由发送方给,AAD 挡得住改字段却挡不住原样重放。接收侧按调用 ID 做 1024 位滑动窗口去重(语义同 IPsec),重放返回
replayed。窗口每把 key 一份,重新握手时重置,P2P 热升级(不换 key)时保留。
- AAD 绑定明文字段:
- P2P 打洞包带协助码派生的 HMAC,并绑定发送方身份:只知道 sessionID(打洞时会主动喷洒到对端公网 IP 的一批端口上,本就不是秘密)伪造不出打洞包,也无法把自己冒充成对端。
- 兼容性:默认不与旧版(0.0.x)互通,需要时用
--min-proto=1显式放宽。- 工具通道版本号在 ToolHello/ToolHelloAck 里协商:双方各自通告支持的版本集,取交集里最高的一个。
0.0.1~0.0.9是 v1,1.0.0起是 v2。 - 默认拒绝降级。允许自动降级的话,不可信的 relay 只要从 Hello 里删掉
versions字段,就能把两个 v2 端悄悄打回 v1,白拿一条没有 AAD、没有抗重放的通道,而且事后无从察觉。所以放宽必须是用户的显式决定。 - 遇到旧版时握手会失败,并给出可操作的提示(而不是一句
unsupported tool protocol version)。参数永远加在新版本那一端 —— 旧版根本没有这个旗标:- 新版 help 连旧版 share → 在 help 端加
--min-proto=1; - 旧版 help 连新版 share → 在 share 端加
--min-proto=1(提示会同时打在 share 本机和旧 help 的终端上)。
- 新版 help 连旧版 share → 在 help 端加
- 放宽只是降低下限,不是强制降级:两端都支持 v2 时仍然谈成 v2。真的降到 v1 时两端都会打印醒目告警,因为那意味着 AAD 绑定、强制密文参数、抗重放三项一起关掉了。
- 与 0.0.x 互通时没有 P2P 直连,全程走中转:协商到 v1 后新端不再发任何打洞包、也不会把流量切到隧道。原因是打洞认证只能单向生效——我们会拒绝旧版不带 MAC 的包,但旧版只比对
session_id、压根不认识mac字段,会照单全收我们的包并单方面认定 P2P 已通,然后把流量送进一条我们这边根本没建起来的隧道。不发包是唯一能让两端状态保持一致的做法。- 需要说明的是:share 侧的地址通告可能在工具握手之前就发出去了(
advertiseAddr在mgr.Start()内部,而握手要等SessionReady之后才到),所以旧对端仍可能自行打洞、空等到它自己超时。这部分浪费在对端、我们改不动它的代码;要彻底免掉就得推迟 P2P 启动,但握手到达前分不清这是工具会话还是 SSH 会话,推迟会让 SSH 的 P2P 一起失效。不会因此出现黑洞:新端始终不回包、也不切隧道。 --p2p=required下两端都立刻报错说明原因(而不是干等打洞超时)。share 侧在握手阶段就回一条带理由的拒绝——"对端太旧"也是一种 P2P 失败,而用户已明确表示不接受中转,这个会话从一开始就不成立;先 Accept 再掐断的话,对端只看得到"握手成功 → tunnel_lost → 重连"的无理由循环。0.0.x 会把拒绝理由原样打印出来。
- 需要说明的是:share 侧的地址通告可能在工具握手之前就发出去了(
- 即便开了
--min-proto=1,两个都支持 v2 的新端之间仍不会被降级:应答方的versions是它"我支持什么"的证词,若双方都能用更高版本却谈成了低版本,说明提议在途中被改过,发起方据此拒绝握手。真正的 0.0.x 不发这个字段,不受影响。 - 打洞校验本身不随
--min-proto=1放开 —— 认证要是能被"自称是旧版"绕过,它就等于不存在。兼容模式下是功能降级,认证不降级。
- 工具通道版本号在 ToolHello/ToolHelloAck 里协商:双方各自通告支持的版本集,取交集里最高的一个。
- 协助码:安全随机生成(54 字符集 × 10 位,去除易混淆字符),默认 30 分钟过期。
- 信任边界是协助码:share 由本机用户主动发起,码交给谁,就等于把这台机器交给谁。
--root/ exec 名单是防手滑的护栏,不是对抗恶意方的边界 —— exec 可跑任意程序,一句sh -c 'cp /etc/passwd <root>/'即可绕过--root。需要真隔离请在进程外面套(容器 / 专用低权限账号)。 - relay 服务端加固:全局 + 每 IP 连接数上限、读/写超时、单消息大小上限。
- 完整审计日志。
| 特性 | 本工具 | frp | ZeroTier | ngrok |
|---|---|---|---|---|
| 核心功能 | SSH/MCP 远程协助 | 反向代理 | 虚拟局域网 | 内网穿透 |
| 使用场景 | 临时协助 / 远程调试 | 长期服务暴露 | 组建虚拟网络 | 临时公网访问 |
| 配置复杂度 | 极低(一个协助码) | 中等 | 中等 | 低 |
| 自建服务 | ✅ 支持 | ✅ 支持 | ❌(有自托管版) | ❌ 依赖官方 |
| 连接方式 | Relay / P2P / LAN 直连 | 仅 Relay | P2P 优先 | 仅 Relay |
| 单次使用 | ✅ 专为临时设计 | ❌ 偏长期 | ❌ 偏长期 | ✅ 临时 |
| AI 集成 | ✅ Claude Code MCP | ❌ | ❌ | ❌ |
- 极简 ——
share生成码,help/Claude 用码连接,两步搞定。 - 协助码过期 —— 默认 30 分钟自动失效。
- 三种连接 —— 公网中转、LAN 直连、P2P 直连按场景自动选择。
- 完全自托管 —— 数据自己掌控。
- AI 原生 —— 直接挂到 Claude Code 当远程调试 MCP。
{ "mcpServers": { "remote-debug": { "command": "remote", "args": ["help", "--server", "relay.example.com:8443", "--mcp-stdio"] } } }