6.1 章节概述

OpenVPN的高级配置与优化是构建企业级VPN解决方案的关键。本章将深入探讨多实例部署、负载均衡、高可用性配置、性能优化以及安全加固等高级主题。

flowchart TD
    A[高级配置与优化] --> B[多实例部署]
    A --> C[负载均衡]
    A --> D[高可用性配置]
    A --> E[性能优化]
    A --> F[安全加固]
    A --> G[监控与日志]
    
    B --> B1[多端口配置]
    B --> B2[多协议支持]
    B --> B3[实例管理]
    
    C --> C1[DNS轮询]
    C --> C2[HAProxy集成]
    C --> C3[客户端负载均衡]
    
    D --> D1[主备模式]
    D --> D2[集群模式]
    D --> D3[故障转移]
    
    E --> E1[网络优化]
    E --> E2[加密优化]
    E --> E3[系统调优]
    
    F --> F1[访问控制]
    F --> F2[审计日志]
    F --> F3[入侵检测]
    
    G --> G1[实时监控]
    G --> G2[日志分析]
    G --> G3[告警系统]

6.2 多实例部署

6.2.1 多端口配置

#!/bin/bash
# OpenVPN多实例部署脚本

# 配置变量
OPENVPN_DIR="/etc/openvpn"
LOG_DIR="/var/log/openvpn"
PID_DIR="/var/run/openvpn"
BASE_PORT=1194
INSTANCE_COUNT=3

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 创建目录结构
create_directories() {
    log_info "创建目录结构..."
    
    for i in $(seq 1 $INSTANCE_COUNT); do
        local instance_dir="${OPENVPN_DIR}/server${i}"
        
        mkdir -p "$instance_dir"
        mkdir -p "${instance_dir}/keys"
        mkdir -p "${instance_dir}/ccd"
        mkdir -p "${LOG_DIR}/server${i}"
        
        log_success "创建实例 server${i} 目录"
    done
}

# 生成多实例配置文件
generate_multi_instance_configs() {
    log_info "生成多实例配置文件..."
    
    for i in $(seq 1 $INSTANCE_COUNT); do
        local port=$((BASE_PORT + i - 1))
        local instance_dir="${OPENVPN_DIR}/server${i}"
        local config_file="${instance_dir}/server.conf"
        
        cat > "$config_file" << EOF
# OpenVPN Server Instance ${i} Configuration
# Port: ${port}

# 基本设置
port ${port}
proto udp
dev tun${i}

# 证书和密钥
ca keys/ca.crt
cert keys/server${i}.crt
key keys/server${i}.key
dh keys/dh.pem
tls-auth keys/ta.key 0

# 网络设置
server 10.8.${i}.0 255.255.255.0
ifconfig-pool-persist ipp${i}.txt

# 客户端配置目录
client-config-dir ccd

# 路由设置
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 安全设置
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# 连接设置
keepalive 10 120
max-clients 100

# 用户和权限
user nobody
group nogroup
persist-key
persist-tun

# 日志设置
status ${LOG_DIR}/server${i}/openvpn-status.log
log-append ${LOG_DIR}/server${i}/openvpn.log
verb 3
mute 20

# 管理接口
management 127.0.0.1 $((7505 + i)) /etc/openvpn/server${i}/management.pwd

# 性能优化
fast-io
sndbuf 0
rcvbuf 0

# 客户端特定配置
client-to-client
duplicate-cn

EOF
        
        log_success "生成实例 server${i} 配置文件 (端口: ${port})"
    done
}

# 生成证书和密钥
generate_certificates() {
    log_info "生成证书和密钥..."
    
    # 初始化PKI
    if [ ! -d "/etc/openvpn/easy-rsa" ]; then
        log_info "初始化Easy-RSA..."
        make-cadir /etc/openvpn/easy-rsa
        cd /etc/openvpn/easy-rsa
        
        # 配置vars文件
        cat > vars << EOF
set_var EASYRSA_REQ_COUNTRY    "CN"
set_var EASYRSA_REQ_PROVINCE   "Beijing"
set_var EASYRSA_REQ_CITY       "Beijing"
set_var EASYRSA_REQ_ORG        "OpenVPN-CA"
set_var EASYRSA_REQ_EMAIL      "admin@example.com"
set_var EASYRSA_REQ_OU         "IT Department"
set_var EASYRSA_KEY_SIZE       2048
set_var EASYRSA_ALGO           rsa
set_var EASYRSA_CA_EXPIRE      3650
set_var EASYRSA_CERT_EXPIRE    365
EOF
        
        # 初始化PKI
        ./easyrsa init-pki
        ./easyrsa --batch build-ca nopass
        ./easyrsa gen-dh
        openvpn --genkey --secret pki/ta.key
        
        log_success "PKI初始化完成"
    fi
    
    cd /etc/openvpn/easy-rsa
    
    # 为每个实例生成服务器证书
    for i in $(seq 1 $INSTANCE_COUNT); do
        local server_name="server${i}"
        
        if [ ! -f "pki/issued/${server_name}.crt" ]; then
            ./easyrsa --batch build-server-full "$server_name" nopass
            log_success "生成服务器证书: $server_name"
        fi
        
        # 复制证书到实例目录
        local instance_dir="${OPENVPN_DIR}/server${i}/keys"
        cp pki/ca.crt "$instance_dir/"
        cp "pki/issued/${server_name}.crt" "$instance_dir/"
        cp "pki/private/${server_name}.key" "$instance_dir/"
        cp pki/dh.pem "$instance_dir/"
        cp pki/ta.key "$instance_dir/"
        
        # 设置权限
        chmod 600 "${instance_dir}/${server_name}.key"
        chmod 600 "${instance_dir}/ta.key"
    done
}

# 创建systemd服务文件
create_systemd_services() {
    log_info "创建systemd服务文件..."
    
    for i in $(seq 1 $INSTANCE_COUNT); do
        local service_file="/etc/systemd/system/openvpn-server@server${i}.service"
        
        cat > "$service_file" << EOF
[Unit]
Description=OpenVPN service for server${i}
After=syslog.target network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO

[Service]
Type=notify
PrivateTmp=true
WorkingDirectory=/etc/openvpn/server${i}
ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-server${i}.log --status-version 2 --suppress-timestamps --config server.conf
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
LimitNPROC=100
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF
        
        log_success "创建服务文件: openvpn-server@server${i}.service"
    done
    
    # 重新加载systemd
    systemctl daemon-reload
}

# 配置防火墙规则
configure_firewall() {
    log_info "配置防火墙规则..."
    
    # 启用IP转发
    echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
    sysctl -p
    
    # 获取外网接口
    local external_interface=$(ip route | grep default | awk '{print $5}' | head -1)
    
    # 配置iptables规则
    for i in $(seq 1 $INSTANCE_COUNT); do
        local port=$((BASE_PORT + i - 1))
        local subnet="10.8.${i}.0/24"
        
        # 允许OpenVPN端口
        iptables -A INPUT -p udp --dport "$port" -j ACCEPT
        
        # NAT规则
        iptables -t nat -A POSTROUTING -s "$subnet" -o "$external_interface" -j MASQUERADE
        
        # 转发规则
        iptables -A FORWARD -i "tun${i}" -j ACCEPT
        iptables -A FORWARD -i "tun${i}" -o "$external_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT
        iptables -A FORWARD -i "$external_interface" -o "tun${i}" -m state --state RELATED,ESTABLISHED -j ACCEPT
        
        log_success "配置实例 server${i} 防火墙规则 (端口: ${port}, 子网: ${subnet})"
    done
    
    # 保存iptables规则
    if command -v iptables-save > /dev/null; then
        iptables-save > /etc/iptables/rules.v4
        log_success "保存iptables规则"
    fi
}

# 启动所有实例
start_all_instances() {
    log_info "启动所有OpenVPN实例..."
    
    for i in $(seq 1 $INSTANCE_COUNT); do
        systemctl enable "openvpn-server@server${i}.service"
        systemctl start "openvpn-server@server${i}.service"
        
        if systemctl is-active --quiet "openvpn-server@server${i}.service"; then
            log_success "实例 server${i} 启动成功"
        else
            log_error "实例 server${i} 启动失败"
        fi
    done
}

# 显示状态信息
show_status() {
    log_info "OpenVPN多实例状态:"
    
    for i in $(seq 1 $INSTANCE_COUNT); do
        local port=$((BASE_PORT + i - 1))
        local status=$(systemctl is-active "openvpn-server@server${i}.service")
        
        if [ "$status" = "active" ]; then
            log_success "实例 server${i}: 运行中 (端口: ${port})"
        else
            log_error "实例 server${i}: 未运行 (端口: ${port})"
        fi
    done
    
    # 显示网络接口
    echo
    log_info "VPN网络接口:"
    ip addr show | grep -E "tun[0-9]+:"
    
    # 显示监听端口
    echo
    log_info "监听端口:"
    netstat -ulnp | grep openvpn
}

# 生成客户端配置
generate_client_config() {
    local client_name="$1"
    local instance_num="$2"
    
    if [ -z "$client_name" ] || [ -z "$instance_num" ]; then
        log_error "用法: generate_client_config <客户端名称> <实例编号>"
        return 1
    fi
    
    if [ "$instance_num" -lt 1 ] || [ "$instance_num" -gt "$INSTANCE_COUNT" ]; then
        log_error "实例编号必须在 1-${INSTANCE_COUNT} 之间"
        return 1
    fi
    
    log_info "为实例 server${instance_num} 生成客户端配置: $client_name"
    
    # 生成客户端证书
    cd /etc/openvpn/easy-rsa
    
    if [ ! -f "pki/issued/${client_name}.crt" ]; then
        ./easyrsa --batch build-client-full "$client_name" nopass
        log_success "生成客户端证书: $client_name"
    fi
    
    # 获取服务器信息
    local server_ip=$(curl -s ifconfig.me)
    local server_port=$((BASE_PORT + instance_num - 1))
    
    # 生成客户端配置文件
    local client_config="/etc/openvpn/server${instance_num}/${client_name}.ovpn"
    
    cat > "$client_config" << EOF
client
dev tun
proto udp
remote $server_ip $server_port
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3

<ca>
$(cat pki/ca.crt)
</ca>

<cert>
$(cat pki/issued/${client_name}.crt)
</cert>

<key>
$(cat pki/private/${client_name}.key)
</key>

<tls-auth>
$(cat pki/ta.key)
</tls-auth>
key-direction 1
EOF
    
    log_success "客户端配置文件已生成: $client_config"
    log_info "服务器: $server_ip:$server_port"
}

# 主函数
main() {
    case "$1" in
        "install")
            log_info "开始OpenVPN多实例部署..."
            create_directories
            generate_multi_instance_configs
            generate_certificates
            create_systemd_services
            configure_firewall
            start_all_instances
            show_status
            log_success "OpenVPN多实例部署完成!"
            ;;
        "start")
            start_all_instances
            ;;
        "status")
            show_status
            ;;
        "client")
            generate_client_config "$2" "$3"
            ;;
        "stop")
            log_info "停止所有OpenVPN实例..."
            for i in $(seq 1 $INSTANCE_COUNT); do
                systemctl stop "openvpn-server@server${i}.service"
                log_success "停止实例 server${i}"
            done
            ;;
        "restart")
            log_info "重启所有OpenVPN实例..."
            for i in $(seq 1 $INSTANCE_COUNT); do
                systemctl restart "openvpn-server@server${i}.service"
                log_success "重启实例 server${i}"
            done
            ;;
        *)
            echo "OpenVPN多实例管理工具"
            echo "用法: $0 {install|start|stop|restart|status|client}"
            echo ""
            echo "操作说明:"
            echo "  install                    - 安装和配置多实例"
            echo "  start                      - 启动所有实例"
            echo "  stop                       - 停止所有实例"
            echo "  restart                    - 重启所有实例"
            echo "  status                     - 显示实例状态"
            echo "  client <名称> <实例编号>   - 生成客户端配置"
            echo ""
            echo "示例:"
            echo "  $0 install"
            echo "  $0 client user1 1"
            echo "  $0 status"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 执行主函数
main "$@"

6.4 高可用性配置

6.4.1 Keepalived高可用配置

#!/bin/bash
# OpenVPN Keepalived高可用配置脚本

# 配置变量
VRRP_INTERFACE="eth0"
VIRTUAL_ROUTER_ID=51
VIRTUAL_IP="192.168.1.100"
PRIORITY_MASTER=110
PRIORITY_BACKUP=100
AUTH_PASS="openvpn123"
OPENVPN_SERVICE="openvpn@server"
KEEPALIVED_CONFIG="/etc/keepalived/keepalived.conf"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 安装Keepalived
install_keepalived() {
    log_info "安装Keepalived..."
    
    if command -v apt-get > /dev/null; then
        apt-get update
        apt-get install -y keepalived
    elif command -v yum > /dev/null; then
        yum install -y keepalived
    else
        log_error "不支持的包管理器"
        return 1
    fi
    
    log_success "Keepalived安装完成"
}

# 配置主服务器
configure_master() {
    log_info "配置Keepalived主服务器..."
    
    # 创建配置目录
    mkdir -p /etc/keepalived
    
    # 生成主服务器配置
    cat > "$KEEPALIVED_CONFIG" << EOF
! Configuration File for keepalived

global_defs {
    notification_email {
        admin@example.com
    }
    notification_email_from keepalived@$(hostname)
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id OPENVPN_MASTER
    vrrp_skip_check_adv_addr
    vrrp_strict
    vrrp_garp_interval 0
    vrrp_gna_interval 0
}

# OpenVPN服务检查脚本
vrrp_script chk_openvpn {
    script "/etc/keepalived/check_openvpn.sh"
    interval 2
    weight -2
    fall 3
    rise 2
}

# VRRP实例配置
vrrp_instance VI_1 {
    state MASTER
    interface $VRRP_INTERFACE
    virtual_router_id $VIRTUAL_ROUTER_ID
    priority $PRIORITY_MASTER
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass $AUTH_PASS
    }
    virtual_ipaddress {
        $VIRTUAL_IP
    }
    track_script {
        chk_openvpn
    }
    notify_master "/etc/keepalived/notify_master.sh"
    notify_backup "/etc/keepalived/notify_backup.sh"
    notify_fault "/etc/keepalived/notify_fault.sh"
}
EOF
    
    log_success "主服务器配置完成"
}

# 配置备份服务器
configure_backup() {
    log_info "配置Keepalived备份服务器..."
    
    # 创建配置目录
    mkdir -p /etc/keepalived
    
    # 生成备份服务器配置
    cat > "$KEEPALIVED_CONFIG" << EOF
! Configuration File for keepalived

global_defs {
    notification_email {
        admin@example.com
    }
    notification_email_from keepalived@$(hostname)
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id OPENVPN_BACKUP
    vrrp_skip_check_adv_addr
    vrrp_strict
    vrrp_garp_interval 0
    vrrp_gna_interval 0
}

# OpenVPN服务检查脚本
vrrp_script chk_openvpn {
    script "/etc/keepalived/check_openvpn.sh"
    interval 2
    weight -2
    fall 3
    rise 2
}

# VRRP实例配置
vrrp_instance VI_1 {
    state BACKUP
    interface $VRRP_INTERFACE
    virtual_router_id $VIRTUAL_ROUTER_ID
    priority $PRIORITY_BACKUP
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass $AUTH_PASS
    }
    virtual_ipaddress {
        $VIRTUAL_IP
    }
    track_script {
        chk_openvpn
    }
    notify_master "/etc/keepalived/notify_master.sh"
    notify_backup "/etc/keepalived/notify_backup.sh"
    notify_fault "/etc/keepalived/notify_fault.sh"
}
EOF
    
    log_success "备份服务器配置完成"
}

# 创建检查脚本
create_check_scripts() {
    log_info "创建Keepalived检查脚本..."
    
    # OpenVPN服务检查脚本
    cat > /etc/keepalived/check_openvpn.sh << 'EOF'
#!/bin/bash
# OpenVPN服务健康检查脚本

OPENVPN_SERVICE="openvpn@server"
OPENVPN_PORT=1194
OPENVPN_LOG="/var/log/openvpn/server.log"

# 检查OpenVPN服务状态
if ! systemctl is-active --quiet "$OPENVPN_SERVICE"; then
    echo "OpenVPN服务未运行"
    exit 1
fi

# 检查OpenVPN端口
if ! netstat -ln | grep -q ":$OPENVPN_PORT "; then
    echo "OpenVPN端口未监听"
    exit 1
fi

# 检查OpenVPN日志错误
if [ -f "$OPENVPN_LOG" ]; then
    if tail -n 10 "$OPENVPN_LOG" | grep -q "ERROR\|FATAL"; then
        echo "OpenVPN日志中发现错误"
        exit 1
    fi
fi

# 检查TUN接口
if ! ip link show tun0 > /dev/null 2>&1; then
    echo "TUN接口不存在"
    exit 1
fi

echo "OpenVPN服务健康"
exit 0
EOF
    
    # 主服务器通知脚本
    cat > /etc/keepalived/notify_master.sh << 'EOF'
#!/bin/bash
# 主服务器切换通知脚本

echo "$(date): 切换为主服务器" >> /var/log/keepalived.log

# 确保OpenVPN服务运行
systemctl start openvpn@server

# 配置路由和防火墙规则
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# 发送邮件通知(可选)
# echo "OpenVPN主服务器已激活" | mail -s "OpenVPN HA切换" admin@example.com
EOF
    
    # 备份服务器通知脚本
    cat > /etc/keepalived/notify_backup.sh << 'EOF'
#!/bin/bash
# 备份服务器切换通知脚本

echo "$(date): 切换为备份服务器" >> /var/log/keepalived.log

# 停止OpenVPN服务(可选)
# systemctl stop openvpn@server

# 发送邮件通知(可选)
# echo "OpenVPN备份服务器已激活" | mail -s "OpenVPN HA切换" admin@example.com
EOF
    
    # 故障通知脚本
    cat > /etc/keepalived/notify_fault.sh << 'EOF'
#!/bin/bash
# 故障通知脚本

echo "$(date): 服务器故障" >> /var/log/keepalived.log

# 尝试重启OpenVPN服务
systemctl restart openvpn@server

# 发送邮件通知(可选)
# echo "OpenVPN服务器故障" | mail -s "OpenVPN HA故障" admin@example.com
EOF
    
    # 设置脚本权限
    chmod +x /etc/keepalived/check_openvpn.sh
    chmod +x /etc/keepalived/notify_master.sh
    chmod +x /etc/keepalived/notify_backup.sh
    chmod +x /etc/keepalived/notify_fault.sh
    
    log_success "检查脚本创建完成"
}

# 配置防火墙
configure_keepalived_firewall() {
    log_info "配置Keepalived防火墙规则..."
    
    # 允许VRRP协议
    iptables -A INPUT -p vrrp -j ACCEPT
    iptables -A OUTPUT -p vrrp -j ACCEPT
    
    # 允许组播地址
    iptables -A INPUT -d 224.0.0.18/32 -j ACCEPT
    iptables -A OUTPUT -d 224.0.0.18/32 -j ACCEPT
    
    # 保存规则
    if command -v iptables-save > /dev/null; then
        iptables-save > /etc/iptables/rules.v4
    fi
    
    log_success "Keepalived防火墙规则配置完成"
}

# 启动Keepalived服务
start_keepalived() {
    log_info "启动Keepalived服务..."
    
    # 检查配置文件
    if keepalived -t -f "$KEEPALIVED_CONFIG"; then
        log_success "Keepalived配置文件检查通过"
    else
        log_error "Keepalived配置文件错误"
        return 1
    fi
    
    # 启动服务
    systemctl enable keepalived
    systemctl restart keepalived
    
    if systemctl is-active --quiet keepalived; then
        log_success "Keepalived服务启动成功"
    else
        log_error "Keepalived服务启动失败"
        return 1
    fi
}

