klink
klink 是一个使用 Go 编写的终端 TUI SSH 节点和端口转发管理器。它保存结构化节点配置,
使用系统 OpenSSH 建立连接,并提供本地、远程和动态 SOCKS5 转发。
当前能力
- 节点新增、编辑、复制、删除、搜索和标签
- IPv6 优先,网络不可达时回退 IPv4
- SSH Agent、私钥文件、系统凭据存储中的密码、ProxyJump 和 HostKey 策略
- Host key 指纹扫描、确认后写入或移除统一的 known_hosts
- 可恢复的 tmux SSH 会话与 Tunnel 启动状态自愈
- 本地转发
-L、远程转发-R、动态转发-D - 隧道专用会话
-N、后台 worker、状态恢复和持续自动重连 - ktui 节点幂等同步、klink JSON 和 OpenSSH
ssh_config导入 - 版本化 JSON 导出
- TUI 宽屏双栏和窄屏单栏布局
- Nodes、Tunnels、SFTP、Settings 和 About 使用一致的单宽语义图标,无需 Nerd Font
- 可持久化的主题、SSH、地址优先级和隧道默认设置
- TUI 配置导入、导出、重载和本机 SSH 环境诊断
- SFTP 本地/远程双栏文件浏览、文件与目录递归上传下载
- About 应用信息、Gitea Release 更新检查和应用内更新
环境要求
- PATH 中可用的 OpenSSH
ssh - macOS、Linux 和 Windows:支持前台和后台隧道
保存密码依赖操作系统凭据存储:macOS 使用 Keychain,Windows 使用 Credential Manager,
Linux/BSD 使用 Secret Service(例如 GNOME Keyring 或 KWallet)。klink 不会把密码写入 config.json。
安装
macOS 和 Linux:
curl -fsSL https://gitea.bytevibe.dev/gary/klink/raw/branch/main/install.sh | sh
Windows PowerShell 5.1 或更高版本:
irm https://gitea.bytevibe.dev/gary/klink/raw/branch/main/install.ps1 | iex
安装器会自动识别操作系统和 CPU 架构,从公开的 Gitea Release 下载最新版,并在安装前校验
checksums.txt 中的 SHA256。macOS/Linux 默认安装到可写的 /usr/local/bin,否则使用
~/.local/bin;Windows 默认安装到 %LOCALAPPDATA%\Programs\klink\bin 并加入用户 PATH。
安装指定版本或覆盖安装目录:
curl -fsSL https://gitea.bytevibe.dev/gary/klink/raw/branch/main/install.sh | \
KLINK_VERSION=v0.1.0 KLINK_INSTALL_DIR="$HOME/.local/bin" sh
$env:KLINK_VERSION="v0.1.0"
$env:KLINK_INSTALL_DIR="$HOME\bin"
irm https://gitea.bytevibe.dev/gary/klink/raw/branch/main/install.ps1 | iex
构建
从源码构建需要 Go 1.25 或更高版本。
make build
./bin/klink version
也可以直接运行:
go run ./cmd/klink
快速开始
添加节点:
klink add Tokyo \
--ipv6 2001:db8::10 \
--ipv4 203.0.113.10 \
--user root \
--identity ~/.ssh/id_ed25519 \
--tags production,asia
在 Nodes 页面新增或编辑节点时,Authentication 可以选择 SSH Agent、Key file 或
Password。选择密码后输入的内容会保存到系统凭据存储,表单和配置文件中都不会显示明文;
再次编辑时密码留空会保留现有凭据。命令行可用 --auth agent|key|password 选择认证方式,
密码本身需要在 TUI 节点编辑器中保存。
打开 TUI:
klink
连接或预览实际执行的 OpenSSH 命令:
klink connect Tokyo
klink connect Tokyo --dry-run
klink connect Tokyo --ipv4
klink connect Tokyo --session
TUI 连接默认在系统安装了 tmux 时使用节点专属会话。SSH 中按 Ctrl-b d 可暂时分离并返回
klink,再次选择同一节点会恢复原会话;未安装 tmux、已经位于 tmux 内,或设置
KLINK_NO_SESSION=1 时自动使用普通 SSH 连接。
klink session list
klink session attach Tokyo
klink session kill Tokyo
检查服务器当前提供的 host key 指纹,再接受或移除 known_hosts 记录:
klink host-key inspect Tokyo --ipv6
klink host-key accept Tokyo --ipv6 --algorithm ssh-ed25519
klink host-key remove Tokyo --ipv6
TUI 操作
| 按键 | 操作 |
|---|---|
Tab / Shift+Tab |
切换下一个/上一个主页标签 |
← / → 或 h / l |
在当前页面切换焦点或调整选项 |
↑ / ↓ 或 j / k |
移动选择 |
Enter |
连接当前节点 |
/ |
搜索节点 |
a / e / c / d |
新增、编辑、复制、删除 |
s |
启动或停止当前隧道 |
r |
重启当前隧道 |
Ctrl+S |
保存编辑表单 |
| 空格 | 在设置页和编辑器中调整当前选项 |
Esc |
取消或返回 |
q |
退出 |
支持鼠标单击标签、列表项和 SFTP 面板,使用滚轮移动指针所在的列表。双击节点、隧道、 设置项、SFTP 文件或弹窗列表项会执行对应操作;表单字段和弹窗按钮可以直接点击。
设置 NO_COLOR=1 可以禁用颜色。
About 页面
About 页面展示 klink Logo、版本、构建信息、运行平台、配置路径和项目地址。
使用 ↑/↓ 或 j/k 选择操作,按 Enter 检查更新或安装已经发现的新版本。
更新来自 gitea.bytevibe.dev/gary/klink 的最新 Release;
klink 只会安装与当前系统、架构匹配且通过 checksums.txt SHA256 校验的附件。安装完成后需要重新启动 klink。
Windows 无法覆盖正在运行的可执行文件,因此会先把新版本暂存到当前程序旁边;退出 klink 后,
后台 PowerShell 助手会完成替换,再次启动即使用新版本。若替换失败,错误会写入
klink.exe.update-error.log。
当前仓库尚未发布 Release 时,检查结果会显示“尚未发布”,不会被当作网络故障。
Settings 页面
在 Settings 页面使用 ↑/↓ 或 j/k 选择项目,使用 ←/→、h/l 或空格修改,
操作项目按 Enter 执行。修改会立即保存。
可配置项目:
system、dark、light主题和颜色开关- 新节点默认使用 SSH Agent、HostKey 策略和连接超时
- IPv6 优先或 IPv4 优先的连接顺序
- 新隧道默认模式和自动重连
- 从 ktui 同步节点,或导入 klink JSON 和 OpenSSH
ssh_config - 导出包含全局设置、节点和隧道的完整 JSON 备份
- 从磁盘重新加载当前配置
- 检查本机
ssh路径、版本、SSH_AUTH_SOCK和 Agent 身份状态 - 扫描所选节点的 host key 指纹,展示算法和 SHA256 指纹,并在用户确认后接受或移除记录
默认设置只影响之后新建的节点和隧道,不会静默改写已有项目。
严格校验和 accept-new 都显式使用同一个 known_hosts 文件,默认是 ~/.ssh/known_hosts;
可通过 KLINK_KNOWN_HOSTS 指定其他路径。SSH、SFTP、隧道和 Settings 中的 Host Key 操作
都会使用这一路径。
SFTP 页面
SFTP 页面左侧浏览本地文件,右侧浏览所选节点的远程文件。宽度不足时只显示当前焦点面板,
使用 ←/→ 或 h/l 切换本地和远程面板。
按 n 打开节点选择框,使用 ↑/↓ 或 j/k 选择节点并按 Enter 连接;当前节点名称显示在远程面板标题中。
按 g 可输入路径并跳转当前面板,相对路径以当前目录为起点,本地和远端都支持 ~ 家目录写法。
上传或下载开始后会显示进度、实时速度和已传输大小。使用 ←/→ 或 h/l 选择“取消”或“隐藏”,
按 Enter 执行;Esc 可直接隐藏。隐藏不会中断传输,按 t 打开任务列表后可重新查看排队中、运行中、已完成、失败或已取消的任务。
传输按加入顺序串行执行;任务列表中选择失败或取消的任务后按 r 会使用 klink 管理的 partial 文件断点续传。
| 按键 | 操作 |
|---|---|
↑/↓ 或 j/k |
移动文件选择 |
Tab / Shift+Tab |
切换下一个/上一个主页标签 |
←/→ 或 h/l |
聚焦本地/远程面板 |
Enter |
进入目录;选择文件时上传或下载 |
Backspace / Esc |
返回当前面板的上级目录 |
u |
上传左侧选中的文件或目录 |
d |
下载右侧选中的文件或目录 |
f |
在当前面板新建空文件 |
m |
在当前面板新建目录 |
e |
重命名当前文件或目录 |
x |
确认后递归删除当前文件或目录 |
g |
输入绝对或相对路径并跳转当前面板 |
r |
刷新两侧目录 |
n |
打开包含全部节点的选择框 |
t |
打开 SFTP 传输任务列表 |
任务列表 r |
重试失败或已取消任务并断点续传 |
新建和重命名不会覆盖同名目标,删除目录前必须确认。文件夹会递归传输,目标已存在时必须确认后才会覆盖;文件先写入临时路径,完成后再重命名,
避免中断后留下看似完整的文件。启用断点续传的任务会保留带传输身份后缀的 .klink-part-* 文件;
下载任务同时保存只含传输身份、大小和 SHA256 的 sidecar 元数据。重试时会先校验本地 partial,
再让 SFTP 从远端对应偏移继续读取,不会重新传输已完成的前缀;成功后原子重命名为目标文件并清理元数据。
为避免密码提示破坏全屏界面,SFTP 使用非交互认证:
可以使用 SSH Agent(包括 Bitwarden SSH Agent)、无需交互输入口令的私钥,或节点中已保存的密码。
密码节点没有已保存凭据时,SFTP 会给出错误并要求先编辑节点。符号链接不会被传输。
文件操作完成后仅刷新受影响的面板;刷新中的列表会暂时显示加载状态,另一侧面板仍可继续浏览。
远端目录列表会在当前 klink 进程内按节点、连接地址和路径缓存。再次进入已访问目录或离开后返回
SFTP 页面时会直接使用缓存;远端标题会显示 cached。上传和远端增删改会自动失效相关缓存,
按 r 可忽略缓存并立即从服务器重新同步。缓存不会写入磁盘,退出 klink 后自动清除。
从 Nodes 页面或 klink connect 启动 SSH 时,klink 会在 OpenSSH 接管终端前显示 Logo 和感谢语。
发布与应用内更新
推送 v* tag 会触发 .gitea/workflows/release.yml,使用 GoReleaser 构建 Linux、macOS、Windows
的 amd64/arm64 压缩包以及 checksums.txt。仓库 Actions Secret 中需要配置具有 Release 写权限的 GITEA_TOKEN。
git tag -a v0.1.0 -m "klink v0.1.0"
git push origin v0.1.0
本地构建也可以注入版本信息:
make build VERSION=0.1.0 COMMIT=local BUILD_DATE=2026-07-19
发布前建议执行 make check,并确认 Gitea Actions 中的 Release 工作流成功上传所有平台附件和
checksums.txt。首次发布完成后,上面的安装命令即可直接使用。
需要真实 OpenSSH/SFTP 子系统时,可显式启用集成测试。测试只读取远端当前目录,不会上传或删除文件:
KLINK_SFTP_INTEGRATION=1 \
KLINK_SFTP_HOST=127.0.0.1 \
KLINK_SFTP_USER=test \
KLINK_SFTP_KEY="$HOME/.ssh/id_ed25519" \
KLINK_SFTP_KNOWN_HOSTS="$HOME/.ssh/known_hosts" \
go test ./internal/sftp -run TestOpenSSHSFTPIntegration -v
可选设置 KLINK_SFTP_PORT 指定 SSH 端口。集成测试默认跳过,不依赖外部服务器。
端口转发
隧道专用模式开启自动重连后,会在网络故障或服务器重启后持续尝试恢复,退避时间从 1 秒 逐步增加并封顶为 32 秒;手动停止会立即取消等待。认证失败、Host Key 失败等不可恢复错误 仍会直接进入失败状态,避免无意义地重复认证。
本地数据库转发:
klink tunnel add database \
--node Tokyo \
--type local \
--bind 127.0.0.1:5432 \
--target db.internal:5432 \
--reconnect
远程转发:
klink tunnel add webhook \
--node Tokyo \
--type remote \
--bind 127.0.0.1:8080 \
--target localhost:3000
动态 SOCKS5 代理:
klink tunnel add socks-dev \
--node Tokyo \
--type dynamic \
--bind 127.0.0.1:1080
管理运行状态:
klink tunnel list
klink tunnel start database --dry-run
klink tunnel start database --background
klink tunnel stop database
klink tunnel restart database
一个配置可以包含多条转发规则:
klink tunnel forward add database \
--type local \
--bind 127.0.0.1:6379 \
--target redis.internal:6379
klink tunnel forward remove database 2
本地和动态转发默认绑定 127.0.0.1。绑定 0.0.0.0、:: 或其他非回环地址时,
启动命令会拒绝继续;确认风险后显式传入 --allow-public。远程公开监听还取决于 SSH
服务器的 GatewayPorts 配置。
后台隧道和 TUI SFTP 依赖非交互式认证,可以使用 SSH Agent、无需手工输入口令的私钥,
或节点中已保存到系统凭据存储的密码。运行日志和 PID 状态保存在配置目录的 runtime/ 子目录中,
权限为当前用户私有。Windows 后台 worker 使用脱离控制台的进程、命名停止事件和 Job Object;
关闭 klink 不会中断 Tunnel,停止时会优雅取消 SSH,强制终止也会清理整个 SSH 子进程树。
导入和导出
从 ktui 同步
在 TUI 的 Settings 页面选择 Sync from ktui 并按 Enter,或者直接运行:
klink sync ktui
klink 会执行:
ktui export json
然后根据 ktui UUID 同步节点名称、IPv4、IPv6、区域、分组和标签。已有节点会保留 klink 中的 SSH 用户、认证方式、密码凭据关联、密钥、端口、Host Key 策略、ProxyJump、连接记录和隧道引用; 只对首次出现的新节点应用当前默认 SSH 设置。重复执行同步不会创建副本。
如果旧版本导入的节点没有稳定 UUID,klink 只会在带有 ktui- ID 或 Imported from ktui
标记的节点中按名称或已有 IP 迁移匹配,不会覆盖同名的手工节点。ktui 中已经消失的节点不会
被自动删除,避免连带删除本地隧道或遗留凭据,需要时可在 Nodes 页面手工确认后删除。
也可以先保存 ktui 导出文件,再通过 Import configuration 或命令行同步:
ktui export json -o ktui-nodes.json
klink import ktui-nodes.json
首次同步后在 Nodes 页面选择新节点并按 e 填写 SSH User,再选择 Agent、密钥或密码认证。
保存的密码只进入系统凭据存储,不会出现在 klink JSON、导出文件或进程参数中。
同步 ktui JSON 或导入 klink JSON:
klink import nodes.json
导入 OpenSSH 配置:
klink import ~/.ssh/config --format ssh-config
只有具体的 Host 别名会被转换为节点。Host *、通配规则和 Match 块不会展开成节点;
导入结果会逐项报告跳过内容和名称/ID 冲突。
导出包含全局设置、节点和隧道的版本化 JSON:
klink export klink-backup.json
klink export -
导出只包含节点的认证方式和私钥路径,不包含系统凭据存储中的密码。将备份导入另一台设备后, 密码节点需要重新输入并保存密码。
配置与安全
查看配置路径:
klink config path
可以用全局参数或环境变量指定其他配置:
klink --config ./demo.json list
KLINK_CONFIG=./demo.json klink list
- 配置文件以
0600权限原子写入 - 密码和私钥内容不会写入配置;只保存私钥路径
- 默认使用严格 HostKey 校验
accept-new允许首次写入主机密钥insecure会禁用 HostKey 校验,仅应在明确理解风险时使用- OpenSSH 参数通过结构化参数数组执行,不经过 shell 插值
如果发行流程同时提供与附件同名的 .sig Ed25519 签名文件,可设置
KLINK_UPDATE_PUBLIC_KEY(Base64 或十六进制公钥)让应用内更新额外校验签名;未配置公钥时保持
现有的 HTTPS + SHA256 校验流程。
许可证
klink 使用 MIT License。