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:
@@ -27,6 +27,9 @@ import Database from "better-sqlite3";
|
|||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// Configure trust proxy to properly detect real client IP behind reverse proxy (nginx)
|
||||||
|
app.set('trust proxy', true);
|
||||||
|
|
||||||
// Initialize auth middleware
|
// Initialize auth middleware
|
||||||
const authManager = AuthManager.getInstance();
|
const authManager = AuthManager.getInstance();
|
||||||
const authenticateJWT = authManager.createAuthMiddleware();
|
const authenticateJWT = authManager.createAuthMiddleware();
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ const authManager = AuthManager.getInstance();
|
|||||||
const authenticateJWT = authManager.createAuthMiddleware();
|
const authenticateJWT = authManager.createAuthMiddleware();
|
||||||
const requireDataAccess = authManager.createDataAccessMiddleware();
|
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
|
// Internal-only endpoint for autostart - requires internal auth token
|
||||||
router.get("/db/host/internal", async (req: Request, res: Response) => {
|
router.get("/db/host/internal", async (req: Request, res: Response) => {
|
||||||
|
|||||||
@@ -570,6 +570,8 @@
|
|||||||
"sshpassRequired": "Sshpass Required For Password Authentication",
|
"sshpassRequired": "Sshpass Required For Password Authentication",
|
||||||
"sshpassRequiredDesc": "For password authentication in tunnels, sshpass must be installed on the system.",
|
"sshpassRequiredDesc": "For password authentication in tunnels, sshpass must be installed on the system.",
|
||||||
"otherInstallMethods": "Other installation methods:",
|
"otherInstallMethods": "Other installation methods:",
|
||||||
|
"debianUbuntuEquivalent": "(Debian/Ubuntu) or the equivalent for your OS.",
|
||||||
|
"or": "or",
|
||||||
"centosRhelFedora": "CentOS/RHEL/Fedora",
|
"centosRhelFedora": "CentOS/RHEL/Fedora",
|
||||||
"macos": "macOS",
|
"macos": "macOS",
|
||||||
"windows": "Windows",
|
"windows": "Windows",
|
||||||
|
|||||||
@@ -592,11 +592,21 @@
|
|||||||
"maxRetriesDescription": "隧道连接的最大重试次数。",
|
"maxRetriesDescription": "隧道连接的最大重试次数。",
|
||||||
"retryIntervalDescription": "重试尝试之间的等待时间。",
|
"retryIntervalDescription": "重试尝试之间的等待时间。",
|
||||||
"otherInstallMethods": "其他安装方法:",
|
"otherInstallMethods": "其他安装方法:",
|
||||||
|
"debianUbuntuEquivalent": "(Debian/Ubuntu) 或您的操作系统的等效命令。",
|
||||||
|
"or": "或",
|
||||||
|
"centosRhelFedora": "CentOS/RHEL/Fedora",
|
||||||
|
"macos": "macOS",
|
||||||
|
"windows": "Windows",
|
||||||
"sshpassOSInstructions": {
|
"sshpassOSInstructions": {
|
||||||
"centos": "CentOS/RHEL/Fedora: sudo yum install sshpass 或 sudo dnf install sshpass",
|
"centos": "CentOS/RHEL/Fedora: sudo yum install sshpass 或 sudo dnf install sshpass",
|
||||||
"macos": "macOS: brew install hudochenkov/sshpass/sshpass",
|
"macos": "macOS: brew install hudochenkov/sshpass/sshpass",
|
||||||
"windows": "Windows: 使用 WSL 或考虑使用 SSH 密钥认证"
|
"windows": "Windows: 使用 WSL 或考虑使用 SSH 密钥认证"
|
||||||
},
|
},
|
||||||
|
"sshServerConfigRequired": "SSH 服务器配置要求",
|
||||||
|
"sshServerConfigDesc": "对于隧道连接,SSH 服务器必须配置允许端口转发:",
|
||||||
|
"gatewayPortsYes": "绑定远程端口到所有接口",
|
||||||
|
"allowTcpForwardingYes": "启用端口转发",
|
||||||
|
"permitRootLoginYes": "如果使用 root 用户进行隧道连接",
|
||||||
"sshServerConfigReverse": "对于反向 SSH 隧道,端点 SSH 服务器必须允许:",
|
"sshServerConfigReverse": "对于反向 SSH 隧道,端点 SSH 服务器必须允许:",
|
||||||
"gatewayPorts": "GatewayPorts yes(绑定远程端口)",
|
"gatewayPorts": "GatewayPorts yes(绑定远程端口)",
|
||||||
"allowTcpForwarding": "AllowTcpForwarding yes(端口转发)",
|
"allowTcpForwarding": "AllowTcpForwarding yes(端口转发)",
|
||||||
|
|||||||
@@ -873,7 +873,7 @@ export function AdminSettings({
|
|||||||
<h4 className="font-medium">{t("admin.export")}</h4>
|
<h4 className="font-medium">{t("admin.export")}</h4>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Export SSH hosts and credentials as SQLite file
|
{t("admin.exportDescription")}
|
||||||
</p>
|
</p>
|
||||||
{showPasswordInput && (
|
{showPasswordInput && (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -925,7 +925,7 @@ export function AdminSettings({
|
|||||||
<h4 className="font-medium">{t("admin.import")}</h4>
|
<h4 className="font-medium">{t("admin.import")}</h4>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Import SQLite file with incremental merge (skips duplicates)
|
{t("admin.importDescription")}
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
|
|||||||
@@ -1149,7 +1149,7 @@ export function HostManagerEditor({
|
|||||||
<code className="bg-muted px-1 rounded inline">
|
<code className="bg-muted px-1 rounded inline">
|
||||||
sudo apt install sshpass
|
sudo apt install sshpass
|
||||||
</code>{" "}
|
</code>{" "}
|
||||||
(Debian/Ubuntu) or the equivalent for your OS.
|
{t("hosts.debianUbuntuEquivalent")}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<strong>{t("hosts.otherInstallMethods")}</strong>
|
<strong>{t("hosts.otherInstallMethods")}</strong>
|
||||||
@@ -1158,7 +1158,7 @@ export function HostManagerEditor({
|
|||||||
<code className="bg-muted px-1 rounded inline">
|
<code className="bg-muted px-1 rounded inline">
|
||||||
sudo yum install sshpass
|
sudo yum install sshpass
|
||||||
</code>{" "}
|
</code>{" "}
|
||||||
or{" "}
|
{t("hosts.or")}{" "}
|
||||||
<code className="bg-muted px-1 rounded inline">
|
<code className="bg-muted px-1 rounded inline">
|
||||||
sudo dnf install sshpass
|
sudo dnf install sshpass
|
||||||
</code>
|
</code>
|
||||||
|
|||||||
Reference in New Issue
Block a user