# 监控高可用状态
monitor_ha() {
    log_info "监控高可用状态..."
    
    while true; do
        clear
        echo "OpenVPN高可用监控 - $(date)"
        echo "=" * 60
        
        # 检查Keepalived服务状态
        if systemctl is-active --quiet keepalived; then
            echo "✓ Keepalived服务: 运行中"
        else
            echo "✗ Keepalived服务: 已停止"
        fi
        
        # 检查OpenVPN服务状态
        if systemctl is-active --quiet "$OPENVPN_SERVICE"; then
            echo "✓ OpenVPN服务: 运行中"
        else
            echo "✗ OpenVPN服务: 已停止"
        fi
        
        echo ""
        echo "虚拟IP状态:"
        
        # 检查虚拟IP
        if ip addr show | grep -q "$VIRTUAL_IP"; then
            echo "✓ 虚拟IP $VIRTUAL_IP: 已绑定(主服务器)"
        else
            echo "✗ 虚拟IP $VIRTUAL_IP: 未绑定(备份服务器)"
        fi
        
        echo ""
        echo "VRRP状态:"
        
        # 显示VRRP状态
        if [ -f /var/log/keepalived.log ]; then
            echo "最近状态变化:"
            tail -n 5 /var/log/keepalived.log | while read line; do
                echo "  $line"
            done
        fi
        
        echo ""
        echo "网络连接:"
        
        # 显示连接数
        local connections=$(netstat -an | grep ":1194 " | wc -l)
        echo "  当前连接数: $connections"
        
        echo ""
        echo "按 Ctrl+C 退出监控"
        sleep 10
    done
}

# 测试高可用
test_ha() {
    log_info "测试高可用配置..."
    
    echo "检查虚拟IP连通性..."
    
    if ping -c 3 "$VIRTUAL_IP" > /dev/null 2>&1; then
        echo "✓ 虚拟IP $VIRTUAL_IP 可达"
    else
        echo "✗ 虚拟IP $VIRTUAL_IP 不可达"
    fi
    
    echo ""
    echo "检查OpenVPN端口..."
    
    if timeout 3 bash -c "</dev/tcp/$VIRTUAL_IP/1194" 2>/dev/null; then
        echo "✓ OpenVPN端口 1194 可达"
    else
        echo "✗ OpenVPN端口 1194 不可达"
    fi
    
    echo ""
    echo "检查服务状态..."
    
    if systemctl is-active --quiet keepalived; then
        echo "✓ Keepalived服务正常"
    else
        echo "✗ Keepalived服务异常"
    fi
    
    if systemctl is-active --quiet "$OPENVPN_SERVICE"; then
        echo "✓ OpenVPN服务正常"
    else
        echo "✗ OpenVPN服务异常"
    fi
}

# 主函数
main() {
    case "$1" in
        "install-master")
            log_info "安装Keepalived主服务器..."
            install_keepalived
            configure_master
            create_check_scripts
            configure_keepalived_firewall
            start_keepalived
            test_ha
            log_success "Keepalived主服务器安装完成!"
            echo ""
            echo "配置信息:"
            echo "  虚拟IP: $VIRTUAL_IP"
            echo "  优先级: $PRIORITY_MASTER (主服务器)"
            echo "  接口: $VRRP_INTERFACE"
            ;;
        "install-backup")
            log_info "安装Keepalived备份服务器..."
            install_keepalived
            configure_backup
            create_check_scripts
            configure_keepalived_firewall
            start_keepalived
            test_ha
            log_success "Keepalived备份服务器安装完成!"
            echo ""
            echo "配置信息:"
            echo "  虚拟IP: $VIRTUAL_IP"
            echo "  优先级: $PRIORITY_BACKUP (备份服务器)"
            echo "  接口: $VRRP_INTERFACE"
            ;;
        "test")
            test_ha
            ;;
        "monitor")
            monitor_ha
            ;;
        "restart")
            log_info "重启Keepalived服务..."
            systemctl restart keepalived
            log_success "Keepalived服务重启完成"
            ;;
        "status")
            log_info "Keepalived高可用状态:"
            
            if systemctl is-active --quiet keepalived; then
                echo "✓ Keepalived服务: 运行中"
            else
                echo "✗ Keepalived服务: 已停止"
            fi
            
            if ip addr show | grep -q "$VIRTUAL_IP"; then
                echo "✓ 当前角色: 主服务器"
            else
                echo "✓ 当前角色: 备份服务器"
            fi
            
            echo ""
            echo "配置信息:"
            echo "  虚拟IP: $VIRTUAL_IP"
            echo "  接口: $VRRP_INTERFACE"
            echo "  路由器ID: $VIRTUAL_ROUTER_ID"
            ;;
        *)
            echo "OpenVPN Keepalived高可用管理工具"
            echo "用法: $0 {install-master|install-backup|test|monitor|restart|status}"
            echo ""
            echo "操作说明:"
            echo "  install-master  - 安装配置主服务器"
            echo "  install-backup  - 安装配置备份服务器"
            echo "  test           - 测试高可用配置"
            echo "  monitor        - 监控高可用状态"
            echo "  restart        - 重启Keepalived服务"
            echo "  status         - 显示状态信息"
            echo ""
            echo "示例:"
            echo "  $0 install-master"
            echo "  $0 install-backup"
            echo "  $0 monitor"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 执行主函数
main "$@"

6.5 性能优化

