自动部署(使用官方安装脚本)
bash <(curl -fsS https://packages.openvpn.net/as/install.sh) --yes

docker部署(官方版)
docker run -d --name=openvpn-as \
--restart=always \
-v /data/openvpn-as/config:/config \
-e INTERFACE=ens192 -e PGID=1001 -e PUID=1001 -e TZ=Asia/Shanghai \
-d -p 1194:1194/udp -p 443:443/tcp -p 943:943/tcp \
--net=host --privileged \
openvpn/openvpn-as
-p 1194:1194/udp -p 443:443/tcp -p 943:943/tcp这部分也可以不加直接默认。执行后要过一会需要下载镜像和初始化服务。可以通过以下命令看日志是否完成
docker logs -f openvpn-as
完成后就可以通过:https://ip:943(这里使用的是https地址)进行访问,默认用户名、密码:admin/password。进入后就可以下载客户端配置文件了,就可以通过客户端进行连接。
docker部署(破解版––2048连接数)
参考资料:原文:OpenVPN Access Server 2.13.1 破解人数限制(已更新到最新版)-个人计算机技术知识记录
github:bigQY/openvpn-as: OpenVPN-Access Server with 2048 licenses
docker-compose.yml
version: "3.8"
services:
openvpn-as:
build:
context: .
dockerfile: Dockerfile
container_name: openvpn-as
network_mode: host
privileged: true
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- MKNOD
volumes:
- ./openvpn-data:/openvpn
environment:
- INTERFACE=ens18
restart: unless-stopped
Dockerfile
FROM openvpn/openvpn-as
COPY uprop.py /tmp/uprop.py
COPY process_egg.sh /tmp/process_egg.sh
RUN chmod +x /tmp/process_egg.sh && \
/tmp/process_egg.sh && \
rm -rf /tmp/pyovpn /tmp/EGG-INFO /tmp/common /tmp/uprop.py /tmp/process_egg.sh
在容器中处理python文件的shell脚本process_egg.sh
#!/bin/bash
set -e
echo "🔧 开始处理 egg 文件..."
# 复制egg文件到临时目录
cp /usr/local/openvpn_as/lib/python/pyovpn-2.0-py3.12.egg /tmp/
cd /tmp
# 解压
python3 -m zipfile -e pyovpn-2.0-py3.12.egg .
# 备份原文件
mv pyovpn/lic/uprop.pyc pyovpn/lic/uprop2.pyc
# 复制新文件
cp /tmp/uprop.py pyovpn/lic/
# 编译
python3 -O -m compileall pyovpn/lic/uprop.py
mv pyovpn/lic/__pycache__/uprop.*.pyc pyovpn/lic/uprop.pyc
# 重新打包
python3 -m zipfile -c pyovpn-2.0-py3.12.egg pyovpn EGG-INFO common
# 移动回原位置
mv pyovpn-2.0-py3.12.egg /usr/local/openvpn_as/lib/python/
echo "✅ 处理完成!"
破解关键:uprop.py
from pyovpn.lic import uprop2
old_figure = None
def new_figure(self, licdict):
ret = old_figure(self, licdict)
ret['concurrent_connections'] = 2048
return ret
for x in dir(uprop2):
if x[:2] == '__':
continue
if x == 'UsageProperties':
exec('old_figure = uprop2.UsageProperties.figure')
exec('uprop2.UsageProperties.figure = new_figure')
exec('%s = uprop2.%s' % (x, x))
#!/bin/bash
# 🔧 完整的OpenVPN-AS配置脚本
docker exec -it openvpn-as bash -c "
# ========== 基础网络配置 ==========
echo '=== 配置网络地址池 ==='
# 动态客户端地址池
/usr/local/openvpn_as/scripts/sacli --key 'vpn.daemon.0.client.network' --value '10.8.1.0' ConfigPut
/usr/local/openvpn_as/scripts/sacli --key 'vpn.daemon.0.client.netmask_bits' --value '24' ConfigPut
# 静态IP地址池
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.static.0.network' --value '10.8.2.0' ConfigPut
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.static.0.netmask_bits' --value '24' ConfigPut
# 默认组地址池
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.group_pool.0' --value '10.8.3.0/24' ConfigPut
# ========== 端口配置 ==========
echo '=== 配置监听端口 ==='
# Web界面端口
/usr/local/openvpn_as/scripts/sacli --key 'cs.https.port' --value '443' ConfigPut
/usr/local/openvpn_as/scripts/sacli --key 'admin_ui.https.port' --value '943' ConfigPut
# VPN监听端口配置(主要的)
/usr/local/openvpn_as/scripts/sacli --key 'vpn.daemon.0.listen.port' --value '1194' ConfigPut
/usr/local/openvpn_as/scripts/sacli --key 'vpn.daemon.0.listen.ip_address' --value 'all' ConfigPut
# ========== 访问控制配置 ==========
echo '=== 配置访问控制 ==='
# 禁用重路由网关(不强制所有流量走VPN)
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.routing.reroute_gw' --value 'false' ConfigPut
/usr/local/openvpn_as/scripts/sacli --key 'vpn.client.routing.reroute_gw' --value 'false' ConfigPut
# 🔑 DNS配置:设置DNS服务器
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.dhcp_option.dns.0' --value '192.168.99.254' ConfigPut
# 设置默认拒绝私有网络访问
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.routing.private_access' --value 'no' ConfigPut
# 移除全局私有网络路由
/usr/local/openvpn_as/scripts/sacli --key 'vpn.server.routing.private_network.0' ConfigDel || true
# ========== 应用配置 ==========
echo '=== 重启服务应用配置 ==='
/usr/local/openvpn_as/scripts/sacli stop
sleep 10
/usr/local/openvpn_as/scripts/sacli start
echo '=== 配置完成 ==='
"
# 验证默认拒绝配置
echo "=== 验证默认拒绝策略配置 ==="
docker exec openvpn-as /usr/local/openvpn_as/scripts/sacli ConfigQuery | grep -E "(routing|dhcp|private_access)"
# 检查是否成功移除全局路由
echo -e "\n=== 检查私有网络路由(应该为空) ==="
docker exec openvpn-as /usr/local/openvpn_as/scripts/sacli ConfigQuery | grep "private_network" || echo "✅ 已成功移除全局私有网络路由"
#验证默认路由策略
docker exec openvpn-as bash -c "
echo '=== 路由层配置验证 ==='
echo '1. 检查私有网络路由(应该为空或无99网段):'
/usr/local/openvpn_as/scripts/sacli ConfigQuery | grep -E 'vpn.server.routing.private_network' || echo '✅ 无私有网络路由配置'
echo -e '\n2. 检查私有网络访问权限:'
/usr/local/openvpn_as/scripts/sacli ConfigQuery | grep -E 'private_access|gateway_access'
echo -e '\n3. 检查重路由配置:(应该为两个false)'
/usr/local/openvpn_as/scripts/sacli ConfigQuery | grep 'reroute_gw'
"
以上脚本的端口方案为:943作为web页面管理端口;443作为客户端访问的页面;1194作为vpn连接端口,但是openvpn-as服务端不监听这个端口,因为有内置的端口转发,将1194端口流量转发到914进行处理连接
互联网
↓
公网服务器 (NPS Server)
├─ 443/TCP → 内网容器:443 (Web界面)
├─ 943/TCP → 内网容器:943 (Admin界面)
├─ 1194/TCP → 内网容器:914 (VPN TCP)
├─ 1194/UDP → 内网容器:916 (VPN UDP - 主要)
└─ 1195/UDP → 内网容器:917 (VPN UDP - 备用)
↓ NPS隧道
内网OpenVPN容器
├─ 443: Web服务 (python3)
├─ 943: Admin界面 (python3)
├─ 914: OpenVPN TCP
├─ 915: OpenVPN TCP备用
├─ 916: OpenVPN UDP
└─ 917: OpenVPN UDP备用
使用流程:
脚本跑完后自动安装启动服务,页面显示Success,web管理页面的地址和密码在:/usr/local/openvpn_as/init.log
或者直接命令行重置密码:
#docker部署需要进入容器
#docker compose exec -it openvpn-as bash
/usr/local/openvpn_as/scripts/sacli --user openvpn --new_pass 'YourNewPassword123!' SetLocalPassword
登录init.log页面提示的地址:

重置管理员密码:
页面操作:Users––Edit User––Reset Password



命令行操作:
# 修改 openvpn 用户密码
/usr/local/openvpn_as/scripts/sacli --user openvpn --new_pass 'YourNewPassword123!' SetLocalPassword
/usr/local/openvpn_as/scripts/sacli --user openvpn --new_pass 'Suit@2025' SetLocalPassword
# 验证密码修改成功(查看用户属性)
/usr/local/openvpn_as/scripts/sacli --user openvpn UserPropGet
# 创建用户并设置密码
/usr/local/openvpn_as/scripts/sacli --user testuser --new_pass 'TestPassword123!' SetLocalPassword
/usr/local/openvpn_as/scripts/sacli --user testuser1 --new_pass 'Suit@2025' SetLocalPassword
# 授予 VPN 访问权限
/usr/local/openvpn_as/scripts/sacli --user testuser --key "prop_autologin" --value "true" UserPropPut
# 查看用户列表
/usr/local/openvpn_as/scripts/sacli UserPropGet
# 修改用户密码
/usr/local/openvpn_as/scripts/sacli --user testuser --new_pass 'NewPassword456!' SetLocalPassword
# 删除用户的本地密码
/usr/local/openvpn_as/scripts/sacli --user testuser RemoveLocalPassword
# 删除整个用户配置
/usr/local/openvpn_as/scripts/sacli --user testuser UserPropDelAll
#常用的 sacli 命令速查
# 查看所有用户
/usr/local/openvpn_as/scripts/sacli UserPropGet
# 查看特定用户信息
/usr/local/openvpn_as/scripts/sacli --user openvpn UserPropGet
# 查看当前 VPN 连接状态
/usr/local/openvpn_as/scripts/sacli VPNStatus
# 查看 VPN 摘要信息
/usr/local/openvpn_as/scripts/sacli VPNSummary
# 查看服务状态
/usr/local/openvpn_as/scripts/sacli Status
# 查看版本信息
/usr/local/openvpn_as/scripts/sacli Version
# 查看配置信息
/usr/local/openvpn_as/scripts/sacli ConfigQuery
# 重启服务
/usr/local/openvpn_as/scripts/sacli Start

🌐 VPN 服务器配置
步骤 1: 配置网络设置
点击左侧菜单 VPN Server → Network Settings
1.1 配置主机名和 IP 地址
Hostname or IP Address:
- 输入: 114.55.148.180(您的服务器公网 IP 或域名)
- 这是客户端连接时使用的地址
Interface and IP Address:
- Protocol: All interfaces (UDP, TCP)
- Port: 1194(默认)或自定义端口

页面提示:Port 1194 also redirects to the admin and client web servers. You can configure this in the Web Services.:说明用于vpn连接的守护进程的1194端口也会被重定向到web页面

客户端web页面和管理端使用不同的端口:管理端943,客户端443


1.2 配置 VPN 网段
Dynamic IP Address Network:
- 输入: 10.8.1.0/24
- 这是分配给 VPN 客户端的 IP 地址池
Static IP Address Network:
- 输入: 10.8.2.0/24
- 用于静态 IP 分配(可选)
# 默认组地址池
- 输入: 10.8.3.0/24

步骤3:创建 VPN 用户
方法 1: Web 界面创建用户
- 点击左侧 Users → Add New User

- 在底部输入用户名,点击 Save


步骤4:访问控制配置

配置允许用户/用户组访问的网段

步骤5:配置DNS

禁用用户:删除对应证书或者锁定


客户端连接:进入客户端web页面下载连接工具:

运行客户端工具输入密码即可连接:

命令行配置用户有效期
#配置全局CA证书有效期10年:
# /usr/local/openvpn_as/scripts/sacli ShowCAs
Sn Type Common Name ClientCerts Valid from Valid Until KeyAlg Signing CA
1770600802 Current CA OpenVPN CA 1 2026-02-08 2026-05-10 rsa2048 -
# /usr/local/openvpn_as/scripts/sacli --exp 3650 Init
# /usr/local/openvpn_as/scripts/sacli Reset
# /usr/local/openvpn_as/scripts/sacli ShowCAs
Sn Type Common Name ClientCerts Valid from Valid Until KeyAlg Signing CA
1770600956 Current CA OpenVPN CA 0 2026-02-08 2036-02-07 rsa2048 -
#步骤1:设置全局证书有效期为90天(web页面生成的证书有效期90天)
/usr/local/openvpn_as/scripts/sa --client_certificate_lifetime=90 setpkiconfig
#检查设置
/usr/local/openvpn_as/scripts/sa showpkiconfig
#设置单独用户配置文件有效期:
/usr/local/openvpn_as/scripts/sacli --user testuser3 --exp 180 GetUserlogin
#为了达到真正的限制效果还需要以下操作:
#禁止用户自己生成新的配置文件
./sacli --user testuser3 --key "prop_autogenerate" --value "false" UserPropPut
/usr/local/openvpn_as/scripts/sacli start
配置用户配置文件有效期脚本:
#!/bin/bash
# OpenVPN AS 用户证书管理脚本
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 配置变量
CONTAINER_NAME=""
SCRIPT_DIR="/usr/local/openvpn_as/scripts"
CERT_OUTPUT_DIR="./usercerts"
TEMP_CERT_DIR="/tmp"
print_success() {
echo -e "${GREEN}✓ $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠ $1${NC}"
}
print_error() {
echo -e "${RED}✗ $1${NC}"
exit 1
}
detect_container() {
if [ -z "$CONTAINER_NAME" ]; then
echo -e "\n${YELLOW}正在检测 OpenVPN AS 容器...${NC}"
CONTAINER_NAME=$(docker ps --format "{{.Names}}" | grep -i "openvpn\|ovpn" | head -1)
if [ -z "$CONTAINER_NAME" ]; then
print_error "未找到 OpenVPN AS 容器,请手动指定容器名称"
fi
print_success "检测到容器: $CONTAINER_NAME"
read -p "是否使用此容器? (y/n): " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
print_error "操作已取消"
fi
fi
}
check_output_dir() {
if [ ! -d "$CERT_OUTPUT_DIR" ]; then
mkdir -p "$CERT_OUTPUT_DIR"
fi
}
exec_container() {
docker exec "$CONTAINER_NAME" "$@"
}
set_global_cert_lifetime() {
echo -e "\n${YELLOW}===== 全局证书有效期配置 =====${NC}"
echo "当前配置:"
exec_container $SCRIPT_DIR/sa showpkiconfig
local current_days=$(exec_container $SCRIPT_DIR/sa showpkiconfig 2>&1 | grep "client_certificate_lifetime" | awk '{print $2}')
echo ""
read -p "是否需要修改全局证书有效期? (当前: ${current_days}天) [y/n]: " modify_choice
if [[ "$modify_choice" =~ ^[Yy]$ ]]; then
read -p "请输入新的有效期(天数): " new_days
if [[ -z "$new_days" ]] || ! [[ "$new_days" =~ ^[0-9]+$ ]]; then
echo "输入无效,保持当前配置"
else
exec_container $SCRIPT_DIR/sa --client_certificate_lifetime=$new_days setpkiconfig
echo "✓ 全局证书有效期已设置为 ${new_days} 天"
exec_container $SCRIPT_DIR/sa showpkiconfig
fi
else
echo "保持当前配置: ${current_days} 天"
fi
}
# 函数: 获取用户输入
get_user_input() {
echo -e "\n${YELLOW}===== 输入用户信息 =====${NC}"
read -p "请输入用户名: " USERNAME
if [ -z "$USERNAME" ]; then
print_error "用户名不能为空"
fi
}
# 函数: 选择证书有效期
select_cert_lifetime() {
echo -e "\n${YELLOW}===== 选择证书有效期 =====${NC}"
echo "1) 90天 (3个月)"
echo "2) 180天 (6个月)"
echo "3) 365天 (1年)"
echo "4) 自定义天数"
read -p "请选择 [1-4]: " choice
case $choice in
1) CERT_DAYS=90; CERT_DESC="90天" ;;
2) CERT_DAYS=180; CERT_DESC="180天" ;;
3) CERT_DAYS=365; CERT_DESC="365天" ;;
4)
read -p "请输入自定义天数: " CERT_DAYS
CERT_DESC="${CERT_DAYS}天"
;;
esac
echo "✓ 已选择证书有效期: $CERT_DESC"
}
# 函数: 从文件批量处理用户
batch_process_users() {
local batch_file="$1"
if [ "$batch_file" = "." ]; then
batch_file="./batch_users_example.txt"
fi
echo -e "\n${YELLOW}===== 批量处理模式 =====${NC}"
echo "从文件读取用户列表: $batch_file"
echo ""
local total_users=0
local success_users=0
while IFS=' ' read -r username days || [ -n "$username" ]; do
# 跳过空行和注释
if [[ -z "$username" ]] || [[ "$username" =~ ^#.* ]]; then
continue
fi
username=$(echo "$username" | xargs)
days=$(echo "$days" | xargs)
# 验证格式
if [[ -z "$username" ]] || [[ -z "$days" ]] || ! [[ "$days" =~ ^[0-9]+$ ]]; then
continue
fi
((total_users++))
echo -e "\n处理用户 [$total_users]: $username (${days}天)"
USERNAME="$username"
CERT_DAYS="$days"
CERT_DESC="${days}天"
if create_user_if_not_exists && generate_user_cert; then
((success_users++))
echo "✓ 用户 $username 处理完成"
else
echo "✗ 用户 $username 处理失败"
fi
done < "$batch_file"
echo -e "\n===== 批量处理完成 ====="
echo "总用户数: $total_users"
echo "成功: $success_users"
echo ""
}
# 函数: 创建用户(如果不存在)
create_user_if_not_exists() {
local user_exists=$(exec_container $SCRIPT_DIR/sacli --pfilt "$USERNAME" UserPropGet 2>&1 | grep "\"$USERNAME\"")
if [ -z "$user_exists" ]; then
echo "创建新用户: $USERNAME"
exec_container $SCRIPT_DIR/sacli --user "$USERNAME" --key "type" --value "user_connect" UserPropPut > /dev/null 2>&1
fi
return 0
}
# 函数: 生成用户证书
generate_user_cert() {
echo -e "\n${YELLOW}===== 生成用户证书 =====${NC}"
local expiry_date=$(date -d "+${CERT_DAYS} days" +%Y-%m-%d)
echo "正在为用户 $USERNAME 生成 ${CERT_DESC} 有效期的证书..."
echo "过期日期: $expiry_date"
# 检查并临时开启 prop_autogenerate
local current_autogen=$(exec_container $SCRIPT_DIR/sacli --pfilt "$USERNAME" UserPropGet 2>&1 | grep "prop_autogenerate" | awk -F'"' '{print $4}')
local need_restore=false
if [ "$current_autogen" = "false" ]; then
echo "临时开启自动生成权限..."
exec_container $SCRIPT_DIR/sacli --user "$USERNAME" --key "prop_autogenerate" --value "true" UserPropPut > /dev/null 2>&1
need_restore=true
fi
# 生成证书
exec_container mkdir -p "$TEMP_CERT_DIR/$USERNAME"
local output=$(exec_container $SCRIPT_DIR/sacli --user "$USERNAME" --exp "$CERT_DAYS" GetUserlogin 2>&1)
# 保存到临时文件
exec_container bash -c "cat > $TEMP_CERT_DIR/$USERNAME/$USERNAME-$expiry_date.ovpn << 'EOF'
$output
EOF"
# 复制到宿主机
mkdir -p "$CERT_OUTPUT_DIR/$USERNAME"
docker cp "$CONTAINER_NAME:$TEMP_CERT_DIR/$USERNAME/$USERNAME-$expiry_date.ovpn" "$CERT_OUTPUT_DIR/$USERNAME/"
exec_container rm -rf "$TEMP_CERT_DIR/$USERNAME"
# 恢复 prop_autogenerate 为 false
if [ "$need_restore" = true ]; then
echo "恢复禁止自动生成配置..."
exec_container $SCRIPT_DIR/sacli --user "$USERNAME" --key "prop_autogenerate" --value "false" UserPropPut > /dev/null 2>&1
fi
echo "✓ 证书已保存到: $CERT_OUTPUT_DIR/$USERNAME/$USERNAME-$expiry_date.ovpn"
return 0
}
# 函数: 重启服务
restart_service() {
echo -e "\n${YELLOW}===== 重启 OpenVPN AS 服务 =====${NC}"
exec_container $SCRIPT_DIR/sacli start
echo "✓ 服务重启完成"
}
# 函数: 显示用户最终配置
show_user_config() {
echo -e "\n${YELLOW}===== 用户配置信息 =====${NC}"
exec_container $SCRIPT_DIR/sacli --pfilt "$USERNAME" UserPropGet
}
# 主函数
main() {
echo -e "${GREEN}"
echo "========================================"
echo " OpenVPN AS 用户证书管理工具"
echo "========================================"
echo -e "${NC}"
detect_container
check_output_dir
set_global_cert_lifetime
echo -e "\n${YELLOW}===== 选择处理模式 =====${NC}"
echo "1) 单个用户处理"
echo "2) 批量处理(从文件读取)"
read -p "请选择 [1-2]: " mode_choice
case $mode_choice in
1)
get_user_input
select_cert_lifetime
create_user_if_not_exists
generate_user_cert
restart_service
show_user_config
echo -e "\n${GREEN}========================================${NC}"
echo -e "${GREEN} 操作完成!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "用户名: $USERNAME"
echo "证书有效期: $CERT_DESC"
echo "证书保存位置: $CERT_OUTPUT_DIR/$USERNAME/"
echo ""
;;
2)
read -p "请输入批量文件路径 (直接回车使用 ./batch_users_example.txt): " batch_file
if [ -z "$batch_file" ]; then
batch_file="./batch_users_example.txt"
fi
batch_process_users "$batch_file"
restart_service
echo "✓ 所有用户证书已生成完成"
echo "证书保存位置: $CERT_OUTPUT_DIR/"
;;
esac
}
main
连接AD域
步骤1:登录Web管理界面
访问:https://192.168.99.119:943/admin

