gary db6d64e9c9
CI / test (push) Successful in 1m7s
CI / cross-build (amd64, darwin) (push) Successful in 38s
CI / cross-build (amd64, linux) (push) Successful in 33s
CI / cross-build (amd64, windows) (push) Successful in 38s
CI / cross-build (arm64, darwin) (push) Successful in 39s
CI / cross-build (arm64, linux) (push) Successful in 39s
CI / cross-build (arm64, windows) (push) Successful in 38s
perf: optimize SFTP sessions and configuration imports
2026-09-13 18:19:56 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00
2026-07-19 22:27:20 +08:00

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。

S
Description
klink 是一个使用 Go 编写的终端 TUI SSH 节点和端口转发管理器
Readme MIT
375 KiB
0 Stars 1 Watchers 0 Forks
v0.1.0
Latest
2026-07-19 22:28:27 +08:00
Languages
Go 97.9%
PowerShell 1.2%
Shell 0.8%