6.5.1 系统性能优化脚本

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OpenVPN性能优化管理器
提供系统级和OpenVPN级的性能优化功能
"""

import os
import sys
import subprocess
import json
import time
from pathlib import Path
from typing import Dict, List, Tuple, Optional

class OpenVPNPerformanceOptimizer:
    """OpenVPN性能优化器"""
    
    def __init__(self):
        self.config_dir = "/etc/openvpn"
        self.log_dir = "/var/log/openvpn"
        self.optimization_log = "/var/log/openvpn-optimization.log"
        
    def log_message(self, message: str, level: str = "INFO"):
        """记录日志消息"""
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] [{level}] {message}"
        print(log_entry)
        
        try:
            with open(self.optimization_log, "a") as f:
                f.write(log_entry + "\n")
        except Exception as e:
            print(f"写入日志失败: {e}")
    
    def run_command(self, command: str) -> Tuple[bool, str]:
        """执行系统命令"""
        try:
            result = subprocess.run(
                command, shell=True, capture_output=True, 
                text=True, timeout=30
            )
            return result.returncode == 0, result.stdout + result.stderr
        except subprocess.TimeoutExpired:
            return False, "命令执行超时"
        except Exception as e:
            return False, str(e)
    
    def optimize_kernel_parameters(self) -> bool:
        """优化内核参数"""
        self.log_message("开始优化内核参数...")
        
        # 内核参数优化配置
        kernel_params = {
            # 网络性能优化
            "net.core.rmem_default": "262144",
            "net.core.rmem_max": "16777216",
            "net.core.wmem_default": "262144",
            "net.core.wmem_max": "16777216",
            "net.core.netdev_max_backlog": "5000",
            "net.core.netdev_budget": "600",
            
            # TCP优化
            "net.ipv4.tcp_rmem": "4096 65536 16777216",
            "net.ipv4.tcp_wmem": "4096 65536 16777216",
            "net.ipv4.tcp_congestion_control": "bbr",
            "net.ipv4.tcp_window_scaling": "1",
            "net.ipv4.tcp_timestamps": "1",
            "net.ipv4.tcp_sack": "1",
            "net.ipv4.tcp_fack": "1",
            "net.ipv4.tcp_low_latency": "1",
            
            # UDP优化
            "net.ipv4.udp_rmem_min": "8192",
            "net.ipv4.udp_wmem_min": "8192",
            
            # 连接跟踪优化
            "net.netfilter.nf_conntrack_max": "1048576",
            "net.netfilter.nf_conntrack_tcp_timeout_established": "7200",
            "net.netfilter.nf_conntrack_udp_timeout": "60",
            
            # 内存管理
            "vm.swappiness": "10",
            "vm.dirty_ratio": "15",
            "vm.dirty_background_ratio": "5",
            
            # 文件系统优化
            "fs.file-max": "2097152",
            "fs.nr_open": "2097152",
        }
        
        # 应用内核参数
        sysctl_conf = "/etc/sysctl.d/99-openvpn-optimization.conf"
        
        try:
            with open(sysctl_conf, "w") as f:
                f.write("# OpenVPN性能优化参数\n")
                f.write(f"# 生成时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n")
                
                for param, value in kernel_params.items():
                    f.write(f"{param} = {value}\n")
                    
                    # 立即应用参数
                    success, output = self.run_command(f"sysctl -w {param}={value}")
                    if not success:
                        self.log_message(f"设置参数 {param} 失败: {output}", "WARNING")
            
            # 重新加载sysctl配置
            success, output = self.run_command("sysctl -p /etc/sysctl.d/99-openvpn-optimization.conf")
            if success:
                self.log_message("内核参数优化完成")
                return True
            else:
                self.log_message(f"重新加载sysctl配置失败: {output}", "ERROR")
                return False
                
        except Exception as e:
            self.log_message(f"优化内核参数失败: {e}", "ERROR")
            return False
    
    def optimize_openvpn_config(self, config_file: str) -> bool:
        """优化OpenVPN配置文件"""
        self.log_message(f"开始优化OpenVPN配置: {config_file}")
        
        if not os.path.exists(config_file):
            self.log_message(f"配置文件不存在: {config_file}", "ERROR")
            return False
        
        # 性能优化参数
        optimization_params = [
            "# 性能优化参数",
            "fast-io",
            "sndbuf 393216",
            "rcvbuf 393216",
            "push \"sndbuf 393216\"",
            "push \"rcvbuf 393216\"",
            "tcp-nodelay",
            "comp-lzo adaptive",
            "tun-mtu 1500",
            "mssfix 1460",
            "fragment 1300",
            "txqueuelen 1000",
            "",
            "# 多线程支持",
            "management-client-user nobody",
            "management-client-group nogroup",
            "",
            "# 连接优化",
            "keepalive 10 60",
            "ping-timer-rem",
            "persist-tun",
            "persist-key",
            "",
            "# 日志优化",
            "verb 3",
            "mute 20",
            "status /var/log/openvpn/status.log 10",
            ""
        ]
        
        try:
            # 备份原配置文件
            backup_file = f"{config_file}.backup.{int(time.time())}"
            success, output = self.run_command(f"cp {config_file} {backup_file}")
            if not success:
                self.log_message(f"备份配置文件失败: {output}", "ERROR")
                return False
            
            # 读取现有配置
            with open(config_file, "r") as f:
                existing_config = f.read()
            
            # 检查是否已经包含优化参数
            if "# 性能优化参数" in existing_config:
                self.log_message("配置文件已包含性能优化参数")
                return True
            
            # 添加优化参数
            with open(config_file, "a") as f:
                f.write("\n")
                for param in optimization_params:
                    f.write(param + "\n")
            
            self.log_message(f"OpenVPN配置优化完成: {config_file}")
            return True
            
        except Exception as e:
            self.log_message(f"优化OpenVPN配置失败: {e}", "ERROR")
            return False
    
    def optimize_system_limits(self) -> bool:
        """优化系统限制"""
        self.log_message("开始优化系统限制...")
        
        limits_conf = "/etc/security/limits.d/99-openvpn.conf"
        
        limits_config = [
            "# OpenVPN性能优化 - 系统限制",
            "# 文件描述符限制",
            "* soft nofile 65536",
            "* hard nofile 65536",
            "root soft nofile 65536",
            "root hard nofile 65536",
            "",
            "# 进程限制",
            "* soft nproc 32768",
            "* hard nproc 32768",
            "root soft nproc 32768",
            "root hard nproc 32768",
            "",
            "# 内存锁定限制",
            "* soft memlock unlimited",
            "* hard memlock unlimited",
            "root soft memlock unlimited",
            "root hard memlock unlimited",
            ""
        ]
        
        try:
            with open(limits_conf, "w") as f:
                for line in limits_config:
                    f.write(line + "\n")
            
            # 更新systemd限制
            systemd_conf = "/etc/systemd/system.conf.d/openvpn-limits.conf"
            os.makedirs("/etc/systemd/system.conf.d", exist_ok=True)
            
            systemd_config = [
                "[Manager]",
                "DefaultLimitNOFILE=65536",
                "DefaultLimitNPROC=32768",
                "DefaultLimitMEMLOCK=infinity",
                ""
            ]
            
            with open(systemd_conf, "w") as f:
                for line in systemd_config:
                    f.write(line + "\n")
            
            # 重新加载systemd配置
            success, output = self.run_command("systemctl daemon-reload")
            if success:
                self.log_message("系统限制优化完成")
                return True
            else:
                self.log_message(f"重新加载systemd配置失败: {output}", "ERROR")
                return False
                
        except Exception as e:
            self.log_message(f"优化系统限制失败: {e}", "ERROR")
            return False
    
    def optimize_network_interface(self, interface: str = "tun0") -> bool:
        """优化网络接口"""
        self.log_message(f"开始优化网络接口: {interface}")
        
        # 网络接口优化命令
        optimization_commands = [
            f"ip link set {interface} txqueuelen 1000",
            f"ethtool -K {interface} gso off 2>/dev/null || true",
            f"ethtool -K {interface} tso off 2>/dev/null || true",
            f"ethtool -K {interface} ufo off 2>/dev/null || true",
            f"ethtool -K {interface} gro off 2>/dev/null || true",
        ]
        
        success_count = 0
        for cmd in optimization_commands:
            success, output = self.run_command(cmd)
            if success:
                success_count += 1
            else:
                self.log_message(f"执行命令失败: {cmd} - {output}", "WARNING")
        
        if success_count > 0:
            self.log_message(f"网络接口优化完成: {success_count}/{len(optimization_commands)} 成功")
            return True
        else:
            self.log_message("网络接口优化失败", "ERROR")
            return False
    
    def create_optimization_script(self) -> bool:
        """创建优化脚本"""
        self.log_message("创建系统优化脚本...")
        
        script_path = "/usr/local/bin/openvpn-optimize.sh"
        
        script_content = '''#!/bin/bash
# OpenVPN系统优化脚本
# 自动执行系统级优化

set -e

log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >&2
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

log_info "开始OpenVPN系统优化..."

# 优化CPU调度
log_info "优化CPU调度..."
echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null || true

# 优化中断处理
log_info "优化中断处理..."
echo 2 > /proc/sys/net/core/netdev_budget_usecs 2>/dev/null || true
echo 600 > /proc/sys/net/core/netdev_budget 2>/dev/null || true

# 优化网络队列
log_info "优化网络队列..."
for iface in $(ls /sys/class/net/ | grep -E '^(eth|ens|enp)'); do
    if [ -d "/sys/class/net/$iface/queues" ]; then
        for queue in /sys/class/net/$iface/queues/rx-*/rps_cpus; do
            if [ -f "$queue" ]; then
                echo f > "$queue" 2>/dev/null || true
            fi
        done
        
        for queue in /sys/class/net/$iface/queues/tx-*/xps_cpus; do
            if [ -f "$queue" ]; then
                echo f > "$queue" 2>/dev/null || true
            fi
        done
    fi
done

# 优化内存管理
log_info "优化内存管理..."
echo 1 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
echo 1 > /proc/sys/vm/drop_caches

# 优化文件系统
log_info "优化文件系统..."
sync
echo 3 > /proc/sys/vm/drop_caches

log_info "OpenVPN系统优化完成"
'''
        
        try:
            with open(script_path, "w") as f:
                f.write(script_content)
            
            # 设置执行权限
            os.chmod(script_path, 0o755)
            
            # 创建systemd服务
            service_content = f'''[Unit]
Description=OpenVPN Performance Optimization
After=network.target

[Service]
Type=oneshot
ExecStart={script_path}
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
'''
            
            service_path = "/etc/systemd/system/openvpn-optimize.service"
            with open(service_path, "w") as f:
                f.write(service_content)
            
            # 启用服务
            success, output = self.run_command("systemctl daemon-reload")
            if success:
                success, output = self.run_command("systemctl enable openvpn-optimize.service")
                if success:
                    self.log_message("优化脚本和服务创建完成")
                    return True
            
            self.log_message(f"创建systemd服务失败: {output}", "ERROR")
            return False
            
        except Exception as e:
            self.log_message(f"创建优化脚本失败: {e}", "ERROR")
            return False
    
    def generate_performance_report(self) -> Dict:
        """生成性能报告"""
        self.log_message("生成性能报告...")
        
        report = {
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            "system_info": {},
            "network_info": {},
            "openvpn_info": {},
            "optimization_status": {}
        }
        
        try:
            # 系统信息
            success, output = self.run_command("uname -a")
            if success:
                report["system_info"]["kernel"] = output.strip()
            
            success, output = self.run_command("nproc")
            if success:
                report["system_info"]["cpu_cores"] = int(output.strip())
            
            success, output = self.run_command("free -m | grep Mem | awk '{print $2}'")
            if success:
                report["system_info"]["memory_mb"] = int(output.strip())
            
            # 网络信息
            success, output = self.run_command("cat /proc/sys/net/core/rmem_max")
            if success:
                report["network_info"]["rmem_max"] = int(output.strip())
            
            success, output = self.run_command("cat /proc/sys/net/core/wmem_max")
            if success:
                report["network_info"]["wmem_max"] = int(output.strip())
            
            # OpenVPN信息
            success, output = self.run_command("systemctl is-active openvpn@server")
            if success:
                report["openvpn_info"]["service_status"] = output.strip()
            
            success, output = self.run_command("netstat -an | grep :1194 | wc -l")
            if success:
                report["openvpn_info"]["connections"] = int(output.strip())
            
            # 优化状态检查
            report["optimization_status"]["sysctl_config"] = os.path.exists("/etc/sysctl.d/99-openvpn-optimization.conf")
            report["optimization_status"]["limits_config"] = os.path.exists("/etc/security/limits.d/99-openvpn.conf")
            report["optimization_status"]["optimization_script"] = os.path.exists("/usr/local/bin/openvpn-optimize.sh")
            
            self.log_message("性能报告生成完成")
            return report
            
        except Exception as e:
            self.log_message(f"生成性能报告失败: {e}", "ERROR")
            return report
    
    def run_full_optimization(self, config_file: str = None) -> bool:
        """执行完整优化"""
        self.log_message("开始执行完整性能优化...")
        
        success_count = 0
        total_steps = 5
        
        # 1. 优化内核参数
        if self.optimize_kernel_parameters():
            success_count += 1
        
        # 2. 优化系统限制
        if self.optimize_system_limits():
            success_count += 1
        
        # 3. 优化OpenVPN配置
        if config_file and self.optimize_openvpn_config(config_file):
            success_count += 1
        else:
            # 尝试找到默认配置文件
            default_configs = [
                "/etc/openvpn/server.conf",
                "/etc/openvpn/server/server.conf"
            ]
            
            for conf in default_configs:
                if os.path.exists(conf):
                    if self.optimize_openvpn_config(conf):
                        success_count += 1
                    break
        
        # 4. 优化网络接口
        if self.optimize_network_interface():
            success_count += 1
        
        # 5. 创建优化脚本
        if self.create_optimization_script():
            success_count += 1
        
        # 生成报告
        report = self.generate_performance_report()
        report_file = f"/var/log/openvpn-performance-report-{int(time.time())}.json"
        
        try:
            with open(report_file, "w") as f:
                json.dump(report, f, indent=2, ensure_ascii=False)
            self.log_message(f"性能报告已保存: {report_file}")
        except Exception as e:
            self.log_message(f"保存性能报告失败: {e}", "ERROR")
        
        success_rate = (success_count / total_steps) * 100
        self.log_message(f"完整优化完成: {success_count}/{total_steps} 步骤成功 ({success_rate:.1f}%)")
        
        return success_count >= (total_steps * 0.8)  # 80%成功率认为优化成功

def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="OpenVPN性能优化工具")
    parser.add_argument("--config", "-c", help="OpenVPN配置文件路径")
    parser.add_argument("--kernel", action="store_true", help="仅优化内核参数")
    parser.add_argument("--limits", action="store_true", help="仅优化系统限制")
    parser.add_argument("--network", action="store_true", help="仅优化网络接口")
    parser.add_argument("--report", action="store_true", help="仅生成性能报告")
    parser.add_argument("--full", action="store_true", help="执行完整优化")
    
    args = parser.parse_args()
    
    # 检查root权限
    if os.geteuid() != 0:
        print("错误: 请使用root权限运行此脚本")
        sys.exit(1)
    
    optimizer = OpenVPNPerformanceOptimizer()
    
    if args.kernel:
        success = optimizer.optimize_kernel_parameters()
    elif args.limits:
        success = optimizer.optimize_system_limits()
    elif args.network:
        success = optimizer.optimize_network_interface()
    elif args.report:
        report = optimizer.generate_performance_report()
        print(json.dumps(report, indent=2, ensure_ascii=False))
        success = True
    elif args.full or not any([args.kernel, args.limits, args.network, args.report]):
        success = optimizer.run_full_optimization(args.config)
    else:
        parser.print_help()
        sys.exit(1)
    
    sys.exit(0 if success else 1)

if __name__ == "__main__":
    main()

6.5.2 网络性能调优

#!/bin/bash
# OpenVPN网络性能调优脚本

# 配置变量
INTERFACE="eth0"
TUN_INTERFACE="tun0"
OPENVPN_PORT=1194
OPTIMIZATION_LOG="/var/log/openvpn-network-optimization.log"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1"
    echo -e "${BLUE}$message${NC}"
    echo "$message" >> "$OPTIMIZATION_LOG"
}

log_success() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1"
    echo -e "${GREEN}$message${NC}"
    echo "$message" >> "$OPTIMIZATION_LOG"
}

log_warning() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1"
    echo -e "${YELLOW}$message${NC}"
    echo "$message" >> "$OPTIMIZATION_LOG"
}

log_error() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1"
    echo -e "${RED}$message${NC}"
    echo "$message" >> "$OPTIMIZATION_LOG"
}

# 检测网络接口
detect_interfaces() {
    log_info "检测网络接口..."
    
    # 检测主网络接口
    local main_interface=$(ip route | grep default | awk '{print $5}' | head -n1)
    if [ -n "$main_interface" ]; then
        INTERFACE="$main_interface"
        log_info "检测到主网络接口: $INTERFACE"
    fi
    
    # 检测TUN接口
    if ip link show "$TUN_INTERFACE" > /dev/null 2>&1; then
        log_info "检测到TUN接口: $TUN_INTERFACE"
    else
        log_warning "TUN接口 $TUN_INTERFACE 不存在"
    fi
}

# 优化网络接口参数
optimize_interface_parameters() {
    log_info "优化网络接口参数..."
    
    local interfaces=("$INTERFACE" "$TUN_INTERFACE")
    
    for iface in "${interfaces[@]}"; do
        if ! ip link show "$iface" > /dev/null 2>&1; then
            log_warning "接口 $iface 不存在,跳过优化"
            continue
        fi
        
        log_info "优化接口: $iface"
        
        # 设置队列长度
        if ip link set "$iface" txqueuelen 1000; then
            log_success "$iface: 设置队列长度为1000"
        else
            log_error "$iface: 设置队列长度失败"
        fi
        
        # 禁用不必要的网络功能(仅对物理接口)
        if [ "$iface" != "$TUN_INTERFACE" ]; then
            # 禁用TCP分段卸载
            if ethtool -K "$iface" tso off 2>/dev/null; then
                log_success "$iface: 禁用TSO"
            else
                log_warning "$iface: 无法禁用TSO"
            fi
            
            # 禁用通用分段卸载
            if ethtool -K "$iface" gso off 2>/dev/null; then
                log_success "$iface: 禁用GSO"
            else
                log_warning "$iface: 无法禁用GSO"
            fi
            
            # 禁用UDP分片卸载
            if ethtool -K "$iface" ufo off 2>/dev/null; then
                log_success "$iface: 禁用UFO"
            else
                log_warning "$iface: 无法禁用UFO"
            fi
            
            # 禁用通用接收卸载
            if ethtool -K "$iface" gro off 2>/dev/null; then
                log_success "$iface: 禁用GRO"
            else
                log_warning "$iface: 无法禁用GRO"
            fi
        fi
    done
}

# 优化网络队列
optimize_network_queues() {
    log_info "优化网络队列..."
    
    # 获取CPU核心数
    local cpu_cores=$(nproc)
    local queue_mask=$(printf "%x" $((2**cpu_cores - 1)))
    
    log_info "CPU核心数: $cpu_cores, 队列掩码: $queue_mask"
    
    # 优化接收队列
    for iface in "$INTERFACE"; do
        if [ -d "/sys/class/net/$iface/queues" ]; then
            log_info "优化 $iface 的接收队列..."
            
            for queue in /sys/class/net/$iface/queues/rx-*/rps_cpus; do
                if [ -f "$queue" ]; then
                    echo "$queue_mask" > "$queue" 2>/dev/null && \
                    log_success "设置RPS队列: $(basename $(dirname $queue))" || \
                    log_warning "设置RPS队列失败: $(basename $(dirname $queue))"
                fi
            done
            
            # 优化发送队列
            log_info "优化 $iface 的发送队列..."
            for queue in /sys/class/net/$iface/queues/tx-*/xps_cpus; do
                if [ -f "$queue" ]; then
                    echo "$queue_mask" > "$queue" 2>/dev/null && \
                    log_success "设置XPS队列: $(basename $(dirname $queue))" || \
                    log_warning "设置XPS队列失败: $(basename $(dirname $queue))"
                fi
            done
        else
            log_warning "$iface: 队列目录不存在"
        fi
    done
}

# 优化中断处理
optimize_interrupts() {
    log_info "优化中断处理..."
    
    # 设置网络设备预算
    if echo 600 > /proc/sys/net/core/netdev_budget 2>/dev/null; then
        log_success "设置网络设备预算: 600"
    else
        log_error "设置网络设备预算失败"
    fi
    
    # 设置网络设备预算时间
    if echo 2000 > /proc/sys/net/core/netdev_budget_usecs 2>/dev/null; then
        log_success "设置网络设备预算时间: 2000微秒"
    else
        log_warning "设置网络设备预算时间失败"
    fi
    
    # 优化中断亲和性
    local cpu_cores=$(nproc)
    local network_irqs=$(grep -E "$INTERFACE|eth" /proc/interrupts | awk -F: '{print $1}' | tr -d ' ')
    
    if [ -n "$network_irqs" ]; then
        log_info "优化网络中断亲和性..."
        local cpu_id=0
        
        for irq in $network_irqs; do
            local cpu_mask=$((1 << cpu_id))
            if echo "$cpu_mask" > "/proc/irq/$irq/smp_affinity" 2>/dev/null; then
                log_success "IRQ $irq 绑定到CPU $cpu_id"
            else
                log_warning "IRQ $irq 绑定失败"
            fi
            
            cpu_id=$(((cpu_id + 1) % cpu_cores))
        done
    else
        log_warning "未找到网络中断"
    fi
}

# 优化防火墙规则
optimize_firewall() {
    log_info "优化防火墙规则..."
    
    # 检查iptables规则数量
    local rule_count=$(iptables -L -n | wc -l)
    log_info "当前iptables规则数量: $rule_count"
    
    if [ "$rule_count" -gt 100 ]; then
        log_warning "iptables规则过多,可能影响性能"
    fi
    
    # 优化连接跟踪
    local conntrack_max=$(cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || echo "0")
    if [ "$conntrack_max" -lt 65536 ]; then
        if echo 65536 > /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null; then
            log_success "增加连接跟踪表大小: 65536"
        else
            log_warning "设置连接跟踪表大小失败"
        fi
    fi
    
    # 优化连接跟踪超时
    if echo 300 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout 2>/dev/null; then
        log_success "设置UDP连接跟踪超时: 300秒"
    else
        log_warning "设置UDP连接跟踪超时失败"
    fi
}

# 测试网络性能
test_network_performance() {
    log_info "测试网络性能..."
    
    # 测试网络延迟
    local gateway=$(ip route | grep default | awk '{print $3}' | head -n1)
    if [ -n "$gateway" ]; then
        log_info "测试到网关的延迟: $gateway"
        local ping_result=$(ping -c 5 "$gateway" 2>/dev/null | tail -n1 | awk -F'/' '{print $5}')
        if [ -n "$ping_result" ]; then
            log_success "平均延迟: ${ping_result}ms"
        else
            log_warning "无法测试网关延迟"
        fi
    fi
    
    # 测试网络吞吐量(如果有iperf3)
    if command -v iperf3 > /dev/null; then
        log_info "iperf3可用,可以进行详细的网络性能测试"
    else
        log_info "建议安装iperf3进行网络性能测试: apt-get install iperf3"
    fi
    
    # 显示网络统计
    log_info "网络接口统计:"
    for iface in "$INTERFACE" "$TUN_INTERFACE"; do
        if [ -f "/sys/class/net/$iface/statistics/rx_bytes" ]; then
            local rx_bytes=$(cat "/sys/class/net/$iface/statistics/rx_bytes")
            local tx_bytes=$(cat "/sys/class/net/$iface/statistics/tx_bytes")
            local rx_packets=$(cat "/sys/class/net/$iface/statistics/rx_packets")
            local tx_packets=$(cat "/sys/class/net/$iface/statistics/tx_packets")
            local rx_errors=$(cat "/sys/class/net/$iface/statistics/rx_errors")
            local tx_errors=$(cat "/sys/class/net/$iface/statistics/tx_errors")
            
            log_info "$iface: RX ${rx_bytes}字节/${rx_packets}包, TX ${tx_bytes}字节/${tx_packets}包, 错误 RX:${rx_errors} TX:${tx_errors}"
        fi
    done
}

# 创建性能监控脚本
create_monitoring_script() {
    log_info "创建网络性能监控脚本..."
    
    local monitor_script="/usr/local/bin/openvpn-network-monitor.sh"
    
    cat > "$monitor_script" << 'EOF'
#!/bin/bash
# OpenVPN网络性能监控脚本

MONITOR_LOG="/var/log/openvpn-network-monitor.log"
INTERVAL=60  # 监控间隔(秒)

log_metric() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$MONITOR_LOG"
}

while true; do
    # 获取网络统计
    for iface in $(ls /sys/class/net/ | grep -E '^(eth|ens|enp|tun)'); do
        if [ -f "/sys/class/net/$iface/statistics/rx_bytes" ]; then
            rx_bytes=$(cat "/sys/class/net/$iface/statistics/rx_bytes")
            tx_bytes=$(cat "/sys/class/net/$iface/statistics/tx_bytes")
            rx_packets=$(cat "/sys/class/net/$iface/statistics/rx_packets")
            tx_packets=$(cat "/sys/class/net/$iface/statistics/tx_packets")
            
            log_metric "INTERFACE:$iface RX_BYTES:$rx_bytes TX_BYTES:$tx_bytes RX_PACKETS:$rx_packets TX_PACKETS:$tx_packets"
        fi
    done
    
    # 获取连接统计
    openvpn_connections=$(netstat -an | grep :1194 | wc -l)
    log_metric "OPENVPN_CONNECTIONS:$openvpn_connections"
    
    # 获取系统负载
    load_avg=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
    log_metric "LOAD_AVERAGE:$load_avg"
    
    sleep "$INTERVAL"
done
EOF
    
    chmod +x "$monitor_script"
    
    # 创建systemd服务
    cat > /etc/systemd/system/openvpn-network-monitor.service << EOF
[Unit]
Description=OpenVPN Network Performance Monitor
After=network.target

[Service]
Type=simple
ExecStart=$monitor_script
Restart=always
RestartSec=10
User=root

[Install]
WantedBy=multi-user.target
EOF
    
    systemctl daemon-reload
    
    log_success "网络性能监控脚本创建完成: $monitor_script"
    log_info "启动监控服务: systemctl start openvpn-network-monitor"
}

# 生成优化报告
generate_optimization_report() {
    log_info "生成网络优化报告..."
    
    local report_file="/var/log/openvpn-network-optimization-report-$(date +%Y%m%d-%H%M%S).txt"
    
    {
        echo "OpenVPN网络性能优化报告"
        echo "生成时间: $(date)"
        echo "=" * 50
        echo ""
        
        echo "系统信息:"
        echo "  内核版本: $(uname -r)"
        echo "  CPU核心数: $(nproc)"
        echo "  内存大小: $(free -h | grep Mem | awk '{print $2}')"
        echo ""
        
        echo "网络接口信息:"
        echo "  主接口: $INTERFACE"
        echo "  TUN接口: $TUN_INTERFACE"
        echo ""
        
        echo "网络参数:"
        echo "  rmem_max: $(cat /proc/sys/net/core/rmem_max)"
        echo "  wmem_max: $(cat /proc/sys/net/core/wmem_max)"
        echo "  netdev_budget: $(cat /proc/sys/net/core/netdev_budget)"
        echo "  conntrack_max: $(cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || echo 'N/A')"
        echo ""
        
        echo "OpenVPN状态:"
        echo "  服务状态: $(systemctl is-active openvpn@server 2>/dev/null || echo 'N/A')"
        echo "  连接数: $(netstat -an | grep :$OPENVPN_PORT | wc -l)"
        echo ""
        
        echo "优化建议:"
        if [ "$(cat /proc/sys/net/core/rmem_max)" -lt 16777216 ]; then
            echo "  - 建议增加接收缓冲区大小"
        fi
        
        if [ "$(cat /proc/sys/net/core/wmem_max)" -lt 16777216 ]; then
            echo "  - 建议增加发送缓冲区大小"
        fi
        
        local rule_count=$(iptables -L -n | wc -l)
        if [ "$rule_count" -gt 100 ]; then
            echo "  - 建议优化iptables规则数量 (当前: $rule_count)"
        fi
        
        if ! command -v iperf3 > /dev/null; then
            echo "  - 建议安装iperf3进行网络性能测试"
        fi
        
    } > "$report_file"
    
    log_success "优化报告已生成: $report_file"
}

# 主函数
main() {
    case "$1" in
        "optimize")
            log_info "开始网络性能优化..."
            detect_interfaces
            optimize_interface_parameters
            optimize_network_queues
            optimize_interrupts
            optimize_firewall
            create_monitoring_script
            generate_optimization_report
            log_success "网络性能优化完成!"
            ;;
        "test")
            detect_interfaces
            test_network_performance
            ;;
        "monitor")
            if [ -f "/usr/local/bin/openvpn-network-monitor.sh" ]; then
                log_info "启动网络性能监控..."
                systemctl start openvpn-network-monitor
                systemctl enable openvpn-network-monitor
                log_success "网络性能监控已启动"
            else
                log_error "监控脚本不存在,请先运行优化"
            fi
            ;;
        "report")
            generate_optimization_report
            ;;
        "status")
            log_info "网络优化状态:"
            
            detect_interfaces
            
            echo ""
            echo "网络参数状态:"
            echo "  rmem_max: $(cat /proc/sys/net/core/rmem_max)"
            echo "  wmem_max: $(cat /proc/sys/net/core/wmem_max)"
            echo "  netdev_budget: $(cat /proc/sys/net/core/netdev_budget)"
            
            echo ""
            echo "监控服务状态:"
            if systemctl is-active --quiet openvpn-network-monitor; then
                echo "  ✓ 网络监控服务: 运行中"
            else
                echo "  ✗ 网络监控服务: 已停止"
            fi
            ;;
        *)
            echo "OpenVPN网络性能调优工具"
            echo "用法: $0 {optimize|test|monitor|report|status}"
            echo ""
            echo "操作说明:"
            echo "  optimize  - 执行网络性能优化"
            echo "  test      - 测试网络性能"
            echo "  monitor   - 启动性能监控"
            echo "  report    - 生成优化报告"
            echo "  status    - 显示优化状态"
            echo ""
            echo "示例:"
            echo "  $0 optimize"
            echo "  $0 test"
            echo "  $0 monitor"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 创建日志目录
mkdir -p "$(dirname "$OPTIMIZATION_LOG")"

# 执行主函数
main "$@"

6.6 监控与日志

6.6.1 日志配置与管理

#!/bin/bash
# OpenVPN日志配置与管理脚本

# 配置变量
LOG_DIR="/var/log/openvpn"
CONFIG_DIR="/etc/openvpn"
LOGROTATE_CONFIG="/etc/logrotate.d/openvpn"
MONITOR_SCRIPT="/usr/local/bin/openvpn-log-monitor.sh"
ALERT_SCRIPT="/usr/local/bin/openvpn-alert.sh"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1${NC}"
}

log_success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1${NC}"
}

log_warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1${NC}"
}

log_error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1${NC}"
}

# 创建日志目录结构
setup_log_directories() {
    log_info "创建日志目录结构..."
    
    local directories=(
        "$LOG_DIR"
        "$LOG_DIR/server"
        "$LOG_DIR/client"
        "$LOG_DIR/access"
        "$LOG_DIR/error"
        "$LOG_DIR/audit"
        "$LOG_DIR/performance"
        "$LOG_DIR/security"
        "$LOG_DIR/archive"
    )
    
    for dir in "${directories[@]}"; do
        if mkdir -p "$dir"; then
            log_success "创建目录: $dir"
        else
            log_error "创建目录失败: $dir"
            return 1
        fi
    done
    
    # 设置权限
    chown -R openvpn:openvpn "$LOG_DIR" 2>/dev/null || chown -R nobody:nogroup "$LOG_DIR"
    chmod -R 755 "$LOG_DIR"
    
    log_success "日志目录结构创建完成"
}

# 配置日志轮转
setup_log_rotation() {
    log_info "配置日志轮转..."
    
    cat > "$LOGROTATE_CONFIG" << 'EOF'
# OpenVPN日志轮转配置
/var/log/openvpn/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
    postrotate
        # 重新加载OpenVPN服务以使用新的日志文件
        systemctl reload openvpn@server 2>/dev/null || true
        systemctl reload openvpn-server@server 2>/dev/null || true
    endscript
}

/var/log/openvpn/server/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
    postrotate
        systemctl reload openvpn@server 2>/dev/null || true
    endscript
}

/var/log/openvpn/client/*.log {
    weekly
    missingok
    rotate 12
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}

/var/log/openvpn/access/*.log {
    daily
    missingok
    rotate 90
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}

/var/log/openvpn/error/*.log {
    daily
    missingok
    rotate 90
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}

/var/log/openvpn/audit/*.log {
    daily
    missingok
    rotate 365
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}

/var/log/openvpn/performance/*.log {
    hourly
    missingok
    rotate 168
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}

/var/log/openvpn/security/*.log {
    daily
    missingok
    rotate 365
    compress
    delaycompress
    notifempty
    create 644 openvpn openvpn
}
EOF
    
    # 测试logrotate配置
    if logrotate -d "$LOGROTATE_CONFIG" > /dev/null 2>&1; then
        log_success "日志轮转配置创建完成"
    else
        log_error "日志轮转配置有误"
        return 1
    fi
}

# 配置OpenVPN服务端日志
configure_server_logging() {
    log_info "配置OpenVPN服务端日志..."
    
    local server_configs=("$CONFIG_DIR/server.conf" "$CONFIG_DIR/server/server.conf")
    
    for config_file in "${server_configs[@]}"; do
        if [ -f "$config_file" ]; then
            log_info "配置文件: $config_file"
            
            # 备份原配置
            cp "$config_file" "${config_file}.backup.$(date +%Y%m%d-%H%M%S)"
            
            # 移除旧的日志配置
            sed -i '/^log\|^log-append\|^status\|^verb\|^mute/d' "$config_file"
            
            # 添加新的日志配置
            cat >> "$config_file" << EOF

# 日志配置
log-append $LOG_DIR/server/openvpn.log
status $LOG_DIR/server/status.log 10
verb 4
mute 20

# 客户端连接日志
log-append $LOG_DIR/access/client-connections.log

# 性能监控
management localhost 7505
management-log-cache 300
EOF
            
            log_success "配置完成: $config_file"
            break
        fi
    done
}

# 创建日志监控脚本
create_log_monitor() {
    log_info "创建日志监控脚本..."
    
    cat > "$MONITOR_SCRIPT" << 'EOF'
#!/bin/bash
# OpenVPN日志监控脚本

LOG_DIR="/var/log/openvpn"
ALERT_LOG="$LOG_DIR/alerts.log"
MONITOR_INTERVAL=60
ERROR_THRESHOLD=10
CONNECTION_THRESHOLD=100

# 监控函数
monitor_errors() {
    local error_count=$(grep -c "ERROR\|FATAL\|CRITICAL" "$LOG_DIR/server/openvpn.log" 2>/dev/null || echo 0)
    
    if [ "$error_count" -gt "$ERROR_THRESHOLD" ]; then
        echo "[$(date)] ALERT: 检测到 $error_count 个错误,超过阈值 $ERROR_THRESHOLD" >> "$ALERT_LOG"
        /usr/local/bin/openvpn-alert.sh "ERROR_THRESHOLD" "$error_count"
    fi
}

monitor_connections() {
    local connection_count=$(grep -c "CLIENT_LIST" "$LOG_DIR/server/status.log" 2>/dev/null || echo 0)
    
    if [ "$connection_count" -gt "$CONNECTION_THRESHOLD" ]; then
        echo "[$(date)] ALERT: 连接数 $connection_count 超过阈值 $CONNECTION_THRESHOLD" >> "$ALERT_LOG"
        /usr/local/bin/openvpn-alert.sh "CONNECTION_THRESHOLD" "$connection_count"
    fi
}

monitor_disk_space() {
    local disk_usage=$(df "$LOG_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
    
    if [ "$disk_usage" -gt 80 ]; then
        echo "[$(date)] ALERT: 日志目录磁盘使用率 ${disk_usage}% 超过80%" >> "$ALERT_LOG"
        /usr/local/bin/openvpn-alert.sh "DISK_SPACE" "$disk_usage"
    fi
}

monitor_service_status() {
    if ! systemctl is-active --quiet openvpn@server && ! systemctl is-active --quiet openvpn-server@server; then
        echo "[$(date)] ALERT: OpenVPN服务未运行" >> "$ALERT_LOG"
        /usr/local/bin/openvpn-alert.sh "SERVICE_DOWN" "OpenVPN"
    fi
}

# 主监控循环
while true; do
    monitor_errors
    monitor_connections
    monitor_disk_space
    monitor_service_status
    
    sleep "$MONITOR_INTERVAL"
done
EOF
    
    chmod +x "$MONITOR_SCRIPT"
    log_success "日志监控脚本创建完成: $MONITOR_SCRIPT"
}

# 创建告警脚本
create_alert_script() {
    log_info "创建告警脚本..."
    
    cat > "$ALERT_SCRIPT" << 'EOF'
#!/bin/bash
# OpenVPN告警脚本

ALERT_TYPE="$1"
ALERT_VALUE="$2"
LOG_FILE="/var/log/openvpn/alerts.log"
EMAIL_RECIPIENT="admin@example.com"
SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

# 发送邮件告警
send_email_alert() {
    local subject="OpenVPN Alert: $ALERT_TYPE"
    local body="Alert Type: $ALERT_TYPE\nAlert Value: $ALERT_VALUE\nTime: $(date)\nServer: $(hostname)"
    
    if command -v mail > /dev/null; then
        echo "$body" | mail -s "$subject" "$EMAIL_RECIPIENT"
        echo "[$(date)] Email alert sent for $ALERT_TYPE" >> "$LOG_FILE"
    fi
}

# 发送Slack告警
send_slack_alert() {
    local message="🚨 OpenVPN Alert\n*Type:* $ALERT_TYPE\n*Value:* $ALERT_VALUE\n*Time:* $(date)\n*Server:* $(hostname)"
    
    if command -v curl > /dev/null && [ -n "$SLACK_WEBHOOK" ]; then
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"$message\"}" \
            "$SLACK_WEBHOOK" > /dev/null 2>&1
        echo "[$(date)] Slack alert sent for $ALERT_TYPE" >> "$LOG_FILE"
    fi
}

# 记录告警
log_alert() {
    echo "[$(date)] ALERT: $ALERT_TYPE = $ALERT_VALUE" >> "$LOG_FILE"
}

# 根据告警类型执行相应操作
case "$ALERT_TYPE" in
    "ERROR_THRESHOLD")
        log_alert
        send_email_alert
        send_slack_alert
        ;;
    "CONNECTION_THRESHOLD")
        log_alert
        send_email_alert
        send_slack_alert
        ;;
    "DISK_SPACE")
        log_alert
        send_email_alert
        send_slack_alert
        # 自动清理旧日志
        find /var/log/openvpn -name "*.log.*.gz" -mtime +30 -delete
        ;;
    "SERVICE_DOWN")
        log_alert
        send_email_alert
        send_slack_alert
        # 尝试重启服务
        systemctl restart openvpn@server 2>/dev/null || systemctl restart openvpn-server@server 2>/dev/null
        ;;
    *)
        log_alert
        ;;
esac
EOF
    
    chmod +x "$ALERT_SCRIPT"
    log_success "告警脚本创建完成: $ALERT_SCRIPT"
}

# 创建systemd服务
create_monitor_service() {
    log_info "创建监控服务..."
    
    cat > /etc/systemd/system/openvpn-log-monitor.service << EOF
[Unit]
Description=OpenVPN Log Monitor
After=network.target openvpn@server.service
Wants=openvpn@server.service

[Service]
Type=simple
ExecStart=$MONITOR_SCRIPT
Restart=always
RestartSec=10
User=root
Group=root

[Install]
WantedBy=multi-user.target
EOF
    
    systemctl daemon-reload
    
    log_success "监控服务创建完成"
    log_info "启动服务: systemctl start openvpn-log-monitor"
    log_info "启用服务: systemctl enable openvpn-log-monitor"
}

# 生成日志分析报告
generate_log_report() {
    log_info "生成日志分析报告..."
    
    local report_file="$LOG_DIR/reports/log-analysis-$(date +%Y%m%d-%H%M%S).txt"
    mkdir -p "$(dirname "$report_file")"
    
    {
        echo "OpenVPN日志分析报告"
        echo "生成时间: $(date)"
        echo "=" * 50
        echo ""
        
        echo "服务状态:"
        if systemctl is-active --quiet openvpn@server; then
            echo "  ✓ OpenVPN服务: 运行中"
        elif systemctl is-active --quiet openvpn-server@server; then
            echo "  ✓ OpenVPN服务: 运行中"
        else
            echo "  ✗ OpenVPN服务: 已停止"
        fi
        echo ""
        
        echo "连接统计:"
        if [ -f "$LOG_DIR/server/status.log" ]; then
            local total_connections=$(grep -c "CLIENT_LIST" "$LOG_DIR/server/status.log" 2>/dev/null || echo 0)
            echo "  当前连接数: $total_connections"
            
            echo "  活跃客户端:"
            grep "CLIENT_LIST" "$LOG_DIR/server/status.log" 2>/dev/null | while read line; do
                echo "    $line"
            done
        else
            echo "  状态文件不存在"
        fi
        echo ""
        
        echo "错误统计 (最近24小时):"
        if [ -f "$LOG_DIR/server/openvpn.log" ]; then
            local error_count=$(grep "$(date -d '1 day ago' '+%Y-%m-%d')\|$(date '+%Y-%m-%d')" "$LOG_DIR/server/openvpn.log" | grep -c "ERROR\|FATAL\|CRITICAL" || echo 0)
            local warning_count=$(grep "$(date -d '1 day ago' '+%Y-%m-%d')\|$(date '+%Y-%m-%d')" "$LOG_DIR/server/openvpn.log" | grep -c "WARNING" || echo 0)
            
            echo "  错误数量: $error_count"
            echo "  警告数量: $warning_count"
            
            if [ "$error_count" -gt 0 ]; then
                echo "  最近错误:"
                grep "$(date -d '1 day ago' '+%Y-%m-%d')\|$(date '+%Y-%m-%d')" "$LOG_DIR/server/openvpn.log" | grep "ERROR\|FATAL\|CRITICAL" | tail -5 | while read line; do
                    echo "    $line"
                done
            fi
        else
            echo "  日志文件不存在"
        fi
        echo ""
        
        echo "磁盘使用情况:"
        df -h "$LOG_DIR" | tail -1 | awk '{print "  使用率: " $5 ", 可用空间: " $4}'
        echo ""
        
        echo "日志文件大小:"
        find "$LOG_DIR" -name "*.log" -type f -exec ls -lh {} \; | awk '{print "  " $9 ": " $5}'
        echo ""
        
        echo "性能指标:"
        if [ -f "$LOG_DIR/performance/metrics.log" ]; then
            echo "  最近性能数据:"
            tail -5 "$LOG_DIR/performance/metrics.log" | while read line; do
                echo "    $line"
            done
        else
            echo "  性能数据不可用"
        fi
        
    } > "$report_file"
    
    log_success "日志分析报告已生成: $report_file"
}

# 主函数
main() {
    case "$1" in
        "setup")
            log_info "开始设置OpenVPN日志系统..."
            setup_log_directories
            setup_log_rotation
            configure_server_logging
            create_log_monitor
            create_alert_script
            create_monitor_service
            log_success "OpenVPN日志系统设置完成!"
            ;;
        "monitor")
            if [ -f "$MONITOR_SCRIPT" ]; then
                log_info "启动日志监控..."
                systemctl start openvpn-log-monitor
                systemctl enable openvpn-log-monitor
                log_success "日志监控已启动"
            else
                log_error "监控脚本不存在,请先运行setup"
            fi
            ;;
        "report")
            generate_log_report
            ;;
        "status")
            log_info "日志系统状态:"
            
            echo ""
            echo "目录状态:"
            if [ -d "$LOG_DIR" ]; then
                echo "  ✓ 日志目录: 存在"
                echo "    大小: $(du -sh $LOG_DIR | awk '{print $1}')"
            else
                echo "  ✗ 日志目录: 不存在"
            fi
            
            echo ""
            echo "服务状态:"
            if systemctl is-active --quiet openvpn-log-monitor; then
                echo "  ✓ 日志监控服务: 运行中"
            else
                echo "  ✗ 日志监控服务: 已停止"
            fi
            
            echo ""
            echo "配置文件状态:"
            if [ -f "$LOGROTATE_CONFIG" ]; then
                echo "  ✓ 日志轮转配置: 存在"
            else
                echo "  ✗ 日志轮转配置: 不存在"
            fi
            
            if [ -f "$MONITOR_SCRIPT" ]; then
                echo "  ✓ 监控脚本: 存在"
            else
                echo "  ✗ 监控脚本: 不存在"
            fi
            
            if [ -f "$ALERT_SCRIPT" ]; then
                echo "  ✓ 告警脚本: 存在"
            else
                echo "  ✗ 告警脚本: 不存在"
            fi
            ;;
        "clean")
            log_info "清理旧日志文件..."
            
            # 清理30天前的压缩日志
            find "$LOG_DIR" -name "*.log.*.gz" -mtime +30 -delete
            
            # 清理7天前的临时文件
            find "$LOG_DIR" -name "*.tmp" -mtime +7 -delete
            
            # 清理空目录
            find "$LOG_DIR" -type d -empty -delete
            
            log_success "日志清理完成"
            ;;
        *)
            echo "OpenVPN日志配置与管理工具"
            echo "用法: $0 {setup|monitor|report|status|clean}"
            echo ""
            echo "操作说明:"
            echo "  setup    - 设置完整的日志系统"
            echo "  monitor  - 启动日志监控服务"
            echo "  report   - 生成日志分析报告"
            echo "  status   - 显示日志系统状态"
            echo "  clean    - 清理旧日志文件"
            echo ""
            echo "示例:"
            echo "  $0 setup"
            echo "  $0 monitor"
            echo "  $0 report"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 执行主函数
main "$@"

6.6.2 性能监控脚本

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OpenVPN性能监控系统
实时监控OpenVPN服务器性能指标
"""

