You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenVPN auth-user-pass-verify执行外部程序失败求助

解决OpenVPN auth-user-pass-verify无法执行外部脚本的问题

一、先手动验证脚本的可执行性

  • 切换到nobody用户执行脚本,模拟OpenVPN的运行环境,直接定位执行报错:
    su -s /bin/bash nobody -c "/etc/openvpn/auth2.sh /tmp/test_auth_file"
    
    提前创建/tmp/test_auth_file,第一行写测试用户名,第二行写测试密码。执行后观察是否有找不到命令、权限不足等明确报错。
  • 检查脚本shebang路径是否匹配系统环境:
    • Bash脚本:执行which bash,若输出为/bin/bash,将脚本开头的#!/usr/bin/bash改为#!/bin/bash;
    • Python脚本:执行which python3,确认路径与脚本中#!/usr/bin/python3一致,不一致则修改shebang。

二、修复文件与目录权限

  • 确保脚本所在目录对nobody有访问权限:
    chmod o+rx /etc/openvpn
    
  • Python脚本涉及的数据库文件与目录需开放读权限:
    # 开放db目录的访问权限
    chmod o+rx /etc/openvpn/db
    # 开放数据库文件的读权限
    chmod o+r /etc/openvpn/db/openvpn-ui.db
    

三、排查安全模块限制(SELinux/AppArmor)

  • SELinux排查:
    临时关闭SELinux测试:
    setenforce 0
    
    重启OpenVPN服务后若错误消失,说明是SELinux阻止了脚本执行,需添加允许规则:
    # 基于审计日志生成规则模块
    audit2allow -a -M openvpn_script
    # 加载规则
    semodule -i openvpn_script.pp
    
    规则加载完成后恢复SELinux:setenforce 1
  • AppArmor排查:
    打开OpenVPN的AppArmor配置文件(通常为/etc/apparmor.d/usr.sbin.openvpn),添加允许执行脚本的规则:
    /etc/openvpn/*.sh rPx,
    /usr/bin/python3 mrPx,
    
    重新加载AppArmor生效:
    systemctl reload apparmor
    

四、检查OpenVPN配置细节

  • 确认配置中未启用chroot选项:若启用chroot,脚本及所有依赖(bash、python3、curl等)必须放在chroot目录内,否则OpenVPN无法找到。
  • 检查临时文件目录权限:via-file模式下OpenVPN会在临时目录创建文件,默认/tmp需对nobody开放读写权限;也可在openvpn.conf中指定自定义临时目录:
    tmp-dir /etc/openvpn/tmp
    
    然后创建目录并设置权限:
    mkdir /etc/openvpn/tmp
    chown nobody:nobody /etc/openvpn/tmp
    chmod 700 /etc/openvpn/tmp
    

五、修正脚本本身的逻辑错误

Bash脚本修正:

  • 修复变量赋值方式、HTTP请求规范及JSON格式错误:
    #!/bin/bash
    
    PATH=$PATH:/usr/local/bin
    
    auth_usr=$(head -1 "$1")
    auth_passwd=$(tail -1 "$1")
    
    if [ "$common_name" = "$auth_usr" ]; then
      # 改用POST请求发送合法JSON格式参数
      result=$(/usr/bin/curl -s -X POST -H "Content-type: application/json" -d '{"username":"'"${auth_usr}"'","password":"'"${auth_passwd}"'"}' http://openvpn-ui:8080/auth)
      echo "$result"
      if [ "$result" = "Authorized" ]; then
        echo "Authorization succeeded"
        exit 0
      else
        echo "Authorization failed"
        exit 1
      fi
    else
      echo "Authorization failed"
      exit 1
    fi
    

Python脚本优化:

  • 添加异常捕获,处理数据库连接失败等异常情况:
    #!/usr/bin/python3
    
    import sys
    import sqlite3
    DB_FILE = '/etc/openvpn/db/openvpn-ui.db'
    
    
    def main():
        try:
            with open(sys.argv[1], 'r') as tmpfile:
                username = tmpfile.readline().rstrip('\n')
                password = tmpfile.readline().rstrip('\n')
    
            creds = get_password(username)
            if not creds:
                print(f'>> user {username} not defined.')
                sys.exit(1)
    
            if len(creds[0]) < 2 or password != creds[0][1]:
                print(f'>> Incorrect password provided by user {username}.')
                sys.exit(1)
    
            sys.exit(0)
        except Exception as e:
            print(f'>> Authentication error: {str(e)}')
            sys.exit(1)
    
    
    def get_password(username):
        try:
            db = sqlite3.connect(DB_FILE)
            cursor = db.cursor()
            cursor.execute('''select username, password from user where username=?''', (username, ))
            creds = cursor.fetchall()
            db.close()
            return creds
        except sqlite3.Error as e:
            print(f'>> Database error: {str(e)}')
            return []
    
    
    if __name__ == '__main__':
        main()
    

内容的提问来源于stack exchange,提问作者DISCO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 02:35:02