Fix VPN verify: via-env→via-file, add pass_len debug logging

OpenVPN 2.7 Windows DCO passes username but NOT password as
environment variable with via-env mode. Switched to via-file:
  server.conf: auth-user-pass-verify script via-file
  verify.sh reads credentials from temp file ():
    line 1 = username, line 2 = password

Also added pass_len to debug log so we can immediately see
if the password was actually received by the script.
This commit is contained in:
cnbugs
2026-08-09 23:34:05 +08:00
parent 70341c78e5
commit f3cda67d9f
+19 -10
View File
@@ -171,13 +171,13 @@ func (m *Manager) WriteServerConf(in *model.Instance, extraDir string) error {
}
if in.AuthMode == model.AuthCertPassword {
// 双因素认证:证书 + 用户名密码
// OpenVPN 以 via-env 方式调用 verify 脚本,环境变量:
// username=<VPN用户名(=证书CN)>
// 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"