import os
import sys
import time
import json
import psutil
import subprocess
import threading
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from pathlib import Path

class OpenVPNPerformanceMonitor:
    """OpenVPN性能监控器"""
    
    def __init__(self, config_file: str = "/etc/openvpn/monitor.conf"):
        self.config_file = config_file
        self.log_dir = "/var/log/openvpn/performance"
        self.metrics_file = f"{self.log_dir}/metrics.log"
        self.alerts_file = f"{self.log_dir}/alerts.log"
        self.running = False
        self.monitor_interval = 60  # 监控间隔(秒)
        
        # 性能阈值
        self.thresholds = {
            "cpu_usage": 80.0,
            "memory_usage": 85.0,
            "disk_usage": 90.0,
            "network_errors": 10,
            "connection_count": 1000,
            "response_time": 5000  # 毫秒
        }
        
        # 确保日志目录存在
        Path(self.log_dir).mkdir(parents=True, exist_ok=True)
        
        self.load_config()
    
    def load_config(self):
        """加载配置文件"""
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as f:
                    config = json.load(f)
                    self.monitor_interval = config.get('monitor_interval', 60)
                    self.thresholds.update(config.get('thresholds', {}))
                    self.log_message(f"配置已加载: {self.config_file}")
            except Exception as e:
                self.log_message(f"加载配置失败: {e}", "ERROR")
    
    def log_message(self, message: str, level: str = "INFO"):
        """记录日志消息"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] [{level}] {message}"
        print(log_entry)
        
        try:
            with open(self.metrics_file, "a") as f:
                f.write(log_entry + "\n")
        except Exception as e:
            print(f"写入日志失败: {e}")
    
    def run_command(self, command: str) -> Tuple[bool, str]:
        """执行系统命令"""
        try:
            result = subprocess.run(
                command, shell=True, capture_output=True, 
                text=True, timeout=10
            )
            return result.returncode == 0, result.stdout.strip()
        except subprocess.TimeoutExpired:
            return False, "命令执行超时"
        except Exception as e:
            return False, str(e)
    
    def get_system_metrics(self) -> Dict:
        """获取系统性能指标"""
        metrics = {
            "timestamp": datetime.now().isoformat(),
            "cpu": {},
            "memory": {},
            "disk": {},
            "network": {},
            "processes": {}
        }
        
        try:
            # CPU指标
            cpu_percent = psutil.cpu_percent(interval=1)
            cpu_count = psutil.cpu_count()
            load_avg = os.getloadavg()
            
            metrics["cpu"] = {
                "usage_percent": cpu_percent,
                "core_count": cpu_count,
                "load_average_1m": load_avg[0],
                "load_average_5m": load_avg[1],
                "load_average_15m": load_avg[2]
            }
            
            # 内存指标
            memory = psutil.virtual_memory()
            swap = psutil.swap_memory()
            
            metrics["memory"] = {
                "total_mb": memory.total // 1024 // 1024,
                "available_mb": memory.available // 1024 // 1024,
                "used_mb": memory.used // 1024 // 1024,
                "usage_percent": memory.percent,
                "swap_total_mb": swap.total // 1024 // 1024,
                "swap_used_mb": swap.used // 1024 // 1024,
                "swap_percent": swap.percent
            }
            
            # 磁盘指标
            disk = psutil.disk_usage('/')
            
            metrics["disk"] = {
                "total_gb": disk.total // 1024 // 1024 // 1024,
                "used_gb": disk.used // 1024 // 1024 // 1024,
                "free_gb": disk.free // 1024 // 1024 // 1024,
                "usage_percent": (disk.used / disk.total) * 100
            }
            
            # 网络指标
            network = psutil.net_io_counters()
            
            metrics["network"] = {
                "bytes_sent": network.bytes_sent,
                "bytes_recv": network.bytes_recv,
                "packets_sent": network.packets_sent,
                "packets_recv": network.packets_recv,
                "errin": network.errin,
                "errout": network.errout,
                "dropin": network.dropin,
                "dropout": network.dropout
            }
            
        except Exception as e:
            self.log_message(f"获取系统指标失败: {e}", "ERROR")
        
        return metrics
    
    def get_openvpn_metrics(self) -> Dict:
        """获取OpenVPN特定指标"""
        metrics = {
            "service_status": "unknown",
            "connection_count": 0,
            "active_clients": [],
            "traffic_stats": {},
            "management_status": "unknown"
        }
        
        try:
            # 检查服务状态
            success, output = self.run_command("systemctl is-active openvpn@server")
            if success:
                metrics["service_status"] = "active"
            else:
                success, output = self.run_command("systemctl is-active openvpn-server@server")
                metrics["service_status"] = "active" if success else "inactive"
            
            # 获取连接统计
            status_file = "/var/log/openvpn/server/status.log"
            if os.path.exists(status_file):
                with open(status_file, 'r') as f:
                    content = f.read()
                    
                    # 统计客户端连接
                    client_lines = [line for line in content.split('\n') if line.startswith('CLIENT_LIST')]
                    metrics["connection_count"] = len(client_lines)
                    
                    # 解析客户端信息
                    for line in client_lines:
                        parts = line.split(',')
                        if len(parts) >= 5:
                            client_info = {
                                "name": parts[1],
                                "real_address": parts[2],
                                "virtual_address": parts[3],
                                "bytes_received": int(parts[4]) if parts[4].isdigit() else 0,
                                "bytes_sent": int(parts[5]) if len(parts) > 5 and parts[5].isdigit() else 0,
                                "connected_since": parts[6] if len(parts) > 6 else "unknown"
                            }
                            metrics["active_clients"].append(client_info)
            
            # 获取流量统计
            success, output = self.run_command("netstat -i | grep tun0")
            if success:
                parts = output.split()
                if len(parts) >= 10:
                    metrics["traffic_stats"] = {
                        "rx_packets": int(parts[3]) if parts[3].isdigit() else 0,
                        "rx_errors": int(parts[4]) if parts[4].isdigit() else 0,
                        "tx_packets": int(parts[7]) if parts[7].isdigit() else 0,
                        "tx_errors": int(parts[8]) if parts[8].isdigit() else 0
                    }
            
            # 检查管理接口
            success, output = self.run_command("netstat -ln | grep :7505")
            metrics["management_status"] = "active" if success else "inactive"
            
        except Exception as e:
            self.log_message(f"获取OpenVPN指标失败: {e}", "ERROR")
        
        return metrics
    
    def check_thresholds(self, system_metrics: Dict, openvpn_metrics: Dict) -> List[Dict]:
        """检查性能阈值"""
        alerts = []
        
        try:
            # 检查CPU使用率
            cpu_usage = system_metrics.get("cpu", {}).get("usage_percent", 0)
            if cpu_usage > self.thresholds["cpu_usage"]:
                alerts.append({
                    "type": "CPU_HIGH",
                    "value": cpu_usage,
                    "threshold": self.thresholds["cpu_usage"],
                    "message": f"CPU使用率过高: {cpu_usage:.1f}%"
                })
            
            # 检查内存使用率
            memory_usage = system_metrics.get("memory", {}).get("usage_percent", 0)
            if memory_usage > self.thresholds["memory_usage"]:
                alerts.append({
                    "type": "MEMORY_HIGH",
                    "value": memory_usage,
                    "threshold": self.thresholds["memory_usage"],
                    "message": f"内存使用率过高: {memory_usage:.1f}%"
                })
            
            # 检查磁盘使用率
            disk_usage = system_metrics.get("disk", {}).get("usage_percent", 0)
            if disk_usage > self.thresholds["disk_usage"]:
                alerts.append({
                    "type": "DISK_HIGH",
                    "value": disk_usage,
                    "threshold": self.thresholds["disk_usage"],
                    "message": f"磁盘使用率过高: {disk_usage:.1f}%"
                })
            
            # 检查网络错误
            network_errors = (system_metrics.get("network", {}).get("errin", 0) + 
                            system_metrics.get("network", {}).get("errout", 0))
            if network_errors > self.thresholds["network_errors"]:
                alerts.append({
                    "type": "NETWORK_ERRORS",
                    "value": network_errors,
                    "threshold": self.thresholds["network_errors"],
                    "message": f"网络错误过多: {network_errors}"
                })
            
            # 检查连接数
            connection_count = openvpn_metrics.get("connection_count", 0)
            if connection_count > self.thresholds["connection_count"]:
                alerts.append({
                    "type": "CONNECTION_HIGH",
                    "value": connection_count,
                    "threshold": self.thresholds["connection_count"],
                    "message": f"连接数过多: {connection_count}"
                })
            
            # 检查服务状态
            if openvpn_metrics.get("service_status") != "active":
                alerts.append({
                    "type": "SERVICE_DOWN",
                    "value": openvpn_metrics.get("service_status"),
                    "threshold": "active",
                    "message": "OpenVPN服务未运行"
                })
            
        except Exception as e:
            self.log_message(f"检查阈值失败: {e}", "ERROR")
        
        return alerts
    
    def send_alerts(self, alerts: List[Dict]):
        """发送告警"""
        for alert in alerts:
            alert_message = {
                "timestamp": datetime.now().isoformat(),
                "alert": alert
            }
            
            # 记录告警日志
            try:
                with open(self.alerts_file, "a") as f:
                    f.write(json.dumps(alert_message, ensure_ascii=False) + "\n")
            except Exception as e:
                self.log_message(f"记录告警失败: {e}", "ERROR")
            
            # 调用外部告警脚本
            try:
                alert_script = "/usr/local/bin/openvpn-alert.sh"
                if os.path.exists(alert_script):
                    subprocess.run([
                        alert_script, 
                        alert["type"], 
                        str(alert["value"])
                    ], timeout=30)
            except Exception as e:
                self.log_message(f"发送告警失败: {e}", "ERROR")
    
    def generate_performance_report(self) -> Dict:
        """生成性能报告"""
        report = {
            "timestamp": datetime.now().isoformat(),
            "summary": {},
            "trends": {},
            "recommendations": []
        }
        
        try:
            # 分析最近24小时的数据
            metrics_data = []
            if os.path.exists(self.metrics_file):
                with open(self.metrics_file, 'r') as f:
                    for line in f:
                        if "[INFO]" in line and "timestamp" in line:
                            try:
                                # 提取JSON数据
                                json_start = line.find('{')
                                if json_start != -1:
                                    json_data = json.loads(line[json_start:])
                                    metrics_data.append(json_data)
                            except:
                                continue
            
            if metrics_data:
                # 计算平均值
                cpu_values = [m.get("cpu", {}).get("usage_percent", 0) for m in metrics_data[-24:]]
                memory_values = [m.get("memory", {}).get("usage_percent", 0) for m in metrics_data[-24:]]
                connection_values = [m.get("openvpn", {}).get("connection_count", 0) for m in metrics_data[-24:]]
                
                report["summary"] = {
                    "avg_cpu_usage": sum(cpu_values) / len(cpu_values) if cpu_values else 0,
                    "max_cpu_usage": max(cpu_values) if cpu_values else 0,
                    "avg_memory_usage": sum(memory_values) / len(memory_values) if memory_values else 0,
                    "max_memory_usage": max(memory_values) if memory_values else 0,
                    "avg_connections": sum(connection_values) / len(connection_values) if connection_values else 0,
                    "max_connections": max(connection_values) if connection_values else 0
                }
                
                # 生成建议
                if report["summary"]["avg_cpu_usage"] > 70:
                    report["recommendations"].append("CPU使用率较高,建议优化配置或升级硬件")
                
                if report["summary"]["avg_memory_usage"] > 80:
                    report["recommendations"].append("内存使用率较高,建议增加内存或优化配置")
                
                if report["summary"]["max_connections"] > 500:
                    report["recommendations"].append("连接数较多,建议考虑负载均衡")
            
        except Exception as e:
            self.log_message(f"生成性能报告失败: {e}", "ERROR")
        
        return report
    
    def monitor_loop(self):
        """监控主循环"""
        self.log_message("开始性能监控...")
        
        while self.running:
            try:
                # 获取系统指标
                system_metrics = self.get_system_metrics()
                
                # 获取OpenVPN指标
                openvpn_metrics = self.get_openvpn_metrics()
                
                # 合并指标
                combined_metrics = {
                    "timestamp": datetime.now().isoformat(),
                    "system": system_metrics,
                    "openvpn": openvpn_metrics
                }
                
                # 记录指标
                self.log_message(json.dumps(combined_metrics, ensure_ascii=False))
                
                # 检查阈值
                alerts = self.check_thresholds(system_metrics, openvpn_metrics)
                
                # 发送告警
                if alerts:
                    self.send_alerts(alerts)
                
                # 等待下次监控
                time.sleep(self.monitor_interval)
                
            except KeyboardInterrupt:
                self.log_message("收到中断信号,停止监控")
                break
            except Exception as e:
                self.log_message(f"监控循环错误: {e}", "ERROR")
                time.sleep(10)  # 错误后等待10秒再继续
        
        self.log_message("性能监控已停止")
    
    def start(self):
        """启动监控"""
        if self.running:
            self.log_message("监控已在运行中")
            return
        
        self.running = True
        monitor_thread = threading.Thread(target=self.monitor_loop)
        monitor_thread.daemon = True
        monitor_thread.start()
        
        return monitor_thread
    
    def stop(self):
        """停止监控"""
        self.running = False
        self.log_message("正在停止监控...")

def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="OpenVPN性能监控工具")
    parser.add_argument("--config", "-c", help="配置文件路径")
    parser.add_argument("--daemon", "-d", action="store_true", help="后台运行")
    parser.add_argument("--report", "-r", action="store_true", help="生成性能报告")
    parser.add_argument("--interval", "-i", type=int, default=60, help="监控间隔(秒)")
    
    args = parser.parse_args()
    
    # 创建监控器
    monitor = OpenVPNPerformanceMonitor(args.config or "/etc/openvpn/monitor.conf")
    monitor.monitor_interval = args.interval
    
    if args.report:
        # 生成报告
        report = monitor.generate_performance_report()
        print(json.dumps(report, indent=2, ensure_ascii=False))
        return
    
    if args.daemon:
        # 后台运行
        monitor.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            monitor.stop()
    else:
        # 前台运行
        monitor.running = True
        try:
            monitor.monitor_loop()
        except KeyboardInterrupt:
            monitor.stop()

if __name__ == "__main__":
    main()

6.7 安全加固

6.7.1 安全配置强化脚本

#!/bin/bash
# OpenVPN安全加固配置脚本

# 配置变量
OPENVPN_DIR="/etc/openvpn"
PKI_DIR="$OPENVPN_DIR/pki"
SERVER_CONFIG="$OPENVPN_DIR/server.conf"
SECURITY_LOG="/var/log/openvpn/security/security.log"
BACKUP_DIR="/etc/openvpn/backup"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$SECURITY_LOG"
}

log_success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$SECURITY_LOG"
}

log_warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1" >> "$SECURITY_LOG"
}

log_error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >> "$SECURITY_LOG"
}

# 创建备份
create_backup() {
    log_info "创建配置备份..."
    
    local backup_timestamp=$(date +%Y%m%d-%H%M%S)
    local backup_path="$BACKUP_DIR/security-backup-$backup_timestamp"
    
    mkdir -p "$backup_path"
    
    # 备份配置文件
    if [ -f "$SERVER_CONFIG" ]; then
        cp "$SERVER_CONFIG" "$backup_path/server.conf.backup"
        log_success "服务器配置已备份"
    fi
    
    # 备份PKI目录
    if [ -d "$PKI_DIR" ]; then
        cp -r "$PKI_DIR" "$backup_path/pki.backup"
        log_success "PKI目录已备份"
    fi
    
    # 备份防火墙规则
    iptables-save > "$backup_path/iptables.backup" 2>/dev/null
    
    log_success "备份完成: $backup_path"
}

# 强化加密配置
harden_encryption() {
    log_info "强化加密配置..."
    
    if [ ! -f "$SERVER_CONFIG" ]; then
        log_error "服务器配置文件不存在: $SERVER_CONFIG"
        return 1
    fi
    
    # 备份原配置
    cp "$SERVER_CONFIG" "${SERVER_CONFIG}.pre-hardening"
    
    # 移除弱加密配置
    sed -i '/^cipher.*DES/d' "$SERVER_CONFIG"
    sed -i '/^cipher.*RC4/d' "$SERVER_CONFIG"
    sed -i '/^cipher.*MD5/d' "$SERVER_CONFIG"
    sed -i '/^auth.*MD5/d' "$SERVER_CONFIG"
    
    # 添加强加密配置
    cat >> "$SERVER_CONFIG" << 'EOF'

# 安全加固配置
# 强加密算法
cipher AES-256-GCM
auth SHA256
ncp-ciphers AES-256-GCM:AES-128-GCM:AES-256-CBC:AES-128-CBC

# TLS安全
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256

# 完美前向保密
tls-crypt ta.key

# 防重放攻击
replay-window 64 15

# 禁用压缩(防CRIME攻击)
comp-lzo no
compress

# 额外安全选项
remote-cert-tls client
verify-x509-name client name
tls-verify /etc/openvpn/verify-cn.sh

# 限制客户端权限
user nobody
group nogroup
persist-key
persist-tun

# 禁用不安全的选项
no-replay-window
no-iv-replay
EOF
    
    log_success "加密配置已强化"
}

# 生成强密钥
generate_strong_keys() {
    log_info "生成强密钥..."
    
    # 生成TLS-Crypt密钥
    if [ ! -f "$OPENVPN_DIR/ta.key" ]; then
        openvpn --genkey --secret "$OPENVPN_DIR/ta.key"
        chmod 600 "$OPENVPN_DIR/ta.key"
        log_success "TLS-Crypt密钥已生成"
    else
        log_warning "TLS-Crypt密钥已存在"
    fi
    
    # 生成DH参数(4096位)
    if [ ! -f "$PKI_DIR/dh.pem" ] || [ $(openssl dhparam -in "$PKI_DIR/dh.pem" -text -noout | grep "DH Parameters" -A1 | tail -1 | awk '{print $1}' | tr -d '()') -lt 4096 ]; then
        log_info "生成4096位DH参数(这可能需要几分钟)..."
        openssl dhparam -out "$PKI_DIR/dh.pem" 4096
        chmod 600 "$PKI_DIR/dh.pem"
        log_success "4096位DH参数已生成"
    else
        log_warning "强DH参数已存在"
    fi
    
    # 检查证书密钥长度
    if [ -f "$PKI_DIR/ca.crt" ]; then
        local key_length=$(openssl x509 -in "$PKI_DIR/ca.crt" -text -noout | grep "Public-Key:" | awk '{print $2}' | tr -d '()')
        if [ "$key_length" -lt 2048 ]; then
            log_warning "CA证书密钥长度($key_length)小于2048位,建议重新生成"
        else
            log_success "CA证书密钥长度: $key_length 位"
        fi
    fi
}

# 配置防火墙规则
configure_firewall() {
    log_info "配置防火墙规则..."
    
    # 检查iptables是否可用
    if ! command -v iptables > /dev/null; then
        log_error "iptables未安装"
        return 1
    fi
    
    # 创建OpenVPN链
    iptables -t filter -N OPENVPN-INPUT 2>/dev/null || true
    iptables -t filter -N OPENVPN-FORWARD 2>/dev/null || true
    iptables -t nat -N OPENVPN-NAT 2>/dev/null || true
    
    # 清空现有规则
    iptables -t filter -F OPENVPN-INPUT
    iptables -t filter -F OPENVPN-FORWARD
    iptables -t nat -F OPENVPN-NAT
    
    # 基本INPUT规则
    iptables -A OPENVPN-INPUT -i lo -j ACCEPT
    iptables -A OPENVPN-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # OpenVPN端口(限制连接频率)
    iptables -A OPENVPN-INPUT -p udp --dport 1194 -m recent --name openvpn --set
    iptables -A OPENVPN-INPUT -p udp --dport 1194 -m recent --name openvpn --rcheck --seconds 60 --hitcount 10 -j DROP
    iptables -A OPENVPN-INPUT -p udp --dport 1194 -j ACCEPT
    
    # 管理端口(仅本地访问)
    iptables -A OPENVPN-INPUT -p tcp --dport 7505 -s 127.0.0.1 -j ACCEPT
    iptables -A OPENVPN-INPUT -p tcp --dport 7505 -j DROP
    
    # SSH访问(限制频率)
    iptables -A OPENVPN-INPUT -p tcp --dport 22 -m recent --name ssh --set
    iptables -A OPENVPN-INPUT -p tcp --dport 22 -m recent --name ssh --rcheck --seconds 60 --hitcount 5 -j DROP
    iptables -A OPENVPN-INPUT -p tcp --dport 22 -j ACCEPT
    
    # 拒绝其他连接
    iptables -A OPENVPN-INPUT -j DROP
    
    # FORWARD规则
    iptables -A OPENVPN-FORWARD -i tun+ -o eth0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    iptables -A OPENVPN-FORWARD -i eth0 -o tun+ -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # 防止VPN客户端互相访问(可选)
    # iptables -A OPENVPN-FORWARD -i tun+ -o tun+ -j DROP
    
    # NAT规则
    iptables -t nat -A OPENVPN-NAT -s 10.8.0.0/24 -o eth0 -j MASQUERADE
    
    # 将规则插入到主链
    iptables -I INPUT -j OPENVPN-INPUT
    iptables -I FORWARD -j OPENVPN-FORWARD
    iptables -t nat -I POSTROUTING -j OPENVPN-NAT
    
    # 保存规则
    if command -v iptables-save > /dev/null; then
        iptables-save > /etc/iptables/rules.v4 2>/dev/null || \
        iptables-save > /etc/iptables.rules 2>/dev/null || \
        iptables-save > /etc/sysconfig/iptables 2>/dev/null || true
    fi
    
    log_success "防火墙规则已配置"
}

# 创建客户端验证脚本
create_client_verification() {
    log_info "创建客户端验证脚本..."
    
    cat > /etc/openvpn/verify-cn.sh << 'EOF'
#!/bin/bash
# OpenVPN客户端证书验证脚本

CLIENT_CN="$1"
CLIENT_CERT="$2"
LOG_FILE="/var/log/openvpn/security/client-verification.log"

# 记录验证尝试
echo "[$(date)] Verifying client: $CLIENT_CN from $trusted_ip" >> "$LOG_FILE"

# 检查证书是否在撤销列表中
if [ -f "/etc/openvpn/pki/crl.pem" ]; then
    if openssl verify -CAfile /etc/openvpn/pki/ca.crt -CRLfile /etc/openvpn/pki/crl.pem "$CLIENT_CERT" > /dev/null 2>&1; then
        echo "[$(date)] Certificate verification passed for $CLIENT_CN" >> "$LOG_FILE"
    else
        echo "[$(date)] Certificate verification failed for $CLIENT_CN" >> "$LOG_FILE"
        exit 1
    fi
fi

# 检查客户端名称格式
if [[ ! "$CLIENT_CN" =~ ^[a-zA-Z0-9_-]+$ ]]; then
    echo "[$(date)] Invalid client name format: $CLIENT_CN" >> "$LOG_FILE"
    exit 1
fi

# 检查客户端是否在允许列表中(可选)
ALLOWED_CLIENTS_FILE="/etc/openvpn/allowed-clients.txt"
if [ -f "$ALLOWED_CLIENTS_FILE" ]; then
    if ! grep -q "^$CLIENT_CN$" "$ALLOWED_CLIENTS_FILE"; then
        echo "[$(date)] Client $CLIENT_CN not in allowed list" >> "$LOG_FILE"
        exit 1
    fi
fi

# 检查时间窗口(防止重放攻击)
CURRENT_TIME=$(date +%s)
CERT_NOT_BEFORE=$(openssl x509 -in "$CLIENT_CERT" -noout -startdate | cut -d= -f2)
CERT_NOT_AFTER=$(openssl x509 -in "$CLIENT_CERT" -noout -enddate | cut -d= -f2)

NOT_BEFORE_EPOCH=$(date -d "$CERT_NOT_BEFORE" +%s)
NOT_AFTER_EPOCH=$(date -d "$CERT_NOT_AFTER" +%s)

if [ "$CURRENT_TIME" -lt "$NOT_BEFORE_EPOCH" ] || [ "$CURRENT_TIME" -gt "$NOT_AFTER_EPOCH" ]; then
    echo "[$(date)] Certificate time validation failed for $CLIENT_CN" >> "$LOG_FILE"
    exit 1
fi

echo "[$(date)] Client verification successful for $CLIENT_CN" >> "$LOG_FILE"
exit 0
EOF
    
    chmod +x /etc/openvpn/verify-cn.sh
    log_success "客户端验证脚本已创建"
}

# 配置系统安全参数
configure_system_security() {
    log_info "配置系统安全参数..."
    
    # 内核参数优化
    cat > /etc/sysctl.d/99-openvpn-security.conf << 'EOF'
# OpenVPN安全优化参数

# 网络安全
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# IPv6安全(如果启用)
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# 内存保护
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.yama.ptrace_scope = 1

# 文件系统安全
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
EOF
    
    # 应用内核参数
    sysctl -p /etc/sysctl.d/99-openvpn-security.conf
    
    log_success "系统安全参数已配置"
}

# 配置日志审计
configure_audit_logging() {
    log_info "配置审计日志..."
    
    # 创建审计日志目录
    mkdir -p /var/log/openvpn/audit
    
    # 配置rsyslog for OpenVPN
    cat > /etc/rsyslog.d/99-openvpn.conf << 'EOF'
# OpenVPN日志配置

# OpenVPN服务日志
:programname, isequal, "openvpn" /var/log/openvpn/server/openvpn.log
& stop

# OpenVPN连接日志
:msg, contains, "CLIENT_LIST" /var/log/openvpn/audit/connections.log
& stop

# OpenVPN错误日志
:msg, contains, "ERROR" /var/log/openvpn/error/errors.log
:msg, contains, "FATAL" /var/log/openvpn/error/errors.log
:msg, contains, "WARNING" /var/log/openvpn/error/errors.log
& stop

# 安全事件日志
:msg, contains, "TLS Error" /var/log/openvpn/security/tls-errors.log
:msg, contains, "certificate verify failed" /var/log/openvpn/security/cert-failures.log
:msg, contains, "authentication failed" /var/log/openvpn/security/auth-failures.log
& stop
EOF
    
    # 重启rsyslog
    systemctl restart rsyslog
    
    log_success "审计日志已配置"
}

# 设置文件权限
set_file_permissions() {
    log_info "设置文件权限..."
    
    # OpenVPN配置目录
    chmod 755 "$OPENVPN_DIR"
    
    # 服务器配置文件
    if [ -f "$SERVER_CONFIG" ]; then
        chmod 600 "$SERVER_CONFIG"
        chown root:root "$SERVER_CONFIG"
    fi
    
    # PKI目录和文件
    if [ -d "$PKI_DIR" ]; then
        chmod 700 "$PKI_DIR"
        chown -R root:root "$PKI_DIR"
        
        # 私钥文件
        find "$PKI_DIR" -name "*.key" -exec chmod 600 {} \;
        
        # 证书文件
        find "$PKI_DIR" -name "*.crt" -exec chmod 644 {} \;
        find "$PKI_DIR" -name "*.pem" -exec chmod 644 {} \;
    fi
    
    # TLS密钥
    if [ -f "$OPENVPN_DIR/ta.key" ]; then
        chmod 600 "$OPENVPN_DIR/ta.key"
        chown root:root "$OPENVPN_DIR/ta.key"
    fi
    
    # 日志目录
    if [ -d "/var/log/openvpn" ]; then
        chmod 755 /var/log/openvpn
        chmod 750 /var/log/openvpn/security
        chown -R root:adm /var/log/openvpn
    fi
    
    log_success "文件权限已设置"
}

# 创建安全检查脚本
create_security_check() {
    log_info "创建安全检查脚本..."
    
    cat > /usr/local/bin/openvpn-security-check.sh << 'EOF'
#!/bin/bash
# OpenVPN安全检查脚本

SECURITY_LOG="/var/log/openvpn/security/security-check.log"
OPENVPN_DIR="/etc/openvpn"
PKI_DIR="$OPENVPN_DIR/pki"

echo "[$(date)] 开始安全检查" >> "$SECURITY_LOG"

# 检查证书有效期
check_certificate_expiry() {
    local cert_file="$1"
    local cert_name="$2"
    
    if [ -f "$cert_file" ]; then
        local expiry_date=$(openssl x509 -in "$cert_file" -noout -enddate | cut -d= -f2)
        local expiry_epoch=$(date -d "$expiry_date" +%s)
        local current_epoch=$(date +%s)
        local days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 ))
        
        if [ "$days_until_expiry" -lt 30 ]; then
            echo "[$(date)] WARNING: $cert_name 将在 $days_until_expiry 天后过期" >> "$SECURITY_LOG"
        elif [ "$days_until_expiry" -lt 90 ]; then
            echo "[$(date)] INFO: $cert_name 将在 $days_until_expiry 天后过期" >> "$SECURITY_LOG"
        fi
    fi
}

# 检查文件权限
check_file_permissions() {
    local file="$1"
    local expected_perm="$2"
    
    if [ -f "$file" ]; then
        local actual_perm=$(stat -c "%a" "$file")
        if [ "$actual_perm" != "$expected_perm" ]; then
            echo "[$(date)] WARNING: $file 权限不正确 (实际: $actual_perm, 期望: $expected_perm)" >> "$SECURITY_LOG"
        fi
    fi
}

# 检查弱加密算法
check_weak_ciphers() {
    local config_file="$OPENVPN_DIR/server.conf"
    
    if [ -f "$config_file" ]; then
        if grep -q "DES\|RC4\|MD5" "$config_file"; then
            echo "[$(date)] WARNING: 检测到弱加密算法" >> "$SECURITY_LOG"
        fi
    fi
}

# 执行检查
check_certificate_expiry "$PKI_DIR/ca.crt" "CA证书"
check_certificate_expiry "$PKI_DIR/issued/server.crt" "服务器证书"

check_file_permissions "$OPENVPN_DIR/server.conf" "600"
check_file_permissions "$OPENVPN_DIR/ta.key" "600"
check_file_permissions "$PKI_DIR/private/server.key" "600"

check_weak_ciphers

# 检查服务状态
if ! systemctl is-active --quiet openvpn@server && ! systemctl is-active --quiet openvpn-server@server; then
    echo "[$(date)] WARNING: OpenVPN服务未运行" >> "$SECURITY_LOG"
fi

# 检查防火墙状态
if ! iptables -L OPENVPN-INPUT > /dev/null 2>&1; then
    echo "[$(date)] WARNING: OpenVPN防火墙规则未配置" >> "$SECURITY_LOG"
fi

echo "[$(date)] 安全检查完成" >> "$SECURITY_LOG"
EOF
    
    chmod +x /usr/local/bin/openvpn-security-check.sh
    
    # 创建定时任务
    cat > /etc/cron.d/openvpn-security-check << 'EOF'
# OpenVPN安全检查定时任务
0 2 * * * root /usr/local/bin/openvpn-security-check.sh
EOF
    
    log_success "安全检查脚本已创建"
}

# 主函数
main() {
    case "$1" in
        "all")
            log_info "开始OpenVPN安全加固..."
            create_backup
            harden_encryption
            generate_strong_keys
            configure_firewall
            create_client_verification
            configure_system_security
            configure_audit_logging
            set_file_permissions
            create_security_check
            log_success "OpenVPN安全加固完成!"
            ;;
        "encryption")
            create_backup
            harden_encryption
            generate_strong_keys
            ;;
        "firewall")
            configure_firewall
            ;;
        "audit")
            configure_audit_logging
            ;;
        "permissions")
            set_file_permissions
            ;;
        "check")
            /usr/local/bin/openvpn-security-check.sh
            ;;
        "backup")
            create_backup
            ;;
        *)
            echo "OpenVPN安全加固工具"
            echo "用法: $0 {all|encryption|firewall|audit|permissions|check|backup}"
            echo ""
            echo "操作说明:"
            echo "  all         - 执行完整的安全加固"
            echo "  encryption  - 强化加密配置"
            echo "  firewall    - 配置防火墙规则"
            echo "  audit       - 配置审计日志"
            echo "  permissions - 设置文件权限"
            echo "  check       - 执行安全检查"
            echo "  backup      - 创建配置备份"
            echo ""
            echo "示例:"
            echo "  $0 all"
            echo "  $0 encryption"
            echo "  $0 check"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 创建必要目录
mkdir -p "$(dirname "$SECURITY_LOG")"
mkdir -p "$BACKUP_DIR"

# 执行主函数
main "$@"

6.7.2 入侵检测与防护

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OpenVPN入侵检测与防护系统
实时监控和防护OpenVPN服务器
"""

