345 lines
12 KiB
Markdown
345 lines
12 KiB
Markdown
# klink
|
||
|
||
`klink` 是一个使用 Go 编写的终端 TUI SSH 节点和端口转发管理器。它保存结构化节点配置,
|
||
使用系统 OpenSSH 建立连接,并提供本地、远程和动态 SOCKS5 转发。
|
||
|
||
|
||
## 当前能力
|
||
|
||
- 节点新增、编辑、复制、删除、搜索和标签
|
||
- IPv6 优先,网络不可达时回退 IPv4
|
||
- SSH Agent、私钥文件、系统凭据存储中的密码、ProxyJump 和 HostKey 策略
|
||
- 本地转发 `-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:
|
||
|
||
```sh
|
||
curl -fsSL https://gitea.bytevibe.dev/gary/klink/raw/branch/main/install.sh | sh
|
||
```
|
||
|
||
Windows PowerShell 5.1 或更高版本:
|
||
|
||
```powershell
|
||
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`。
|
||
|
||
安装指定版本或覆盖安装目录:
|
||
|
||
```sh
|
||
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
|
||
```
|
||
|
||
```powershell
|
||
$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 或更高版本。
|
||
|
||
```sh
|
||
make build
|
||
./bin/klink version
|
||
```
|
||
|
||
也可以直接运行:
|
||
|
||
```sh
|
||
go run ./cmd/klink
|
||
```
|
||
|
||
## 快速开始
|
||
|
||
添加节点:
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
klink
|
||
```
|
||
|
||
连接或预览实际执行的 OpenSSH 命令:
|
||
|
||
```sh
|
||
klink connect Tokyo
|
||
klink connect Tokyo --dry-run
|
||
klink connect Tokyo --ipv4
|
||
```
|
||
|
||
## TUI 操作
|
||
|
||
| 按键 | 操作 |
|
||
| --- | --- |
|
||
| `Tab` / `Shift+Tab` | 切换下一个/上一个主页标签 |
|
||
| `←` / `→` 或 `h` / `l` | 在当前页面切换焦点或调整选项 |
|
||
| `↑` / `↓` 或 `j` / `k` | 移动选择 |
|
||
| `Enter` | 连接当前节点 |
|
||
| `/` | 搜索节点 |
|
||
| `a` / `e` / `c` / `d` | 新增、编辑、复制、删除 |
|
||
| `s` | 启动或停止当前隧道 |
|
||
| `r` | 重启当前隧道 |
|
||
| `Ctrl+S` | 保存编辑表单 |
|
||
| 空格 | 在设置页和编辑器中调整当前选项 |
|
||
| `Esc` | 取消或返回 |
|
||
| `q` | 退出 |
|
||
|
||
设置 `NO_COLOR=1` 可以禁用颜色。
|
||
|
||
### About 页面
|
||
|
||
About 页面展示 klink Logo、版本、构建信息、运行平台、配置路径和项目地址。
|
||
使用 `↑/↓` 或 `j/k` 选择操作,按 `Enter` 检查更新或安装已经发现的新版本。
|
||
更新来自 [gitea.bytevibe.dev/gary/klink](https://gitea.bytevibe.dev/gary/klink) 的最新 Release;
|
||
klink 只会安装与当前系统、架构匹配且通过 `checksums.txt` SHA256 校验的附件。安装完成后需要重新启动 klink。
|
||
|
||
当前仓库尚未发布 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 身份状态
|
||
|
||
默认设置只影响之后新建的节点和隧道,不会静默改写已有项目。
|
||
|
||
### SFTP 页面
|
||
|
||
SFTP 页面左侧浏览本地文件,右侧浏览所选节点的远程文件。宽度不足时只显示当前焦点面板,
|
||
使用 `←/→` 或 `h/l` 切换本地和远程面板。
|
||
按 `n` 打开节点选择框,使用 `↑/↓` 或 `j/k` 选择节点并按 `Enter` 连接;当前节点名称显示在远程面板标题中。
|
||
按 `g` 可输入路径并跳转当前面板,相对路径以当前目录为起点,本地和远端都支持 `~` 家目录写法。
|
||
上传或下载开始后会显示进度、实时速度和已传输大小。使用 `←/→` 或 `h/l` 选择“取消”或“隐藏”,
|
||
按 `Enter` 执行;`Esc` 可直接隐藏。隐藏不会中断传输,按 `t` 打开任务列表后可重新查看运行中、已完成、失败或已取消的任务。
|
||
|
||
| 按键 | 操作 |
|
||
| --- | --- |
|
||
| `↑/↓` 或 `j/k` | 移动文件选择 |
|
||
| `Tab` / `Shift+Tab` | 切换下一个/上一个主页标签 |
|
||
| `←/→` 或 `h/l` | 聚焦本地/远程面板 |
|
||
| `Enter` | 进入目录;选择文件时上传或下载 |
|
||
| `Backspace` / `Esc` | 返回当前面板的上级目录 |
|
||
| `u` | 上传左侧选中的文件或目录 |
|
||
| `d` | 下载右侧选中的文件或目录 |
|
||
| `f` | 在当前面板新建空文件 |
|
||
| `m` | 在当前面板新建目录 |
|
||
| `e` | 重命名当前文件或目录 |
|
||
| `x` | 确认后递归删除当前文件或目录 |
|
||
| `g` | 输入绝对或相对路径并跳转当前面板 |
|
||
| `r` | 刷新两侧目录 |
|
||
| `n` | 打开包含全部节点的选择框 |
|
||
| `t` | 打开 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`。
|
||
|
||
```sh
|
||
git tag -a v0.1.0 -m "klink v0.1.0"
|
||
git push origin v0.1.0
|
||
```
|
||
|
||
本地构建也可以注入版本信息:
|
||
|
||
```sh
|
||
make build VERSION=0.1.0 COMMIT=local BUILD_DATE=2026-07-19
|
||
```
|
||
|
||
发布前建议执行 `make check`,并确认 Gitea Actions 中的 Release 工作流成功上传所有平台附件和
|
||
`checksums.txt`。首次发布完成后,上面的安装命令即可直接使用。
|
||
|
||
## 端口转发
|
||
|
||
本地数据库转发:
|
||
|
||
```sh
|
||
klink tunnel add database \
|
||
--node Tokyo \
|
||
--type local \
|
||
--bind 127.0.0.1:5432 \
|
||
--target db.internal:5432 \
|
||
--reconnect
|
||
```
|
||
|
||
远程转发:
|
||
|
||
```sh
|
||
klink tunnel add webhook \
|
||
--node Tokyo \
|
||
--type remote \
|
||
--bind 127.0.0.1:8080 \
|
||
--target localhost:3000
|
||
```
|
||
|
||
动态 SOCKS5 代理:
|
||
|
||
```sh
|
||
klink tunnel add socks-dev \
|
||
--node Tokyo \
|
||
--type dynamic \
|
||
--bind 127.0.0.1:1080
|
||
```
|
||
|
||
管理运行状态:
|
||
|
||
```sh
|
||
klink tunnel list
|
||
klink tunnel start database --dry-run
|
||
klink tunnel start database --background
|
||
klink tunnel stop database
|
||
klink tunnel restart database
|
||
```
|
||
|
||
一个配置可以包含多条转发规则:
|
||
|
||
```sh
|
||
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/` 子目录中,
|
||
权限为当前用户私有。
|
||
|
||
## 导入和导出
|
||
|
||
### 从 ktui 导入
|
||
|
||
在 TUI 的 Settings 页面选择 `Import from ktui` 并按 `Enter`。klink 会执行:
|
||
|
||
```sh
|
||
ktui export json
|
||
```
|
||
|
||
然后导入节点名称、UUID、IPv4、IPv6、区域、分组和标签。也可以先保存 ktui 导出文件,
|
||
再通过 `Import configuration` 或命令行导入:
|
||
|
||
```sh
|
||
ktui export json -o ktui-nodes.json
|
||
klink import ktui-nodes.json
|
||
```
|
||
|
||
导入后在 Nodes 页面选择节点并按 `e` 填写 SSH `User`,再选择 Agent、密钥或密码认证。
|
||
保存的密码只进入系统凭据存储,不会出现在 klink JSON、导出文件或进程参数中。
|
||
|
||
导入 ktui/klink JSON:
|
||
|
||
```sh
|
||
klink import nodes.json
|
||
```
|
||
|
||
导入 OpenSSH 配置:
|
||
|
||
```sh
|
||
klink import ~/.ssh/config --format ssh-config
|
||
```
|
||
|
||
只有具体的 `Host` 别名会被转换为节点。`Host *`、通配规则和 Match 块不会展开成节点;
|
||
导入结果会逐项报告跳过内容和名称/ID 冲突。
|
||
|
||
导出包含全局设置、节点和隧道的版本化 JSON:
|
||
|
||
```sh
|
||
klink export klink-backup.json
|
||
klink export -
|
||
```
|
||
|
||
导出只包含节点的认证方式和私钥路径,不包含系统凭据存储中的密码。将备份导入另一台设备后,
|
||
密码节点需要重新输入并保存密码。
|
||
|
||
## 配置与安全
|
||
|
||
查看配置路径:
|
||
|
||
```sh
|
||
klink config path
|
||
```
|
||
|
||
可以用全局参数或环境变量指定其他配置:
|
||
|
||
```sh
|
||
klink --config ./demo.json list
|
||
KLINK_CONFIG=./demo.json klink list
|
||
```
|
||
|
||
- 配置文件以 `0600` 权限原子写入
|
||
- 密码和私钥内容不会写入配置;只保存私钥路径
|
||
- 默认使用严格 HostKey 校验
|
||
- `accept-new` 允许首次写入主机密钥
|
||
- `insecure` 会禁用 HostKey 校验,仅应在明确理解风险时使用
|
||
- OpenSSH 参数通过结构化参数数组执行,不经过 shell 插值
|
||
|
||
## 许可证
|
||
|
||
klink 使用 [MIT License](LICENSE)。
|