FIX: Resolve critical reverse proxy security vulnerability and complete i18n implementation

Security Fixes:
- Configure Express trust proxy to properly detect client IPs behind nginx reverse proxy
- Remove deprecated isLocalhost() function that was vulnerable to IP spoofing
- Ensure /ssh/db/host/internal endpoint uses secure token-based authentication only

Internationalization Improvements:
- Replace hardcoded English strings with proper i18n keys in admin settings
- Complete SSH configuration documentation translation (sshpass, server config)
- Add missing translation keys for Debian/Ubuntu, macOS, Windows installation methods
- Fix Chinese translation key mismatches for SSH server configuration options

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ZacharyZcR
2025-09-25 07:28:17 +08:00
parent 2006a0a089
commit dad9282dfa
6 changed files with 19 additions and 8 deletions

View File

@@ -27,6 +27,9 @@ import Database from "better-sqlite3";
const app = express();
// Configure trust proxy to properly detect real client IP behind reverse proxy (nginx)
app.set('trust proxy', true);
// Initialize auth middleware
const authManager = AuthManager.getInstance();
const authenticateJWT = authManager.createAuthMiddleware();

View File

@@ -40,10 +40,6 @@ const authManager = AuthManager.getInstance();
const authenticateJWT = authManager.createAuthMiddleware();
const requireDataAccess = authManager.createDataAccessMiddleware();
function isLocalhost(req: Request) {
const ip = req.ip || req.connection?.remoteAddress;
return ip === "127.0.0.1" || ip === "::1" || ip === "::ffff:127.0.0.1";
}
// Internal-only endpoint for autostart - requires internal auth token
router.get("/db/host/internal", async (req: Request, res: Response) => {

View File

@@ -570,6 +570,8 @@
"sshpassRequired": "Sshpass Required For Password Authentication",
"sshpassRequiredDesc": "For password authentication in tunnels, sshpass must be installed on the system.",
"otherInstallMethods": "Other installation methods:",
"debianUbuntuEquivalent": "(Debian/Ubuntu) or the equivalent for your OS.",
"or": "or",
"centosRhelFedora": "CentOS/RHEL/Fedora",
"macos": "macOS",
"windows": "Windows",

View File

@@ -592,11 +592,21 @@
"maxRetriesDescription": "隧道连接的最大重试次数。",
"retryIntervalDescription": "重试尝试之间的等待时间。",
"otherInstallMethods": "其他安装方法:",
"debianUbuntuEquivalent": "(Debian/Ubuntu) 或您的操作系统的等效命令。",
"or": "或",
"centosRhelFedora": "CentOS/RHEL/Fedora",
"macos": "macOS",
"windows": "Windows",
"sshpassOSInstructions": {
"centos": "CentOS/RHEL/Fedora: sudo yum install sshpass 或 sudo dnf install sshpass",
"macos": "macOS: brew install hudochenkov/sshpass/sshpass",
"windows": "Windows: 使用 WSL 或考虑使用 SSH 密钥认证"
},
"sshServerConfigRequired": "SSH 服务器配置要求",
"sshServerConfigDesc": "对于隧道连接SSH 服务器必须配置允许端口转发:",
"gatewayPortsYes": "绑定远程端口到所有接口",
"allowTcpForwardingYes": "启用端口转发",
"permitRootLoginYes": "如果使用 root 用户进行隧道连接",
"sshServerConfigReverse": "对于反向 SSH 隧道,端点 SSH 服务器必须允许:",
"gatewayPorts": "GatewayPorts yes绑定远程端口",
"allowTcpForwarding": "AllowTcpForwarding yes端口转发",

View File

@@ -873,7 +873,7 @@ export function AdminSettings({
<h4 className="font-medium">{t("admin.export")}</h4>
</div>
<p className="text-xs text-muted-foreground">
Export SSH hosts and credentials as SQLite file
{t("admin.exportDescription")}
</p>
{showPasswordInput && (
<div className="space-y-2">
@@ -925,7 +925,7 @@ export function AdminSettings({
<h4 className="font-medium">{t("admin.import")}</h4>
</div>
<p className="text-xs text-muted-foreground">
Import SQLite file with incremental merge (skips duplicates)
{t("admin.importDescription")}
</p>
<input
type="file"

View File

@@ -1149,7 +1149,7 @@ export function HostManagerEditor({
<code className="bg-muted px-1 rounded inline">
sudo apt install sshpass
</code>{" "}
(Debian/Ubuntu) or the equivalent for your OS.
{t("hosts.debianUbuntuEquivalent")}
</div>
<div className="mt-2">
<strong>{t("hosts.otherInstallMethods")}</strong>
@@ -1158,7 +1158,7 @@ export function HostManagerEditor({
<code className="bg-muted px-1 rounded inline">
sudo yum install sshpass
</code>{" "}
or{" "}
{t("hosts.or")}{" "}
<code className="bg-muted px-1 rounded inline">
sudo dnf install sshpass
</code>