import os
import re
import sys
import time
import json
import sqlite3
import subprocess
import threading
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Set
from pathlib import Path
from collections import defaultdict, deque

class OpenVPNIntrusionDetection:
    """OpenVPN入侵检测系统"""
    
    def __init__(self, config_file: str = "/etc/openvpn/ids.conf"):
        self.config_file = config_file
        self.log_dir = "/var/log/openvpn"
        self.db_file = "/var/lib/openvpn/ids.db"
        self.running = False
        
        # 监控配置
        self.monitor_files = [
            "/var/log/openvpn/server/openvpn.log",
            "/var/log/openvpn/access/client-connections.log",
            "/var/log/openvpn/security/auth-failures.log",
            "/var/log/auth.log",
            "/var/log/syslog"
        ]
        
        # 威胁检测规则
        self.threat_patterns = {
            "brute_force": {
                "pattern": r"authentication failed|TLS Error|certificate verify failed",
                "threshold": 5,
                "window": 300,  # 5分钟
                "action": "block_ip"
            },
            "connection_flood": {
                "pattern": r"CLIENT_LIST",
                "threshold": 20,
                "window": 60,  # 1分钟
                "action": "rate_limit"
            },
            "suspicious_activity": {
                "pattern": r"SIGUSR1|SIGTERM|management interface",
                "threshold": 10,
                "window": 600,  # 10分钟
                "action": "alert"
            },
            "certificate_abuse": {
                "pattern": r"certificate has expired|certificate is not yet valid",
                "threshold": 3,
                "window": 300,
                "action": "block_cert"
            }
        }
        
        # 白名单IP
        self.whitelist_ips = set([
            "127.0.0.1",
            "::1"
        ])
        
        # 黑名单IP
        self.blacklist_ips = set()
        
        # 事件计数器
        self.event_counters = defaultdict(lambda: deque())
        
        # 初始化数据库
        self.init_database()
        
        # 加载配置
        self.load_config()
    
    def init_database(self):
        """初始化数据库"""
        os.makedirs(os.path.dirname(self.db_file), exist_ok=True)
        
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        # 创建事件表
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS security_events (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                event_type TEXT NOT NULL,
                source_ip TEXT,
                client_name TEXT,
                severity TEXT,
                description TEXT,
                action_taken TEXT,
                raw_log TEXT
            )
        """)
        
        # 创建IP黑名单表
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS ip_blacklist (
                ip TEXT PRIMARY KEY,
                added_time DATETIME DEFAULT CURRENT_TIMESTAMP,
                reason TEXT,
                expires_time DATETIME
            )
        """)
        
        # 创建统计表
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS threat_statistics (
                date DATE PRIMARY KEY,
                brute_force_attempts INTEGER DEFAULT 0,
                connection_floods INTEGER DEFAULT 0,
                blocked_ips INTEGER DEFAULT 0,
                total_threats INTEGER DEFAULT 0
            )
        """)
        
        conn.commit()
        conn.close()
    
    def load_config(self):
        """加载配置文件"""
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as f:
                    config = json.load(f)
                    
                    # 更新威胁检测规则
                    if 'threat_patterns' in config:
                        self.threat_patterns.update(config['threat_patterns'])
                    
                    # 更新白名单
                    if 'whitelist_ips' in config:
                        self.whitelist_ips.update(config['whitelist_ips'])
                    
                    # 更新监控文件
                    if 'monitor_files' in config:
                        self.monitor_files = config['monitor_files']
                    
                    self.log_message(f"配置已加载: {self.config_file}")
            except Exception as e:
                self.log_message(f"加载配置失败: {e}", "ERROR")
    
    def log_message(self, message: str, level: str = "INFO"):
        """记录日志消息"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] [IDS] [{level}] {message}"
        print(log_entry)
        
        # 写入IDS日志文件
        ids_log = f"{self.log_dir}/security/ids.log"
        try:
            os.makedirs(os.path.dirname(ids_log), exist_ok=True)
            with open(ids_log, "a") as f:
                f.write(log_entry + "\n")
        except Exception as e:
            print(f"写入日志失败: {e}")
    
    def extract_ip_from_log(self, log_line: str) -> Optional[str]:
        """从日志行中提取IP地址"""
        # 匹配IPv4地址
        ipv4_pattern = r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b'
        match = re.search(ipv4_pattern, log_line)
        if match:
            return match.group()
        
        # 匹配IPv6地址
        ipv6_pattern = r'\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b'
        match = re.search(ipv6_pattern, log_line)
        if match:
            return match.group()
        
        return None
    
    def extract_client_name(self, log_line: str) -> Optional[str]:
        """从日志行中提取客户端名称"""
        # 匹配CLIENT_LIST行中的客户端名称
        if "CLIENT_LIST" in log_line:
            parts = log_line.split(',')
            if len(parts) > 1:
                return parts[1].strip()
        
        # 匹配其他格式的客户端名称
        cn_pattern = r'CN=([^,\s]+)'
        match = re.search(cn_pattern, log_line)
        if match:
            return match.group(1)
        
        return None
    
    def is_whitelisted(self, ip: str) -> bool:
        """检查IP是否在白名单中"""
        return ip in self.whitelist_ips
    
    def add_to_blacklist(self, ip: str, reason: str, duration_hours: int = 24):
        """添加IP到黑名单"""
        if self.is_whitelisted(ip):
            self.log_message(f"IP {ip} 在白名单中,跳过黑名单添加", "WARNING")
            return
        
        expires_time = datetime.now() + timedelta(hours=duration_hours)
        
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        cursor.execute("""
            INSERT OR REPLACE INTO ip_blacklist (ip, reason, expires_time)
            VALUES (?, ?, ?)
        """, (ip, reason, expires_time))
        
        conn.commit()
        conn.close()
        
        self.blacklist_ips.add(ip)
        self.log_message(f"IP {ip} 已添加到黑名单,原因: {reason}")
        
        # 执行防火墙阻断
        self.block_ip_firewall(ip)
    
    def block_ip_firewall(self, ip: str):
        """使用防火墙阻断IP"""
        try:
            # 添加iptables规则
            subprocess.run([
                "iptables", "-I", "INPUT", "-s", ip, "-j", "DROP"
            ], check=True, capture_output=True)
            
            self.log_message(f"防火墙已阻断IP: {ip}")
        except subprocess.CalledProcessError as e:
            self.log_message(f"防火墙阻断失败: {e}", "ERROR")
    
    def unblock_expired_ips(self):
        """解除过期的IP阻断"""
        current_time = datetime.now()
        
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        # 查找过期的IP
        cursor.execute("""
            SELECT ip FROM ip_blacklist 
            WHERE expires_time < ?
        """, (current_time,))
        
        expired_ips = [row[0] for row in cursor.fetchall()]
        
        for ip in expired_ips:
            try:
                # 移除iptables规则
                subprocess.run([
                    "iptables", "-D", "INPUT", "-s", ip, "-j", "DROP"
                ], capture_output=True)
                
                self.blacklist_ips.discard(ip)
                self.log_message(f"IP {ip} 已从黑名单移除(过期)")
            except subprocess.CalledProcessError:
                pass  # 规则可能已经不存在
        
        # 从数据库中删除过期记录
        cursor.execute("""
            DELETE FROM ip_blacklist 
            WHERE expires_time < ?
        """, (current_time,))
        
        conn.commit()
        conn.close()
    
    def record_security_event(self, event_type: str, source_ip: str, 
                            client_name: str, severity: str, 
                            description: str, action_taken: str, 
                            raw_log: str):
        """记录安全事件"""
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        cursor.execute("""
            INSERT INTO security_events 
            (event_type, source_ip, client_name, severity, description, action_taken, raw_log)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        """, (event_type, source_ip, client_name, severity, description, action_taken, raw_log))
        
        conn.commit()
        conn.close()
    
    def analyze_log_line(self, log_line: str, file_path: str):
        """分析单行日志"""
        current_time = datetime.now()
        
        for threat_name, threat_config in self.threat_patterns.items():
            if re.search(threat_config['pattern'], log_line, re.IGNORECASE):
                source_ip = self.extract_ip_from_log(log_line)
                client_name = self.extract_client_name(log_line)
                
                if source_ip and not self.is_whitelisted(source_ip):
                    # 记录事件时间
                    event_key = f"{threat_name}:{source_ip}"
                    self.event_counters[event_key].append(current_time)
                    
                    # 清理过期事件
                    window_start = current_time - timedelta(seconds=threat_config['window'])
                    while (self.event_counters[event_key] and 
                           self.event_counters[event_key][0] < window_start):
                        self.event_counters[event_key].popleft()
                    
                    # 检查是否超过阈值
                    event_count = len(self.event_counters[event_key])
                    if event_count >= threat_config['threshold']:
                        self.handle_threat(threat_name, threat_config, source_ip, 
                                         client_name, event_count, log_line)
    
    def handle_threat(self, threat_name: str, threat_config: Dict, 
                     source_ip: str, client_name: str, 
                     event_count: int, raw_log: str):
        """处理威胁事件"""
        action = threat_config['action']
        description = f"{threat_name} 检测到 {event_count} 次事件,来源IP: {source_ip}"
        
        if action == "block_ip":
            self.add_to_blacklist(source_ip, threat_name, 24)
            action_taken = f"IP已阻断24小时"
            severity = "HIGH"
        elif action == "rate_limit":
            # 实现速率限制
            self.implement_rate_limit(source_ip)
            action_taken = "实施速率限制"
            severity = "MEDIUM"
        elif action == "alert":
            action_taken = "发送告警"
            severity = "LOW"
        elif action == "block_cert":
            if client_name:
                self.revoke_certificate(client_name)
                action_taken = f"证书 {client_name} 已撤销"
            else:
                action_taken = "无法撤销证书(客户端名称未知)"
            severity = "HIGH"
        else:
            action_taken = "无操作"
            severity = "INFO"
        
        # 记录安全事件
        self.record_security_event(
            threat_name, source_ip, client_name, 
            severity, description, action_taken, raw_log
        )
        
        # 发送告警
        self.send_alert(threat_name, source_ip, client_name, description, action_taken)
        
        self.log_message(f"威胁处理: {description} - {action_taken}", "WARNING")
    
    def implement_rate_limit(self, ip: str):
        """实施IP速率限制"""
        try:
            # 使用iptables限制连接速率
            subprocess.run([
                "iptables", "-I", "INPUT", "-s", ip, 
                "-p", "udp", "--dport", "1194",
                "-m", "recent", "--name", "openvpn_limit", "--set"
            ], check=True, capture_output=True)
            
            subprocess.run([
                "iptables", "-I", "INPUT", "-s", ip,
                "-p", "udp", "--dport", "1194",
                "-m", "recent", "--name", "openvpn_limit", 
                "--rcheck", "--seconds", "60", "--hitcount", "5",
                "-j", "DROP"
            ], check=True, capture_output=True)
            
            self.log_message(f"对IP {ip} 实施速率限制")
        except subprocess.CalledProcessError as e:
            self.log_message(f"速率限制失败: {e}", "ERROR")
    
    def revoke_certificate(self, client_name: str):
        """撤销客户端证书"""
        try:
            # 使用EasyRSA撤销证书
            easyrsa_path = "/etc/openvpn/easy-rsa"
            if os.path.exists(easyrsa_path):
                subprocess.run([
                    "./easyrsa", "revoke", client_name
                ], cwd=easyrsa_path, check=True, capture_output=True)
                
                # 生成新的CRL
                subprocess.run([
                    "./easyrsa", "gen-crl"
                ], cwd=easyrsa_path, check=True, capture_output=True)
                
                self.log_message(f"证书 {client_name} 已撤销")
            else:
                self.log_message("EasyRSA路径不存在,无法撤销证书", "ERROR")
        except subprocess.CalledProcessError as e:
            self.log_message(f"证书撤销失败: {e}", "ERROR")
    
    def send_alert(self, threat_type: str, source_ip: str, 
                  client_name: str, description: str, action_taken: str):
        """发送告警通知"""
        alert_script = "/usr/local/bin/openvpn-alert.sh"
        if os.path.exists(alert_script):
            try:
                subprocess.run([
                    alert_script, "SECURITY_THREAT", 
                    f"{threat_type}:{source_ip}:{description}"
                ], timeout=30, capture_output=True)
            except subprocess.TimeoutExpired:
                self.log_message("告警脚本执行超时", "WARNING")
            except Exception as e:
                self.log_message(f"发送告警失败: {e}", "ERROR")
    
    def monitor_log_file(self, file_path: str):
        """监控单个日志文件"""
        if not os.path.exists(file_path):
            return
        
        try:
            # 获取文件当前大小
            file_size = os.path.getsize(file_path)
            
            with open(file_path, 'r') as f:
                # 移动到文件末尾
                f.seek(file_size)
                
                while self.running:
                    line = f.readline()
                    if line:
                        self.analyze_log_line(line.strip(), file_path)
                    else:
                        time.sleep(0.1)
        except Exception as e:
            self.log_message(f"监控文件 {file_path} 失败: {e}", "ERROR")
    
    def cleanup_old_events(self):
        """清理旧的安全事件记录"""
        cutoff_date = datetime.now() - timedelta(days=90)
        
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        cursor.execute("""
            DELETE FROM security_events 
            WHERE timestamp < ?
        """, (cutoff_date,))
        
        deleted_count = cursor.rowcount
        conn.commit()
        conn.close()
        
        if deleted_count > 0:
            self.log_message(f"清理了 {deleted_count} 条旧的安全事件记录")
    
    def generate_threat_report(self) -> Dict:
        """生成威胁报告"""
        conn = sqlite3.connect(self.db_file)
        cursor = conn.cursor()
        
        # 获取最近24小时的威胁统计
        last_24h = datetime.now() - timedelta(hours=24)
        
        cursor.execute("""
            SELECT event_type, severity, COUNT(*) as count
            FROM security_events 
            WHERE timestamp > ?
            GROUP BY event_type, severity
        """, (last_24h,))
        
        threat_stats = {}
        for row in cursor.fetchall():
            event_type, severity, count = row
            if event_type not in threat_stats:
                threat_stats[event_type] = {}
            threat_stats[event_type][severity] = count
        
        # 获取当前黑名单IP数量
        cursor.execute("SELECT COUNT(*) FROM ip_blacklist WHERE expires_time > ?", 
                      (datetime.now(),))
        blacklist_count = cursor.fetchone()[0]
        
        # 获取最近的安全事件
        cursor.execute("""
            SELECT timestamp, event_type, source_ip, severity, description
            FROM security_events 
            WHERE timestamp > ?
            ORDER BY timestamp DESC
            LIMIT 10
        """, (last_24h,))
        
        recent_events = []
        for row in cursor.fetchall():
            recent_events.append({
                "timestamp": row[0],
                "event_type": row[1],
                "source_ip": row[2],
                "severity": row[3],
                "description": row[4]
            })
        
        conn.close()
        
        return {
            "timestamp": datetime.now().isoformat(),
            "period": "last_24_hours",
            "threat_statistics": threat_stats,
            "blacklisted_ips": blacklist_count,
            "recent_events": recent_events,
            "system_status": "active" if self.running else "inactive"
        }
    
    def start(self):
        """启动入侵检测系统"""
        if self.running:
            self.log_message("入侵检测系统已在运行中")
            return
        
        self.running = True
        self.log_message("启动OpenVPN入侵检测系统")
        
        # 启动日志监控线程
        monitor_threads = []
        for log_file in self.monitor_files:
            if os.path.exists(log_file):
                thread = threading.Thread(
                    target=self.monitor_log_file, 
                    args=(log_file,)
                )
                thread.daemon = True
                thread.start()
                monitor_threads.append(thread)
                self.log_message(f"开始监控日志文件: {log_file}")
        
        # 启动清理任务线程
        cleanup_thread = threading.Thread(target=self.cleanup_task)
        cleanup_thread.daemon = True
        cleanup_thread.start()
        
        return monitor_threads
    
    def cleanup_task(self):
        """定期清理任务"""
        while self.running:
            try:
                # 解除过期的IP阻断
                self.unblock_expired_ips()
                
                # 清理旧的事件记录
                self.cleanup_old_events()
                
                # 等待1小时
                time.sleep(3600)
            except Exception as e:
                self.log_message(f"清理任务错误: {e}", "ERROR")
                time.sleep(300)  # 错误后等待5分钟
    
    def stop(self):
        """停止入侵检测系统"""
        self.running = False
        self.log_message("正在停止入侵检测系统...")