步骤2:导航到认证配置
- 点击左侧菜单的 “Authentication”
- 选择 “LDAP” 选项卡
步骤3:启用LDAP认证
进入AD域服务器192.168.99.211,关闭以下的安全选项:
运行 gpedit.msc 导航到:计算机配置 → Windows设置 → 安全设置 → 本地策略 → 安全选项 找到并修改: 网络安全: LDAP 客户端签名要求 → 设为 无 域控制器: LDAP 服务器签名要求强制 → 设为 无

openvpn-as web页面:
□ Enable LDAP authentication → ☑ Enable LDAP authentication


步骤4:配置LDAP服务器连接

Primary server: 192.168.99.211
□ Connect to LDAP servers with SSL → 选择 "Off"(重要!)
□ Authenticate with username/password for initial bind → ☑ 启用
Bind DN (username): Administrator@linuxjk.cn
Password: 输入密码(Suit@2025)
步骤5:配置用户搜索参数
Base DN for user entries: DC=linuxjk,DC=cn
Username attribute: sAMAccountName
LDAP filter: (&(sAMAccountName=%u)(objectClass=user)(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
#过滤器配置:在AD中禁用的账户无法登录
作用分解:
& - AND操作,所有条件都必须满足
(objectClass=user) - 对象类别为用户
(objectCategory=person) - 对象类别为人
(!(userAccountControl:1.2.840.113556.1.4.803:=2)) - 账户未禁用
userAccountControl 是AD账户控制属性
:1.2.840.113556.1.4.803: 是LDAP匹配规则,表示按位与
=2 表示账户被禁用的标志位
! 表示"非",所以整个条件是"账户未禁用"
步骤6:配置AD域中用户的搜索范围:
# 1. 确认当前配置
echo "当前搜索范围配置:"
./sacli ConfigQuery | grep "users_search_scope"
# 2. 如果配置不正确,修正它
./sacli --key "auth.ldap.0.users_search_scope" --value "subtree" ConfigPut
# 3. 重启服务使配置生效
./sacli Stop
./sacli Start
# 4. 验证配置已应用
./sacli ConfigQuery | grep "users_search_scope"
说明:为什么需要命令行配置搜索范围:
- 基础DN:
DC=linuxjk,DC=cn(整个域) - 用户分布:
test1在OU=城建信息,DC=linuxjk,DC=cnzhangpeng可能在CN=Users,DC=linuxjk,DC=cn或其他OU
不同搜索范围的效果:
| 搜索范围 | 能否找到test1 | 能否找到zhangpeng | 说明 |
|---|---|---|---|
| Base | ❌ 不能 | ❌ 不能 | 只搜索DC=linuxjk,DC=cn本身(这是容器对象,不是用户) |
| One | ❌ 不能 | ❌ 不能 | 只搜索DC=linuxjk,DC=cn的直接子级(可能是Users容器和城建信息OU,但不搜索它们内部) |
| Subtree | ✅ 能 | ✅ 能 | 搜索整个域树,包括所有子OU和嵌套OU |
步骤7:配置认证默认设置
返回或点击 “General Settings” 选项卡:
Default authentication system: LDAP
其他选项保持默认或根据需求配置:
- Require local user accounts with external authentication systems: Off

步骤8:配置密码锁定策略(可选)
在 “Authentication” 部分下的 “Password lockout policy”:
Failed attempts until lockout occurs: 失败次数锁定,可以设置一个值(如5),或留空禁用
Lockout release timeout in seconds: 锁定时间(s),可以设置一个值(如10),或留空禁用
步骤9:应用配置
- 点击页面右上角的 “Save“ 按钮
- 提示重启服务,确认重启

步骤10:验证配置
配置完成后,可以通过以下方式验证:
- 查看当前配置:
- 在命令行中执行:
/usr/local/openvpn-as/scripts/sacli ConfigQuery | grep -E "auth.ldap" - root@e9dcd3f8c7ee:/# /usr/local/openvpn_as/scripts/sacli ConfigQuery | grep -E “auth.ldap”
“auth.ldap.0.bind_dn”: “Administrator@linuxjk.cn”,
“auth.ldap.0.bind_pw”: “Suit@2025”,
“auth.ldap.0.debug”: “true”,
“auth.ldap.0.enable”: “true”,
“auth.ldap.0.fallback_local”: “true”,
“auth.ldap.0.server.0.host”: “192.168.99.211”,
“auth.ldap.0.server.0.port”: “389”,
“auth.ldap.0.timeout”: “15”,
“auth.ldap.0.uname_attr”: “sAMAccountName”,
“auth.ldap.0.use_ssl”: “never”,
“auth.ldap.0.use_start_tls”: “never”,
“auth.ldap.0.user_search_filter”: “(&(sAMAccountName=%u)(objectClass=user)(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))”,
“auth.ldap.0.users_base_dn”: “DC=linuxjk,DC=cn”,
“auth.ldap.0.users_search_scope”: “subtree”,
- 在命令行中执行:
- 测试登录:(上一步如果显示auth.ldap.0.add_req不为空需要进行下面的操作)
- 打开用户登录页面:
https://192.168.99.119:943 - 使用AD域用户(如test1、zhangpeng)尝试登录
- 打开用户登录页面:
Web页面配置与命令行配置的对应关系
| Web页面选项 | 对应命令行配置 | 备注 |
|---|---|---|
| Enable LDAP authentication | auth.ldap.0.enable: true | 启用LDAP |
| Primary server | auth.ldap.0.server.0.host | AD服务器地址 |
| Connect to LDAP servers with SSL | auth.ldap.0.use_ssl: never | 必须选择“Off” |
| Bind DN | auth.ldap.0.bind_dn | 管理员账户 |
| Password | auth.ldap.0.bind_pw | 管理员密码 |
| Base DN for user entries | auth.ldap.0.users_base_dn | 设为“DC=linuxjk,DC=cn” |
| Username attribute | auth.ldap.0.uname_attr | 设为“sAMAccountName” |
| LDAP filter | auth.ldap.0.user_search_filter | 简化过滤器 |
| Default authentication system | auth.module.type: ldap | 在General中设置 |
Web页面可能缺失的配置项
注意:Web页面可能没有直接提供以下配置项,需要通过命令行补充:
auth.ldap.0.add_req– 额外的用户添加验证过滤器auth.ldap.0.use_start_tls– StartTLS设置(默认为never)auth.ldap.0.fallback_local– 本地认证回退
如果需要这些配置,可以在Web页面配置后,通过命令行补充:
cd /usr/local/openvpn_as/scripts
# 确保ssl被禁用
./sacli --key "auth.ldap.0.use_ssl" --value "never" ConfigPut
# 确保StartTLS被禁用
./sacli --key "auth.ldap.0.use_start_tls" --value "never" ConfigPut
# 删除add_req配置
./sacli --key "auth.ldap.0.add_req" ConfigDel
# 重启服务使配置生效
./sacli Stop
./sacli Start
故障排除
如果Web页面配置后无法登录:
- 检查配置语法:
- 确保过滤器语法正确
- 确保基础DN正确
- 测试LDAP连接(在容器内):apt-get update && apt-get install -y ldap-utils
# 测试绑定
ldapwhoami -x -H ldap://192.168.99.211 -D “Administrator@linuxjk.cn” -w “Suit@2025”
ldapwhoami -x -H ldap://192.168.99.190 -D “Administrator@suitbim.com” -w “act1veP@ss”
# 测试搜索
ldapsearch -x -H ldap://192.168.99.211 -D “Administrator@linuxjk.cn” -w “Suit@2025” \
-b “DC=linuxjk,DC=cn” \
“(&(sAMAccountName=test1)(objectClass=user)(objectCategory=person))” \
sAMAccountName
ldapsearch -x -H ldap://192.168.99.190 -D “Administrator@suitbim.com” -w “act1veP@ss” \
-b “DC=suitbim,DC=com” \
“(&(sAMAccountName=zhangpeng)(objectClass=user)(objectCategory=person))” \
sAMAccountName
注意事项
- SSL设置:Web页面上的“Connect to LDAP servers with SSL”必须选择“Off”,否则会因证书问题无法连接
- 过滤器语法:Web页面上的过滤器输入框可能较小,注意括号匹配
- 保存后重启:部分配置更改需要重启OpenVPN AS服务才能生效
配置组映射,将AD中的用户添加到openvpn-as中并设置用户组
一、OpenVPN AS 用户管理机制
1. 用户自动添加机制
- 默认情况:AD域用户首次成功登录后,会自动在OpenVPN AS中创建账户
- 无需手动添加:用户通过LDAP认证成功后自动出现在用户列表
- 本地缓存:登录信息会缓存在OpenVPN AS数据库中
2. 用户可见性
- 只有登录过的用户会出现在OpenVPN AS用户列表中
- 从未登录的用户不会显示
- 用户信息同步:每次登录时会从AD同步最新信息
不使用组映射功能,根据用户属性分配组(待定)
清除用户属性:
./sacli –user test1 UserPropDelAll
将用户分配到某组手动脚本:需要在web页面上先创建测试部门1-4
#!/bin/bash
# manual_assign_group_cn.sh - 手动分配用户到中文部门对应组
USERNAME="$1"
if [ -z "$USERNAME" ]; then
echo "用法: $0 <用户名>"
echo "示例: $0 test1"
exit 1
fi
echo "=== 为用户 $USERNAME 手动分配组 ==="
echo "请选择要分配的部门组:"
echo "1) 测试部门1 (dept1)"
echo "2) 测试部门2 (dept2)"
echo "3) 测试部门3 (dept3)"
echo "4) 测试部门4 (dept4)"
echo "5) Default (默认组)"
read -p "请输入选择 [1-5]: " CHOICE
case "$CHOICE" in
1)
GROUP="测试部门1"
;;
2)
GROUP="测试部门2"
;;
3)
GROUP="测试部门3"
;;
4)
GROUP="测试部门4"
;;
5)
CN_DEPT="默认部门"
GROUP="Default"
;;
*)
echo "无效选择"
exit 1
;;
esac
echo "正在将用户 $USERNAME 分配到 $CN_DEPT ($GROUP) 组..."
# 切换到sacli目录
cd /usr/local/openvpn_as/scripts
# 清理现有组分配
./sacli --user "$USERNAME" --key "conn_group" UserPropDel 2>/dev/null
# 分配新组
./sacli --user "$USERNAME" --key "conn_group" --value "$GROUP" UserPropPut
if [ $? -eq 0 ]; then
echo "✓ 分配成功:用户 $USERNAME 已分配到 $CN_DEPT ($GROUP) 组"
# 验证分配
echo "验证分配..."
./sacli --user "$USERNAME" UserPropGet | grep -o "\"conn_group\": \"$GROUP\"" && echo "✓ 验证成功"
# 重启服务
read -p "是否重启OpenVPN AS服务使配置生效?(y/N): " RESTART
if [ "$RESTART" = "y" ] || [ "$RESTART" = "Y" ]; then
echo "正在重启服务..."
./sacli Stop
sleep 2
./sacli Start
echo "服务已重启"
fi
else
echo "✗ 分配失败"
exit 1
fi
echo "完成!"
配置登录钩子(自动执行)
1. 安装和配置脚本
bash
# 创建脚本目录
mkdir -p /usr/local/openvpn_as/login_hooks
# 保存自动分配脚本
cat > /usr/local/openvpn_as/login_hooks/auto_assign_cn_group.sh << 'EOF'
#!/bin/bash
# 登录钩子脚本 - 自动分配到中文组
USERNAME="$1"
# 记录登录事件
echo "$(date '+%Y-%m-%d %H:%M:%S') - 用户 $USERNAME 登录" >> /var/log/openvpn_cn_login.log
# 执行自动分配
/usr/local/openvpn_as/scripts/auto_assign_cn_group_login.sh "$USERNAME"
# 返回成功
exit 0
EOF
chmod +x /usr/local/openvpn_as/login_hooks/auto_assign_cn_group.sh
2. 配置OpenVPN AS使用登录钩子
bash
cd /usr/local/openvpn_as/scripts
# 停止服务
./sacli Stop
# 配置登录钩子脚本
./sacli --key "vpn.server.login_script" --value "/usr/local/openvpn_as/login_hooks/auto_assign_cn_group.sh" ConfigPut
# 配置登录钩子执行用户(通常是root或openvpn用户)
./sacli --key "vpn.server.login_script_user" --value "root" ConfigPut
# 配置登录钩子执行组
./sacli --key "vpn.server.login_script_group" --value "root" ConfigPut
# 启动服务
./sacli Start
echo "登录钩子配置完成!"
五、批量初始化现有用户
bash
#!/bin/bash
# init_existing_users_cn.sh - 初始化现有用户的中文组分配
echo "=== 初始化现有用户的中文组分配 ==="
cd /usr/local/openvpn_as/scripts
# 获取所有用户列表
USER_LIST="test1 test2 test3 test4 zhangpeng"
echo "找到用户: $USER_LIST"
# 为每个用户执行自动分配
for USER in $USER_LIST; do
echo "处理用户: $USER"
# 使用自动分配脚本
./auto_assign_cn_group_login.sh "$USER" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo " ✓ $USER 处理完成"
else
echo " ✗ $USER 处理失败"
fi
done
echo "初始化完成!"
登录钩子管理命令:
# 检查登录钩子配置
./sacli ConfigQuery | grep -i hook
# 删除当前的钩子配置
./sacli --key "vpn.server.login_script" ConfigDel
配置内网穿透获取公网ip:NPS/NPC
公网云服务器:安装NPS
# 安装nps服务端
wget https://github.com/ehang-io/nps/releases/download/v0.26.10/linux_amd64_server.tar.gz
tar -xzf linux_amd64_server.tar.gz
cd nps
# 安装
sudo ./nps install
# 启动
nohup ./nps > nps.log 2>&1 &
# Web管理界面: http://VPS_IP:8080
# 默认用户名: admin
# 默认密码: 123
# 获取服务器公网IP
curl -s ipinfo.io/ip
# 或者
curl -s ifconfig.me
# 检查NPS进程
ps aux | grep nps
# 检查端口监听
ss -lntup | grep -E ":8080|:8024"
./conf/nps.conf
appname = nps
runmode = dev
http_proxy_ip=0.0.0.0
http_proxy_port=8081
https_proxy_port=8443
https_just_proxy=true
https_default_cert_file=conf/server.pem
https_default_key_file=conf/server.key
bridge_type=tcp
bridge_port=8024
bridge_ip=0.0.0.0
public_vkey=123
log_level=7
web_host=a.o.com
web_username=admin
web_password=123
web_port = 8081
web_ip=0.0.0.0
web_base_url=
web_open_ssl=false
web_cert_file=conf/server.pem
web_key_file=conf/server.key
auth_crypt_key =1234567812345678
allow_user_login=false
allow_user_register=false
allow_user_change_username=false
allow_flow_limit=false
allow_rate_limit=false
allow_tunnel_num_limit=false
allow_local_proxy=false
allow_connection_num_limit=false
allow_multi_ip=false
system_info_display=false
http_cache=false
http_cache_length=100
http_add_origin_header=false
disconnect_timeout=60

