diff --git a/backend/pkg/openvpn/manager.go b/backend/pkg/openvpn/manager.go index 28e2ffd..880b791 100644 --- a/backend/pkg/openvpn/manager.go +++ b/backend/pkg/openvpn/manager.go @@ -171,13 +171,13 @@ func (m *Manager) WriteServerConf(in *model.Instance, extraDir string) error { } if in.AuthMode == model.AuthCertPassword { // 双因素认证:证书 + 用户名密码 - // OpenVPN 以 via-env 方式调用 verify 脚本,环境变量: - // username= - // password=<用户输入的明文密码> + // OpenVPN 以 via-file 方式调用 verify 脚本,$1 为临时文件路径: + // 第 1 行 = VPN用户名(=证书CN) + // 第 2 行 = 用户输入的明文密码 // 脚本退出码 0 = 允许,非 0 = 拒绝 verifyScript := filepath.Join(m.InstanceDir(in.Name), "verify.sh") conf.WriteString("script-security 2\n") - conf.WriteString("auth-user-pass-verify \"" + verifyScript + "\" via-env\n") + conf.WriteString("auth-user-pass-verify \"" + verifyScript + "\" via-file\n") conf.WriteString("verify-client-cert require\n") _ = m.WriteVerifyScriptWithPort(in.Name, verifyScript, m.port) } @@ -507,16 +507,25 @@ func (m *Manager) WriteVerifyScript(instanceName, scriptPath string) error { // WriteVerifyScriptWithPort 生成带指定端口的认证脚本。 func (m *Manager) WriteVerifyScriptWithPort(instanceName, scriptPath string, port int) error { script := fmt.Sprintf(`#!/bin/bash -# OpenVPN auth-user-pass-verify script (via-env). +# OpenVPN auth-user-pass-verify script (via-file). # Generated by openvpn-manager — do NOT edit manually. -# Calls manager API to verify bcrypt password. Exit 0=allow, 1=deny. +# OpenVPN writes credentials to a temp file passed as $1: +# line 1 = username, line 2 = password LOG="/tmp/openvpn-verify.log" PORT=%d INSTANCE="%s" +CREDS_FILE="$1" -user="${username:-}" -pass="${password:-}" -echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') VERIFY user=$user instance=$INSTANCE" >> "$LOG" +echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') VERIFY instance=$INSTANCE creds_file=$CREDS_FILE" >> "$LOG" + +if [ -z "$CREDS_FILE" ] || [ ! -f "$CREDS_FILE" ]; then + echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') DENY no credentials file" >> "$LOG" + exit 1 +fi + +user=$(sed -n '1p' "$CREDS_FILE") +pass=$(sed -n '2p' "$CREDS_FILE") +echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') user=$user pass_len=${#pass}" >> "$LOG" if [ -z "$user" ] || [ -z "$pass" ]; then echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') DENY empty credentials" >> "$LOG" @@ -531,7 +540,7 @@ CODE=$(curl -s -o /tmp/ovpn-verify-resp.txt -w "%%{http_code}" \ 2>>"$LOG" || echo "000") BODY=$(cat /tmp/ovpn-verify-resp.txt 2>/dev/null) -echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') HTTP_CODE=$CODE BODY=$BODY" >> "$LOG" +echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') HTTP=$CODE BODY=$BODY" >> "$LOG" if [ "$CODE" = "200" ]; then echo "$(date '+%%Y-%%m-%%d %%H:%%M:%%S') ALLOW" >> "$LOG"