def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="OpenVPN入侵检测系统")
    parser.add_argument("--config", "-c", help="配置文件路径")
    parser.add_argument("--daemon", "-d", action="store_true", help="后台运行")
    parser.add_argument("--report", "-r", action="store_true", help="生成威胁报告")
    
    args = parser.parse_args()
    
    # 创建IDS实例
    ids = OpenVPNIntrusionDetection(args.config or "/etc/openvpn/ids.conf")
    
    if args.report:
        # 生成威胁报告
        report = ids.generate_threat_report()
        print(json.dumps(report, indent=2, ensure_ascii=False))
        return
    
    if args.daemon:
        # 后台运行
        ids.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            ids.stop()
    else:
        # 前台运行
        ids.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            ids.stop()

if __name__ == "__main__":
    main()

6.2.2 多协议支持配置

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OpenVPN多协议配置管理器
支持UDP、TCP、HTTP代理等多种协议配置
"""

import os
import sys
import json
import subprocess
from typing import Dict, List, Optional
from pathlib import Path

class MultiProtocolManager:
    """多协议配置管理器"""
    
    def __init__(self, base_dir: str = "/etc/openvpn"):
        self.base_dir = Path(base_dir)
        self.protocols = {
            'udp': {'port': 1194, 'description': 'UDP协议 - 性能最佳'},
            'tcp': {'port': 1195, 'description': 'TCP协议 - 稳定性好'},
            'tcp_http': {'port': 8080, 'description': 'TCP HTTP代理模式'},
            'tcp_https': {'port': 8443, 'description': 'TCP HTTPS代理模式'}
        }
        self.config_templates = {}
        self._load_templates()
    
    def _load_templates(self):
        """加载配置模板"""
        # UDP配置模板
        self.config_templates['udp'] = """