按照以下步骤添加客户端,获取此验证密钥
Web界面操作步骤
1. 创建客户端
登录后点击:客户端 -> 新增
填写信息:
- 客户端名称: openvpn-client
- 连接密钥: 自动生成或自定义 (记住这个密钥!)
- 是否压缩: 选择"是"
- 是否加密: 选择"是"
2. 添加TCP隧道 (OpenVPN)
点击:隧道 -> 新增
隧道类型: tcp
服务端端口: 1194
目标(内网)地址: 127.0.0.1:914
备注: OpenVPN-TCP
2.5添加TCP隧道 (备用)
服务端端口: 1195
目标(内网)地址: 127.0.0.1:915
3. 添加UDP隧道 (OpenVPN)
点击:隧道 -> 新增
隧道类型: udp
服务端端口: 1194
目标(内网)地址: 127.0.0.1:916
备注: OpenVPN-UDP
3.5添加UDP隧道(备用)
服务端端口: 1195
目标(内网)地址: 127.0.0.1:917
4. 添加管理界面隧道
点击:隧道 -> 新增
隧道类型: tcp
服务端端口: 943
目标(内网)地址: 127.0.0.1:943
备注: OpenVPN-Admin
4.5 添加客户端wweb页面隧道
服务端端口: 443
目标(内网)地址: 127.0.0.1:443


本地客户端配置
# 下载客户端
wget https://github.com/ehang-io/nps/releases/download/v0.26.10/linux_amd64_client.tar.gz
tar -xzf linux_amd64_client.tar.gz
# 从NPS web界面获取客户端连接命令
# 使用nohup确保SSH断开后进程继续运行
nohup ./npc -server=114.55.148.180:8024 -vkey=zqflfrgacrxc4sbk > npc.log 2>&1 &
# 查看进程
ps aux | grep npc | grep -v grep