diff --git a/README-CN.md b/README-CN.md index 65b82cb0..ea7fdde1 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,7 +1,7 @@ # 仓库统计
@@ -44,22 +44,24 @@ Termix 是一个开源、永久免费、自托管的一体化服务器管理平台。它提供了一个基于网页的解决方案,通过一个直观的界面管理你的服务器和基础设施。Termix -提供 SSH 终端访问、SSH 隧道功能以及远程文件管理,还会陆续添加更多工具。 +提供 SSH 终端访问、SSH 隧道功能以及远程文件管理,还会陆续添加更多工具。Termix 是适用于所有平台的完美免费自托管 Termius 替代品。 # 功能 -- **SSH 终端访问** - 功能完整的终端,支持分屏(最多 4 个面板)和标签系统 -- **SSH 隧道管理** - 创建和管理 SSH 隧道,支持自动重连和健康监控 -- **远程文件管理器** - 直接在远程服务器上管理文件,支持查看和编辑代码、图片、音频和视频。无缝上传、下载、重命名、删除和移动文件。 -- **SSH 主机管理器** - 保存、组织和管理 SSH 连接,支持标签和文件夹,轻松保存可重用的登录信息,同时能够自动部署 SSH 密钥 -- **服务器统计** - 查看任意 SSH 服务器的 CPU、内存和硬盘使用情况 -- **用户认证** - 安全的用户管理,支持管理员控制、OIDC 和双因素认证(TOTP) -- **数据库加密** - SQLite 数据库文件在静态时加密,支持自动加密/解密 -- **数据导出/导入** - 导出和导入 SSH 主机、凭据和文件管理器数据,支持增量同步 +- **SSH 终端访问** - 功能齐全的终端,具有分屏支持(最多 4 个面板)和类似浏览器的选项卡系统。包括对自定义终端的支持,包括常见终端主题、字体和其他组件 +- **SSH 隧道管理** - 创建和管理 SSH 隧道,具有自动重新连接和健康监控功能 +- **远程文件管理器** - 直接在远程服务器上管理文件,支持查看和编辑代码、图像、音频和视频。无缝上传、下载、重命名、删除和移动文件 +- **SSH 主机管理器** - 保存、组织和管理您的 SSH 连接,支持标签和文件夹,并轻松保存可重用的登录信息,同时能够自动部署 SSH 密钥 +- **服务器统计** - 在任何 SSH 服务器上查看 CPU、内存和磁盘使用情况以及网络、正常运行时间和系统信息 +- **仪表板** - 在仪表板上一目了然地查看服务器信息 +- **用户认证** - 安全的用户管理,具有管理员控制以及 OIDC 和 2FA (TOTP) 支持。查看所有平台上的活动用户会话并撤销权限。 +- **数据库加密** - 后端存储为加密的 SQLite 数据库文件 +- **数据导出/导入** - 导出和导入 SSH 主机、凭据和文件管理器数据 - **自动 SSL 设置** - 内置 SSL 证书生成和管理,支持 HTTPS 重定向 -- **现代化界面** - 使用 React、Tailwind CSS 和 Shadcn 构建的简洁桌面/移动友好界面 -- **语言支持** - 内置英语、中文和德语支持 -- **平台支持** - 提供 Web 应用、桌面应用程序(Windows 和 Linux)以及 iOS 和 Android 专用移动应用。计划支持 macOS 和 iPadOS。 +- **现代用户界面** - 使用 React、Tailwind CSS 和 Shadcn 构建的简洁的桌面/移动设备友好界面 +- **语言** - 内置支持英语、中文、德语和葡萄牙语 +- **平台支持** - 可作为 Web 应用程序、桌面应用程序(Windows、Linux 和 macOS)以及适用于 iOS 和 Android 的专用移动/平板电脑应用程序。 +- **SSH 工具** - 创建可重用的命令片段,单击即可执行。在多个打开的终端上同时运行一个命令。 # 计划功能 @@ -69,14 +71,28 @@ Termix 是一个开源、永久免费、自托管的一体化服务器管理平 支持的设备: -- 网站(任何现代浏览器,如 Google、Safari 和 Firefox) -- Windows(应用程序) -- Linux(应用程序) -- iOS(应用程序) -- Android(应用程序) -- iPadOS 和 macOS 正在开发中 +- 网站(任何平台上的任何现代浏览器,如 Chrome、Safari 和 Firefox) +- Windows(x64/ia32) + - 便携版 + - MSI 安装程序 + - Chocolatey 软件包管理器 +- Linux(x64/ia32) + - 便携版 + - AppImage + - Deb + - Flatpak +- macOS(x64/ia32 on v12.0+) + - Apple App Store + - DMG + - Homebrew +- iOS/iPadOS(v15.1+) + - Apple App Store + - ISO +- Android(v7.0+) + - Google Play 商店 + - APK -访问 Termix [文档](https://docs.termix.site/install) 获取所有平台的安装信息。或者可以参考以下示例 docker-compose 文件: +访问 Termix [文档](https://docs.termix.site/install) 了解有关如何在所有平台上安装 Termix 的更多信息。或者,在此处查看示例 Docker Compose 文件: ```yaml services: @@ -128,6 +144,7 @@ volumes: 你的浏览器不支持 video 标签。 +视频和图像可能已过时。 # 许可证 diff --git a/README.md b/README.md index b57f98e1..e0d99567 100644 --- a/README.md +++ b/README.md @@ -75,12 +75,12 @@ Supported Devices: - Website (any modern browser on any platform like Chrome, Safari, and Firefox) - Windows (x64/ia32) - - Portable EXE + - Portable - MSI Installer - Chocolatey Package Manager - Linux (x64/ia32) - - Portable EXE - - Appimage + - Portable + - AppImage - Deb - Flatpak - macOS (x64/ia32 on v12.0+) @@ -147,6 +147,7 @@ channel, however, response times may be longer. Your browser does not support the video tag. +Videos and images may be out of date. # License diff --git a/repo-images/Image 1.png b/repo-images/Image 1.png index 7a398fb4..fea7eb76 100644 Binary files a/repo-images/Image 1.png and b/repo-images/Image 1.png differ diff --git a/repo-images/Image 2.png b/repo-images/Image 2.png index e7a1f6b8..9a47b331 100644 Binary files a/repo-images/Image 2.png and b/repo-images/Image 2.png differ diff --git a/repo-images/Image 3.png b/repo-images/Image 3.png index 70077cdf..4179a57a 100644 Binary files a/repo-images/Image 3.png and b/repo-images/Image 3.png differ diff --git a/repo-images/Image 4.png b/repo-images/Image 4.png index 5cb16b6c..e2dfa99a 100644 Binary files a/repo-images/Image 4.png and b/repo-images/Image 4.png differ diff --git a/repo-images/Image 5.png b/repo-images/Image 5.png index 868e5c27..e44011e0 100644 Binary files a/repo-images/Image 5.png and b/repo-images/Image 5.png differ diff --git a/repo-images/Image 6.png b/repo-images/Image 6.png index 9d87ba0f..f6f70ba1 100644 Binary files a/repo-images/Image 6.png and b/repo-images/Image 6.png differ diff --git a/src/backend/ssh/file-manager.ts b/src/backend/ssh/file-manager.ts index 7a543ab1..31a8403a 100644 --- a/src/backend/ssh/file-manager.ts +++ b/src/backend/ssh/file-manager.ts @@ -413,6 +413,27 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { }); client.on("error", (err) => { + if ( + (err.message.includes("All configured authentication methods failed") || + err.message.includes("No authentication methods remaining")) && + resolvedCredentials.authType === "password" && + !config.password && + resolvedCredentials.password && + !userProvidedPassword + ) { + fileLogger.info( + "Retrying password auth with password method for file manager", + { + operation: "file_connect_retry", + sessionId, + hostId, + }, + ); + config.password = resolvedCredentials.password; + client.connect(config); + return; + } + if (responseSent) return; responseSent = true; fileLogger.error("SSH connection failed for file manager", { diff --git a/src/backend/ssh/terminal.ts b/src/backend/ssh/terminal.ts index 12af8974..cf93f9f8 100644 --- a/src/backend/ssh/terminal.ts +++ b/src/backend/ssh/terminal.ts @@ -362,7 +362,10 @@ wss.on("connection", async (ws: WebSocket, req) => { } }); - async function handleConnectToHost(data: ConnectToHostData) { + async function handleConnectToHost( + data: ConnectToHostData, + retryWithPassword = false, + ) { const { hostConfig, initialPath, executeCommand } = data; const { id, @@ -658,6 +661,22 @@ wss.on("connection", async (ws: WebSocket, req) => { sshConn.on("error", (err: Error) => { clearTimeout(connectionTimeout); + if ( + (err.message.includes("All configured authentication methods failed") || + err.message.includes("No authentication methods remaining")) && + resolvedCredentials.authType === "password" && + !retryWithPassword && + !(hostConfig as any).userProvidedPassword + ) { + sshLogger.info("Retrying password auth with password method", { + operation: "ssh_connect_retry", + hostId: id, + }); + cleanupSSH(); + handleConnectToHost(data, true); + return; + } + if ( (authMethodNotAvailable && resolvedCredentials.authType === "none") || (resolvedCredentials.authType === "none" && @@ -912,7 +931,7 @@ wss.on("connection", async (ws: WebSocket, req) => { return; } - if ((hostConfig as any).userProvidedPassword) { + if ((hostConfig as any).userProvidedPassword || retryWithPassword) { connectConfig.password = resolvedCredentials.password; } } else if (