# OpenVPN UDP Server Configuration
port {port}
proto udp
dev tun-udp

# 证书和密钥
ca keys/ca.crt
cert keys/server-udp.crt
key keys/server-udp.key
dh keys/dh.pem
tls-auth keys/ta.key 0

# 网络设置
server 10.8.1.0 255.255.255.0
ifconfig-pool-persist ipp-udp.txt

# 路由设置
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 安全设置
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# 性能优化
fast-io
sndbuf 0
rcvbuf 0

# 连接设置
keepalive 10 120
max-clients 100

# 系统设置
user nobody
group nogroup
persist-key
persist-tun

# 日志设置
status /var/log/openvpn/udp-status.log
log-append /var/log/openvpn/udp.log
verb 3

# 管理接口
management 127.0.0.1 7505
"""
        
        # TCP配置模板
        self.config_templates['tcp'] = """
# OpenVPN TCP Server Configuration
port {port}
proto tcp
dev tun-tcp

# 证书和密钥
ca keys/ca.crt
cert keys/server-tcp.crt
key keys/server-tcp.key
dh keys/dh.pem
tls-auth keys/ta.key 0

# 网络设置
server 10.8.2.0 255.255.255.0
ifconfig-pool-persist ipp-tcp.txt

# 路由设置
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 安全设置
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# TCP特定优化
tcp-nodelay

# 连接设置
keepalive 10 120
max-clients 50

# 系统设置
user nobody
group nogroup
persist-key
persist-tun

# 日志设置
status /var/log/openvpn/tcp-status.log
log-append /var/log/openvpn/tcp.log
verb 3

# 管理接口
management 127.0.0.1 7506
"""
        
        # TCP HTTP代理模式模板
        self.config_templates['tcp_http'] = """
# OpenVPN TCP HTTP Proxy Mode
port {port}
proto tcp
dev tun-http

# 证书和密钥
ca keys/ca.crt
cert keys/server-http.crt
key keys/server-http.key
dh keys/dh.pem
tls-auth keys/ta.key 0

# 网络设置
server 10.8.3.0 255.255.255.0
ifconfig-pool-persist ipp-http.txt

# HTTP代理设置
http-proxy-retry
http-proxy-option AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

# 路由设置
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 安全设置
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# 连接设置
keepalive 10 120
max-clients 30

# 系统设置
user nobody
group nogroup
persist-key
persist-tun

# 日志设置
status /var/log/openvpn/http-status.log
log-append /var/log/openvpn/http.log
verb 3

# 管理接口
management 127.0.0.1 7507
"""
        
        # TCP HTTPS代理模式模板
        self.config_templates['tcp_https'] = """
# OpenVPN TCP HTTPS Proxy Mode
port {port}
proto tcp
dev tun-https

# 证书和密钥
ca keys/ca.crt
cert keys/server-https.crt
key keys/server-https.key
dh keys/dh.pem
tls-auth keys/ta.key 0

# 网络设置
server 10.8.4.0 255.255.255.0
ifconfig-pool-persist ipp-https.txt

# HTTPS代理设置
http-proxy-retry
http-proxy-option AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
http-proxy-option CUSTOM-HEADER "Host: www.example.com"

# 路由设置
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 安全设置
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# 连接设置
keepalive 10 120
max-clients 30

# 系统设置
user nobody
group nogroup
persist-key
persist-tun

# 日志设置
status /var/log/openvpn/https-status.log
log-append /var/log/openvpn/https.log
verb 3

# 管理接口
management 127.0.0.1 7508
"""
    
    def create_protocol_config(self, protocol: str, custom_port: Optional[int] = None) -> bool:
        """创建指定协议的配置文件"""
        if protocol not in self.protocols:
            print(f"错误: 不支持的协议 '{protocol}'")
            return False
        
        port = custom_port or self.protocols[protocol]['port']
        
        # 创建协议目录
        protocol_dir = self.base_dir / protocol
        protocol_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建子目录
        (protocol_dir / "keys").mkdir(exist_ok=True)
        (protocol_dir / "ccd").mkdir(exist_ok=True)
        
        # 生成配置文件
        config_content = self.config_templates[protocol].format(port=port)
        config_file = protocol_dir / "server.conf"
        
        with open(config_file, 'w') as f:
            f.write(config_content)
        
        print(f"✓ 创建 {protocol} 协议配置文件: {config_file}")
        print(f"  端口: {port}")
        print(f"  描述: {self.protocols[protocol]['description']}")
        
        return True
    
    def generate_certificates(self, protocol: str) -> bool:
        """为指定协议生成证书"""
        if protocol not in self.protocols:
            print(f"错误: 不支持的协议 '{protocol}'")
            return False
        
        easy_rsa_dir = self.base_dir / "easy-rsa"
        protocol_dir = self.base_dir / protocol
        
        if not easy_rsa_dir.exists():
            print("错误: Easy-RSA未初始化,请先运行PKI初始化")
            return False
        
        try:
            # 切换到Easy-RSA目录
            os.chdir(easy_rsa_dir)
            
            # 生成服务器证书
            server_name = f"server-{protocol}"
            
            if not (easy_rsa_dir / "pki" / "issued" / f"{server_name}.crt").exists():
                subprocess.run([
                    "./easyrsa", "--batch", "build-server-full", server_name, "nopass"
                ], check=True)
                print(f"✓ 生成服务器证书: {server_name}")
            
            # 复制证书到协议目录
            keys_dir = protocol_dir / "keys"
            
            # 复制文件
            files_to_copy = [
                ("pki/ca.crt", "ca.crt"),
                (f"pki/issued/{server_name}.crt", f"server-{protocol}.crt"),
                (f"pki/private/{server_name}.key", f"server-{protocol}.key"),
                ("pki/dh.pem", "dh.pem"),
                ("pki/ta.key", "ta.key")
            ]
            
            for src, dst in files_to_copy:
                src_path = easy_rsa_dir / src
                dst_path = keys_dir / dst
                
                if src_path.exists():
                    subprocess.run(["cp", str(src_path), str(dst_path)], check=True)
                    
                    # 设置权限
                    if "key" in dst:
                        os.chmod(dst_path, 0o600)
            
            print(f"✓ 复制证书到 {protocol} 目录")
            return True
            
        except subprocess.CalledProcessError as e:
            print(f"错误: 证书生成失败 - {e}")
            return False
    
    def create_systemd_service(self, protocol: str) -> bool:
        """创建systemd服务文件"""
        if protocol not in self.protocols:
            print(f"错误: 不支持的协议 '{protocol}'")
            return False
        
        service_content = f"""
[Unit]
Description=OpenVPN service for {protocol} protocol
After=syslog.target network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)

[Service]
Type=notify
PrivateTmp=true
WorkingDirectory={self.base_dir}/{protocol}
ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-{protocol}.log --status-version 2 --suppress-timestamps --config server.conf
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
LimitNPROC=100
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
"""
        
        service_file = Path(f"/etc/systemd/system/openvpn-{protocol}.service")
        
        with open(service_file, 'w') as f:
            f.write(service_content)
        
        # 重新加载systemd
        subprocess.run(["systemctl", "daemon-reload"], check=True)
        
        print(f"✓ 创建systemd服务: openvpn-{protocol}.service")
        return True
    
    def configure_firewall(self, protocol: str) -> bool:
        """配置防火墙规则"""
        if protocol not in self.protocols:
            print(f"错误: 不支持的协议 '{protocol}'")
            return False
        
        port = self.protocols[protocol]['port']
        proto_type = "tcp" if "tcp" in protocol else "udp"
        
        try:
            # 允许端口
            subprocess.run([
                "iptables", "-A", "INPUT", "-p", proto_type, 
                "--dport", str(port), "-j", "ACCEPT"
            ], check=True)
            
            # 获取外网接口
            result = subprocess.run([
                "ip", "route", "show", "default"
            ], capture_output=True, text=True)
            
            if result.returncode == 0:
                external_interface = result.stdout.split()[4]
                
                # 配置NAT规则
                subnet_map = {
                    'udp': '10.8.1.0/24',
                    'tcp': '10.8.2.0/24',
                    'tcp_http': '10.8.3.0/24',
                    'tcp_https': '10.8.4.0/24'
                }
                
                subnet = subnet_map.get(protocol, '10.8.1.0/24')
                
                subprocess.run([
                    "iptables", "-t", "nat", "-A", "POSTROUTING",
                    "-s", subnet, "-o", external_interface, "-j", "MASQUERADE"
                ], check=True)
                
                print(f"✓ 配置 {protocol} 防火墙规则 (端口: {port}, 子网: {subnet})")
                return True
            
        except subprocess.CalledProcessError as e:
            print(f"错误: 防火墙配置失败 - {e}")
            return False
    
    def generate_client_config(self, protocol: str, client_name: str, server_ip: str) -> str:
        """生成客户端配置文件"""
        if protocol not in self.protocols:
            raise ValueError(f"不支持的协议: {protocol}")
        
        port = self.protocols[protocol]['port']
        proto_type = "tcp" if "tcp" in protocol else "udp"
        
        # 基础配置
        config = f"""
client
dev tun
proto {proto_type}
remote {server_ip} {port}
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3
"""
        
        # 协议特定配置
        if protocol == "tcp_http":
            config += """
# HTTP代理模式配置
http-proxy-retry
http-proxy-option AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
"""
        elif protocol == "tcp_https":
            config += """
# HTTPS代理模式配置
http-proxy-retry
http-proxy-option AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
http-proxy-option CUSTOM-HEADER "Host: www.example.com"
"""
        
        # 添加证书内容
        easy_rsa_dir = self.base_dir / "easy-rsa"
        
        try:
            # 读取证书文件
            ca_crt = (easy_rsa_dir / "pki" / "ca.crt").read_text()
            client_crt = (easy_rsa_dir / "pki" / "issued" / f"{client_name}.crt").read_text()
            client_key = (easy_rsa_dir / "pki" / "private" / f"{client_name}.key").read_text()
            ta_key = (easy_rsa_dir / "pki" / "ta.key").read_text()
            
            config += f"""

<ca>
{ca_crt}
</ca>

<cert>
{client_crt}
</cert>

<key>
{client_key}
</key>

<tls-auth>
{ta_key}
</tls-auth>
key-direction 1
"""
            
            return config
            
        except FileNotFoundError as e:
            raise FileNotFoundError(f"证书文件不存在: {e}")
    
    def deploy_protocol(self, protocol: str, custom_port: Optional[int] = None) -> bool:
        """部署指定协议的完整配置"""
        print(f"开始部署 {protocol} 协议配置...")
        
        # 创建配置文件
        if not self.create_protocol_config(protocol, custom_port):
            return False
        
        # 生成证书
        if not self.generate_certificates(protocol):
            return False
        
        # 创建systemd服务
        if not self.create_systemd_service(protocol):
            return False
        
        # 配置防火墙
        if not self.configure_firewall(protocol):
            return False
        
        print(f"✓ {protocol} 协议部署完成")
        return True
    
    def list_protocols(self):
        """列出所有支持的协议"""
        print("支持的协议:")
        for protocol, info in self.protocols.items():
            print(f"  {protocol:12} - 端口: {info['port']:5} - {info['description']}")
    
    def get_status(self) -> Dict[str, Dict]:
        """获取所有协议的状态"""
        status = {}
        
        for protocol in self.protocols:
            service_name = f"openvpn-{protocol}.service"
            
            try:
                result = subprocess.run([
                    "systemctl", "is-active", service_name
                ], capture_output=True, text=True)
                
                is_active = result.stdout.strip() == "active"
                
                # 获取连接数
                connections = 0
                status_file = f"/var/log/openvpn/{protocol}-status.log"
                
                if os.path.exists(status_file):
                    with open(status_file, 'r') as f:
                        content = f.read()
                        connections = content.count("CLIENT_LIST")
                
                status[protocol] = {
                    'active': is_active,
                    'port': self.protocols[protocol]['port'],
                    'connections': connections,
                    'description': self.protocols[protocol]['description']
                }
                
            except Exception as e:
                status[protocol] = {
                    'active': False,
                    'port': self.protocols[protocol]['port'],
                    'connections': 0,
                    'error': str(e),
                    'description': self.protocols[protocol]['description']
                }
        
        return status

# 命令行接口
def main():
    import argparse
    
    parser = argparse.ArgumentParser(description="OpenVPN多协议配置管理器")
    parser.add_argument("action", choices=[
        "list", "deploy", "status", "client", "start", "stop", "restart"
    ], help="操作类型")
    parser.add_argument("--protocol", "-p", help="协议类型")
    parser.add_argument("--port", type=int, help="自定义端口")
    parser.add_argument("--client", help="客户端名称")
    parser.add_argument("--server", help="服务器IP地址")
    
    args = parser.parse_args()
    
    manager = MultiProtocolManager()
    
    if args.action == "list":
        manager.list_protocols()
    
    elif args.action == "deploy":
        if not args.protocol:
            print("错误: 请指定协议类型 (--protocol)")
            sys.exit(1)
        
        if manager.deploy_protocol(args.protocol, args.port):
            print(f"\n{args.protocol} 协议部署成功!")
        else:
            print(f"\n{args.protocol} 协议部署失败!")
            sys.exit(1)
    
    elif args.action == "status":
        status = manager.get_status()
        
        print("OpenVPN多协议状态:")
        print("-" * 80)
        print(f"{'协议':<12} {'状态':<8} {'端口':<6} {'连接数':<8} {'描述'}")
        print("-" * 80)
        
        for protocol, info in status.items():
            status_text = "运行中" if info['active'] else "已停止"
            print(f"{protocol:<12} {status_text:<8} {info['port']:<6} {info['connections']:<8} {info['description']}")
    
    elif args.action == "client":
        if not all([args.protocol, args.client, args.server]):
            print("错误: 生成客户端配置需要指定 --protocol, --client, --server")
            sys.exit(1)
        
        try:
            config = manager.generate_client_config(args.protocol, args.client, args.server)
            
            output_file = f"{args.client}-{args.protocol}.ovpn"
            with open(output_file, 'w') as f:
                f.write(config)
            
            print(f"✓ 客户端配置文件已生成: {output_file}")
            
        except Exception as e:
            print(f"错误: {e}")
            sys.exit(1)
    
    elif args.action in ["start", "stop", "restart"]:
        if not args.protocol:
            print("错误: 请指定协议类型 (--protocol)")
            sys.exit(1)
        
        service_name = f"openvpn-{args.protocol}.service"
        
        try:
            subprocess.run(["systemctl", args.action, service_name], check=True)
            print(f"✓ {args.action} {service_name} 成功")
        except subprocess.CalledProcessError as e:
            print(f"错误: {args.action} {service_name} 失败 - {e}")
            sys.exit(1)

if __name__ == "__main__":
    main()

6.3 负载均衡配置

6.3.1 DNS轮询负载均衡

#!/bin/bash
# OpenVPN DNS轮询负载均衡配置脚本

# 配置变量
DOMAIN="vpn.example.com"
SERVERS=(
    "192.168.1.10:1194"
    "192.168.1.11:1194"
    "192.168.1.12:1194"
)
DNS_CONFIG_FILE="/etc/bind/zones/db.${DOMAIN}"
TTL=60  # DNS记录TTL,单位秒

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 安装BIND DNS服务器
install_bind() {
    log_info "安装BIND DNS服务器..."
    
    if command -v apt-get > /dev/null; then
        apt-get update
        apt-get install -y bind9 bind9utils bind9-doc
    elif command -v yum > /dev/null; then
        yum install -y bind bind-utils
    else
        log_error "不支持的包管理器"
        return 1
    fi
    
    log_success "BIND DNS服务器安装完成"
}

# 配置BIND主配置文件
configure_bind_main() {
    log_info "配置BIND主配置文件..."
    
    local named_conf="/etc/bind/named.conf.local"
    
    # 备份原配置
    if [ -f "$named_conf" ]; then
        cp "$named_conf" "${named_conf}.backup"
    fi
    
    # 添加域配置
    cat >> "$named_conf" << EOF

// OpenVPN Load Balancing Zone
zone "${DOMAIN}" {
    type master;
    file "/etc/bind/zones/db.${DOMAIN}";
    allow-transfer { any; };
};
EOF
    
    log_success "BIND主配置文件配置完成"
}

# 创建DNS区域文件
create_dns_zone() {
    log_info "创建DNS区域文件..."
    
    # 创建zones目录
    mkdir -p /etc/bind/zones
    
    # 生成区域文件
    cat > "$DNS_CONFIG_FILE" << EOF
;
; BIND data file for ${DOMAIN}
;
\$TTL    ${TTL}
@       IN      SOA     ns1.${DOMAIN}. admin.${DOMAIN}. (
                     $(date +%Y%m%d%H)        ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.${DOMAIN}.
ns1     IN      A       $(echo ${SERVERS[0]} | cut -d: -f1)

; OpenVPN Load Balancing Records
EOF
    
    # 添加A记录实现轮询
    for server in "${SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        echo "@       IN      A       $ip" >> "$DNS_CONFIG_FILE"
    done
    
    # 添加SRV记录
    echo "" >> "$DNS_CONFIG_FILE"
    echo "; SRV Records for OpenVPN" >> "$DNS_CONFIG_FILE"
    
    local priority=10
    for server in "${SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        local port=$(echo "$server" | cut -d: -f2)
        echo "_openvpn._udp    IN      SRV     $priority 5 $port $ip." >> "$DNS_CONFIG_FILE"
        ((priority += 10))
    done
    
    log_success "DNS区域文件创建完成: $DNS_CONFIG_FILE"
}

# 配置BIND选项
configure_bind_options() {
    log_info "配置BIND选项..."
    
    local options_file="/etc/bind/named.conf.options"
    
    # 备份原配置
    if [ -f "$options_file" ]; then
        cp "$options_file" "${options_file}.backup"
    fi
    
    cat > "$options_file" << EOF
options {
    directory "/var/cache/bind";
    
    // 启用递归查询
    recursion yes;
    allow-recursion { any; };
    
    // 监听所有接口
    listen-on { any; };
    listen-on-v6 { any; };
    
    // 转发器配置
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };
    
    // 安全设置
    dnssec-validation auto;
    
    // 负载均衡设置
    rrset-order {
        class IN type A name "${DOMAIN}" order random;
    };
    
    auth-nxdomain no;    # conform to RFC1035
};
EOF
    
    log_success "BIND选项配置完成"
}

# 启动和配置BIND服务
start_bind_service() {
    log_info "启动BIND服务..."
    
    # 检查配置文件语法
    if named-checkconf; then
        log_success "BIND配置文件语法检查通过"
    else
        log_error "BIND配置文件语法错误"
        return 1
    fi
    
    # 检查区域文件
    if named-checkzone "$DOMAIN" "$DNS_CONFIG_FILE"; then
        log_success "DNS区域文件检查通过"
    else
        log_error "DNS区域文件错误"
        return 1
    fi
    
    # 启动服务
    systemctl enable bind9 || systemctl enable named
    systemctl restart bind9 || systemctl restart named
    
    if systemctl is-active --quiet bind9 || systemctl is-active --quiet named; then
        log_success "BIND服务启动成功"
    else
        log_error "BIND服务启动失败"
        return 1
    fi
}

# 配置防火墙
configure_dns_firewall() {
    log_info "配置DNS防火墙规则..."
    
    # 允许DNS端口
    iptables -A INPUT -p udp --dport 53 -j ACCEPT
    iptables -A INPUT -p tcp --dport 53 -j ACCEPT
    
    # 保存规则
    if command -v iptables-save > /dev/null; then
        iptables-save > /etc/iptables/rules.v4
    fi
    
    log_success "DNS防火墙规则配置完成"
}

# 测试DNS负载均衡
test_dns_load_balancing() {
    log_info "测试DNS负载均衡..."
    
    echo "进行多次DNS查询测试..."
    
    for i in {1..10}; do
        local result=$(dig +short @localhost "$DOMAIN" A)
        echo "查询 $i: $result"
        sleep 1
    done
    
    echo ""
    log_info "SRV记录查询测试:"
    dig +short @localhost "_openvpn._udp.$DOMAIN" SRV
}

# 生成客户端配置
generate_client_config_with_dns() {
    local client_name="$1"
    
    if [ -z "$client_name" ]; then
        log_error "请提供客户端名称"
        return 1
    fi
    
    log_info "生成使用DNS负载均衡的客户端配置..."
    
    local config_file="${client_name}-dns-lb.ovpn"
    
    cat > "$config_file" << EOF
client
dev tun
proto udp

# DNS负载均衡配置
remote ${DOMAIN} 1194
resolv-retry infinite
nobind

# 多服务器配置(备用)
EOF
    
    # 添加所有服务器作为备用
    for server in "${SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        local port=$(echo "$server" | cut -d: -f2)
        echo "remote $ip $port" >> "$config_file"
    done
    
    cat >> "$config_file" << EOF

# 连接策略
remote-random
connect-retry-max 3
connect-retry 5

# 安全设置
remote-cert-tls server
cipher AES-256-GCM
auth SHA256

# 系统设置
persist-key
persist-tun
verb 3

# 证书内容(需要手动添加)
# <ca>
# ... CA证书内容 ...
# </ca>
# 
# <cert>
# ... 客户端证书内容 ...
# </cert>
# 
# <key>
# ... 客户端私钥内容 ...
# </key>
# 
# <tls-auth>
# ... TLS认证密钥内容 ...
# </tls-auth>
# key-direction 1
EOF
    
    log_success "客户端配置文件已生成: $config_file"
    log_info "请手动添加证书内容到配置文件中"
}

# 监控DNS服务器状态
monitor_dns_servers() {
    log_info "监控DNS服务器状态..."
    
    while true; do
        clear
        echo "DNS负载均衡监控 - $(date)"
        echo "=" * 50
        
        # 检查BIND服务状态
        if systemctl is-active --quiet bind9 || systemctl is-active --quiet named; then
            echo "✓ BIND服务: 运行中"
        else
            echo "✗ BIND服务: 已停止"
        fi
        
        echo ""
        echo "服务器状态检查:"
        
        for server in "${SERVERS[@]}"; do
            local ip=$(echo "$server" | cut -d: -f1)
            local port=$(echo "$server" | cut -d: -f2)
            
            if timeout 3 bash -c "</dev/tcp/$ip/$port" 2>/dev/null; then
                echo "✓ $server: 在线"
            else
                echo "✗ $server: 离线"
            fi
        done
        
        echo ""
        echo "DNS查询测试:"
        local dns_result=$(dig +short @localhost "$DOMAIN" A | head -1)
        echo "当前解析结果: $dns_result"
        
        echo ""
        echo "按 Ctrl+C 退出监控"
        sleep 10
    done
}

# 主函数
main() {
    case "$1" in
        "install")
            log_info "开始安装DNS负载均衡..."
            install_bind
            configure_bind_main
            create_dns_zone
            configure_bind_options
            start_bind_service
            configure_dns_firewall
            test_dns_load_balancing
            log_success "DNS负载均衡安装完成!"
            echo ""
            echo "使用方法:"
            echo "  客户端配置: $0 client <客户端名称>"
            echo "  监控状态:   $0 monitor"
            echo "  测试负载:   $0 test"
            ;;
        "client")
            generate_client_config_with_dns "$2"
            ;;
        "test")
            test_dns_load_balancing
            ;;
        "monitor")
            monitor_dns_servers
            ;;
        "restart")
            log_info "重启BIND服务..."
            systemctl restart bind9 || systemctl restart named
            log_success "BIND服务重启完成"
            ;;
        "status")
            log_info "DNS负载均衡状态:"
            
            if systemctl is-active --quiet bind9 || systemctl is-active --quiet named; then
                echo "✓ BIND服务: 运行中"
            else
                echo "✗ BIND服务: 已停止"
            fi
            
            echo ""
            echo "服务器列表:"
            for server in "${SERVERS[@]}"; do
                echo "  - $server"
            done
            
            echo ""
            echo "域名: $DOMAIN"
            echo "TTL: $TTL 秒"
            ;;
        *)
            echo "OpenVPN DNS负载均衡管理工具"
            echo "用法: $0 {install|client|test|monitor|restart|status}"
            echo ""
            echo "操作说明:"
            echo "  install                    - 安装和配置DNS负载均衡"
            echo "  client <客户端名称>        - 生成客户端配置文件"
            echo "  test                       - 测试DNS负载均衡"
            echo "  monitor                    - 监控服务器状态"
            echo "  restart                    - 重启BIND服务"
            echo "  status                     - 显示状态信息"
            echo ""
            echo "示例:"
            echo "  $0 install"
            echo "  $0 client user1"
            echo "  $0 test"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 执行主函数
main "$@"

6.3.2 HAProxy负载均衡

#!/bin/bash
# OpenVPN HAProxy负载均衡配置脚本

# 配置变量
HAPROXY_CONFIG="/etc/haproxy/haproxy.cfg"
OPENVPN_SERVERS=(
    "192.168.1.10:1194"
    "192.168.1.11:1194"
    "192.168.1.12:1194"
)
LB_PORT=1194
STATS_PORT=8404
STATS_USER="admin"
STATS_PASS="password123"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 安装HAProxy
install_haproxy() {
    log_info "安装HAProxy..."
    
    if command -v apt-get > /dev/null; then
        apt-get update
        apt-get install -y haproxy
    elif command -v yum > /dev/null; then
        yum install -y haproxy
    else
        log_error "不支持的包管理器"
        return 1
    fi
    
    log_success "HAProxy安装完成"
}

# 配置HAProxy
configure_haproxy() {
    log_info "配置HAProxy..."
    
    # 备份原配置
    if [ -f "$HAPROXY_CONFIG" ]; then
        cp "$HAPROXY_CONFIG" "${HAPROXY_CONFIG}.backup"
    fi
    
    # 生成HAProxy配置文件
    cat > "$HAPROXY_CONFIG" << EOF
#---------------------------------------------------------------------
# OpenVPN HAProxy Load Balancer Configuration
#---------------------------------------------------------------------

global
    log         127.0.0.1:514 local0
    chroot      /var/lib/haproxy
    stats       socket /run/haproxy/admin.sock mode 660 level admin
    stats       timeout 30s
    user        haproxy
    group       haproxy
    daemon
    
    # SSL/TLS配置
    ssl-default-bind-ciphers ECDHE+AESGCM:ECDHE+CHACHA20:RSA+AESGCM:RSA+SHA256:!aNULL:!MD5:!DSS
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    mode                    tcp
    log                     global
    option                  tcplog
    option                  dontlognull
    option                  tcp-check
    timeout connect         5000
    timeout client          50000
    timeout server          50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

#---------------------------------------------------------------------
# 统计页面配置
#---------------------------------------------------------------------
frontend stats
    bind *:${STATS_PORT}
    mode http
    stats enable
    stats uri /stats
    stats refresh 30s
    stats admin if TRUE
    stats auth ${STATS_USER}:${STATS_PASS}
    stats realm "HAProxy Statistics"

#---------------------------------------------------------------------
# OpenVPN UDP负载均衡
#---------------------------------------------------------------------
frontend openvpn_udp_frontend
    bind *:${LB_PORT}
    mode tcp
    default_backend openvpn_udp_backend

backend openvpn_udp_backend
    mode tcp
    balance roundrobin
    option tcp-check
    
    # 健康检查配置
    tcp-check connect
    tcp-check send-binary 38
    tcp-check expect binary 40
    
EOF
    
    # 添加服务器配置
    local server_id=1
    for server in "${OPENVPN_SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        local port=$(echo "$server" | cut -d: -f2)
        
        echo "    server openvpn${server_id} ${ip}:${port} check inter 5s rise 2 fall 3" >> "$HAPROXY_CONFIG"
        ((server_id++))
    done
    
    # 添加TCP配置(如果需要)
    cat >> "$HAPROXY_CONFIG" << EOF

#---------------------------------------------------------------------
# OpenVPN TCP负载均衡(可选)
#---------------------------------------------------------------------
frontend openvpn_tcp_frontend
    bind *:1195
    mode tcp
    default_backend openvpn_tcp_backend

backend openvpn_tcp_backend
    mode tcp
    balance roundrobin
    option tcp-check
    
EOF
    
    # 添加TCP服务器配置
    server_id=1
    for server in "${OPENVPN_SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        local tcp_port=1195  # 假设TCP端口为1195
        
        echo "    server openvpn_tcp${server_id} ${ip}:${tcp_port} check inter 5s rise 2 fall 3" >> "$HAPROXY_CONFIG"
        ((server_id++))
    done
    
    log_success "HAProxy配置文件生成完成"
}

# 配置日志
configure_logging() {
    log_info "配置HAProxy日志..."
    
    # 配置rsyslog
    cat > /etc/rsyslog.d/49-haproxy.conf << EOF
# HAProxy日志配置
\$ModLoad imudp
\$UDPServerRun 514
\$UDPServerAddress 127.0.0.1

# HAProxy日志分离
local0.*    /var/log/haproxy.log
& stop
EOF
    
    # 重启rsyslog
    systemctl restart rsyslog
    
    log_success "HAProxy日志配置完成"
}

# 启动HAProxy服务
start_haproxy() {
    log_info "启动HAProxy服务..."
    
    # 检查配置文件
    if haproxy -c -f "$HAPROXY_CONFIG"; then
        log_success "HAProxy配置文件检查通过"
    else
        log_error "HAProxy配置文件错误"
        return 1
    fi
    
    # 启动服务
    systemctl enable haproxy
    systemctl restart haproxy
    
    if systemctl is-active --quiet haproxy; then
        log_success "HAProxy服务启动成功"
    else
        log_error "HAProxy服务启动失败"
        return 1
    fi
}

# 配置防火墙
configure_haproxy_firewall() {
    log_info "配置HAProxy防火墙规则..."
    
    # 允许负载均衡端口
    iptables -A INPUT -p udp --dport "$LB_PORT" -j ACCEPT
    iptables -A INPUT -p tcp --dport 1195 -j ACCEPT  # TCP端口
    iptables -A INPUT -p tcp --dport "$STATS_PORT" -j ACCEPT  # 统计页面
    
    # 保存规则
    if command -v iptables-save > /dev/null; then
        iptables-save > /etc/iptables/rules.v4
    fi
    
    log_success "HAProxy防火墙规则配置完成"
}

# 生成客户端配置
generate_haproxy_client_config() {
    local client_name="$1"
    local lb_server_ip="$2"
    
    if [ -z "$client_name" ] || [ -z "$lb_server_ip" ]; then
        log_error "用法: generate_haproxy_client_config <客户端名称> <负载均衡器IP>"
        return 1
    fi
    
    log_info "生成HAProxy负载均衡客户端配置..."
    
    local config_file="${client_name}-haproxy-lb.ovpn"
    
    cat > "$config_file" << EOF
client
dev tun
proto udp

# HAProxy负载均衡器配置
remote ${lb_server_ip} ${LB_PORT}
resolv-retry infinite
nobind

# 备用服务器(直连)
EOF
    
    # 添加备用服务器
    for server in "${OPENVPN_SERVERS[@]}"; do
        local ip=$(echo "$server" | cut -d: -f1)
        local port=$(echo "$server" | cut -d: -f2)
        echo "remote $ip $port" >> "$config_file"
    done
    
    cat >> "$config_file" << EOF

# 连接策略
connect-retry-max 3
connect-retry 5

# 安全设置
remote-cert-tls server
cipher AES-256-GCM
auth SHA256

# 系统设置
persist-key
persist-tun
verb 3

# 证书内容(需要手动添加)
# <ca>
# ... CA证书内容 ...
# </ca>
# 
# <cert>
# ... 客户端证书内容 ...
# </cert>
# 
# <key>
# ... 客户端私钥内容 ...
# </key>
# 
# <tls-auth>
# ... TLS认证密钥内容 ...
# </tls-auth>
# key-direction 1
EOF
    
    log_success "客户端配置文件已生成: $config_file"
    log_info "负载均衡器地址: $lb_server_ip:$LB_PORT"
    log_info "统计页面: http://$lb_server_ip:$STATS_PORT/stats"
    log_info "统计页面用户名: $STATS_USER"
    log_info "统计页面密码: $STATS_PASS"
}

# 监控HAProxy状态
monitor_haproxy() {
    log_info "监控HAProxy状态..."
    
    while true; do
        clear
        echo "HAProxy负载均衡监控 - $(date)"
        echo "=" * 60
        
        # 检查HAProxy服务状态
        if systemctl is-active --quiet haproxy; then
            echo "✓ HAProxy服务: 运行中"
        else
            echo "✗ HAProxy服务: 已停止"
        fi
        
        echo ""
        echo "后端服务器状态:"
        
        # 使用HAProxy统计接口获取状态
        if command -v socat > /dev/null; then
            echo "show stat" | socat stdio /run/haproxy/admin.sock | \
            awk -F',' 'NR>1 && $2~/openvpn/ {printf "  %-15s %-10s %-10s\n", $2, $18, $19}'
        else
            # 手动检查服务器状态
            for server in "${OPENVPN_SERVERS[@]}"; do
                local ip=$(echo "$server" | cut -d: -f1)
                local port=$(echo "$server" | cut -d: -f2)
                
                if timeout 3 bash -c "</dev/tcp/$ip/$port" 2>/dev/null; then
                    echo "  ✓ $server: 在线"
                else
                    echo "  ✗ $server: 离线"
                fi
            done
        fi
        
        echo ""
        echo "连接统计:"
        
        # 显示连接数
        local connections=$(netstat -an | grep ":$LB_PORT " | wc -l)
        echo "  当前连接数: $connections"
        
        echo ""
        echo "统计页面: http://localhost:$STATS_PORT/stats"
        echo "按 Ctrl+C 退出监控"
        sleep 10
    done
}

# 测试负载均衡
test_load_balancing() {
    log_info "测试HAProxy负载均衡..."
    
    local lb_ip="127.0.0.1"
    
    echo "测试负载均衡器连通性..."
    
    for i in {1..5}; do
        if timeout 3 bash -c "</dev/tcp/$lb_ip/$LB_PORT" 2>/dev/null; then
            echo "✓ 测试 $i: 负载均衡器端口 $LB_PORT 可达"
        else
            echo "✗ 测试 $i: 负载均衡器端口 $LB_PORT 不可达"
        fi
        sleep 1
    done
    
    echo ""
    echo "检查统计页面..."
    
    if curl -s --connect-timeout 5 "http://$lb_ip:$STATS_PORT/stats" > /dev/null; then
        echo "✓ 统计页面可访问: http://$lb_ip:$STATS_PORT/stats"
    else
        echo "✗ 统计页面不可访问"
    fi
}

# 主函数
main() {
    case "$1" in
        "install")
            log_info "开始安装HAProxy负载均衡..."
            install_haproxy
            configure_haproxy
            configure_logging
            start_haproxy
            configure_haproxy_firewall
            test_load_balancing
            log_success "HAProxy负载均衡安装完成!"
            echo ""
            echo "使用方法:"
            echo "  客户端配置: $0 client <客户端名称> <负载均衡器IP>"
            echo "  监控状态:   $0 monitor"
            echo "  测试负载:   $0 test"
            echo "  统计页面:   http://$(hostname -I | awk '{print $1}'):$STATS_PORT/stats"
            echo "  用户名/密码: $STATS_USER/$STATS_PASS"
            ;;
        "client")
            generate_haproxy_client_config "$2" "$3"
            ;;
        "test")
            test_load_balancing
            ;;
        "monitor")
            monitor_haproxy
            ;;
        "restart")
            log_info "重启HAProxy服务..."
            systemctl restart haproxy
            log_success "HAProxy服务重启完成"
            ;;
        "status")
            log_info "HAProxy负载均衡状态:"
            
            if systemctl is-active --quiet haproxy; then
                echo "✓ HAProxy服务: 运行中"
            else
                echo "✗ HAProxy服务: 已停止"
            fi
            
            echo ""
            echo "配置信息:"
            echo "  负载均衡端口: $LB_PORT"
            echo "  统计页面端口: $STATS_PORT"
            echo "  后端服务器数量: ${#OPENVPN_SERVERS[@]}"
            
            echo ""
            echo "后端服务器列表:"
            for server in "${OPENVPN_SERVERS[@]}"; do
                echo "  - $server"
            done
            ;;
        *)
            echo "OpenVPN HAProxy负载均衡管理工具"
            echo "用法: $0 {install|client|test|monitor|restart|status}"
            echo ""
            echo "操作说明:"
            echo "  install                           - 安装和配置HAProxy负载均衡"
            echo "  client <客户端名称> <负载均衡器IP> - 生成客户端配置文件"
            echo "  test                              - 测试负载均衡"
            echo "  monitor                           - 监控服务器状态"
            echo "  restart                           - 重启HAProxy服务"
            echo "  status                            - 显示状态信息"
            echo ""
            echo "示例:"
            echo "  $0 install"
            echo "  $0 client user1 192.168.1.100"
            echo "  $0 monitor"
            exit 1
            ;;
    esac
}

# 检查root权限
if [ "$EUID" -ne 0 ]; then
    log_error "请使用root权限运行此脚本"
    exit 1
fi

# 执行主函数
main "$@"