Files
xlxumu/docs/operations/安全文档.md

57 KiB
Raw Blame History

安全文档

版本历史

版本 日期 作者 变更说明
1.0 2024-01-20 安全团队 初始版本

1. 安全概述

1.1 安全目标

确保畜牧养殖管理平台的数据安全、系统安全和业务安全,保护用户隐私和企业资产。

1.2 安全原则

  • 最小权限原则:用户和系统只获得完成任务所需的最小权限
  • 深度防御:多层安全防护,避免单点故障
  • 零信任架构:不信任任何用户或设备,持续验证
  • 数据保护:全生命周期数据保护
  • 持续监控:实时安全监控和威胁检测

1.3 安全合规

  • 等保2.0符合网络安全等级保护2.0要求
  • GDPR:遵循欧盟通用数据保护条例
  • 个人信息保护法:符合中国个人信息保护法要求
  • 行业标准:遵循畜牧业相关安全标准

2. 安全架构

2.1 安全架构图

graph TB
    subgraph "边界安全"
        WAF[Web应用防火墙]
        FW[网络防火墙]
        IPS[入侵防护系统]
        DDoS[DDoS防护]
    end
    
    subgraph "应用安全"
        AUTH[身份认证]
        AUTHZ[权限控制]
        ENCRYPT[数据加密]
        AUDIT[审计日志]
    end
    
    subgraph "数据安全"
        BACKUP[数据备份]
        MASK[数据脱敏]
        DLP[数据防泄漏]
        CRYPTO[加密存储]
    end
    
    subgraph "基础设施安全"
        HOST[主机安全]
        CONTAINER[容器安全]
        NETWORK[网络安全]
        MONITOR[安全监控]
    end
    
    Internet --> WAF
    WAF --> FW
    FW --> IPS
    IPS --> AUTH
    AUTH --> AUTHZ
    AUTHZ --> ENCRYPT
    ENCRYPT --> AUDIT

2.2 安全域划分

安全域 描述 安全等级 访问控制
互联网区 面向公网的服务 WAF + 防火墙
DMZ区 前端应用和负载均衡 严格访问控制
应用区 后端API服务 内网访问
数据区 数据库和存储 极高 最小权限访问
管理区 运维和管理系统 极高 VPN + 双因子认证

3. 身份认证与授权

3.1 用户身份认证

3.1.1 多因子认证(MFA)

// 双因子认证实现
class TwoFactorAuth {
    constructor() {
        this.totpWindow = 30; // 30秒时间窗口
        this.backupCodes = [];
    }
    
    // 生成TOTP密钥
    generateSecret(userId) {
        const secret = speakeasy.generateSecret({
            name: `畜牧管理平台 (${userId})`,
            issuer: '畜牧管理平台'
        });
        
        return {
            secret: secret.base32,
            qrCode: qrcode.toDataURL(secret.otpauth_url)
        };
    }
    
    // 验证TOTP令牌
    verifyToken(secret, token) {
        return speakeasy.totp.verify({
            secret: secret,
            encoding: 'base32',
            token: token,
            window: this.totpWindow
        });
    }
    
    // 生成备用码
    generateBackupCodes() {
        const codes = [];
        for (let i = 0; i < 10; i++) {
            codes.push(crypto.randomBytes(4).toString('hex').toUpperCase());
        }
        return codes;
    }
    
    // 验证备用码
    verifyBackupCode(userId, code) {
        // 从数据库获取用户备用码
        const userBackupCodes = this.getUserBackupCodes(userId);
        const index = userBackupCodes.indexOf(code);
        
        if (index !== -1) {
            // 使用后删除备用码
            userBackupCodes.splice(index, 1);
            this.updateUserBackupCodes(userId, userBackupCodes);
            return true;
        }
        
        return false;
    }
}

3.1.2 JWT令牌安全

// JWT安全配置
const jwtConfig = {
    // 使用RS256算法
    algorithm: 'RS256',
    // 短期访问令牌
    accessTokenExpiry: '15m',
    // 长期刷新令牌
    refreshTokenExpiry: '7d',
    // 令牌发行者
    issuer: 'xlxumu-platform',
    // 令牌受众
    audience: 'xlxumu-users'
};

class JWTManager {
    constructor() {
        this.privateKey = fs.readFileSync('private.pem');
        this.publicKey = fs.readFileSync('public.pem');
        this.blacklist = new Set(); // 令牌黑名单
    }
    
    // 生成访问令牌
    generateAccessToken(payload) {
        return jwt.sign(payload, this.privateKey, {
            algorithm: jwtConfig.algorithm,
            expiresIn: jwtConfig.accessTokenExpiry,
            issuer: jwtConfig.issuer,
            audience: jwtConfig.audience,
            jwtid: uuidv4() // 唯一标识符
        });
    }
    
    // 生成刷新令牌
    generateRefreshToken(userId) {
        const payload = {
            userId: userId,
            type: 'refresh',
            tokenFamily: uuidv4() // 令牌族标识
        };
        
        return jwt.sign(payload, this.privateKey, {
            algorithm: jwtConfig.algorithm,
            expiresIn: jwtConfig.refreshTokenExpiry,
            issuer: jwtConfig.issuer,
            audience: jwtConfig.audience,
            jwtid: uuidv4()
        });
    }
    
    // 验证令牌
    verifyToken(token) {
        try {
            // 检查黑名单
            if (this.blacklist.has(token)) {
                throw new Error('Token is blacklisted');
            }
            
            const decoded = jwt.verify(token, this.publicKey, {
                algorithms: [jwtConfig.algorithm],
                issuer: jwtConfig.issuer,
                audience: jwtConfig.audience
            });
            
            return decoded;
        } catch (error) {
            throw new Error('Invalid token');
        }
    }
    
    // 撤销令牌
    revokeToken(token) {
        this.blacklist.add(token);
        // 可以设置定时清理过期的黑名单令牌
    }
}

3.2 权限控制系统

3.2.1 RBAC权限模型

// 基于角色的访问控制
class RBACManager {
    constructor() {
        this.roles = new Map();
        this.permissions = new Map();
        this.userRoles = new Map();
    }
    
    // 定义权限
    definePermission(name, resource, action) {
        this.permissions.set(name, {
            resource: resource,
            action: action,
            description: `${action} on ${resource}`
        });
    }
    
    // 定义角色
    defineRole(name, permissions) {
        this.roles.set(name, {
            name: name,
            permissions: permissions,
            inherits: []
        });
    }
    
    // 角色继承
    addRoleInheritance(childRole, parentRole) {
        if (this.roles.has(childRole) && this.roles.has(parentRole)) {
            this.roles.get(childRole).inherits.push(parentRole);
        }
    }
    
    // 分配角色给用户
    assignRole(userId, roleName) {
        if (!this.userRoles.has(userId)) {
            this.userRoles.set(userId, []);
        }
        this.userRoles.get(userId).push(roleName);
    }
    
    // 检查用户权限
    hasPermission(userId, permission) {
        const userRoles = this.userRoles.get(userId) || [];
        
        for (const roleName of userRoles) {
            if (this.roleHasPermission(roleName, permission)) {
                return true;
            }
        }
        
        return false;
    }
    
    // 检查角色权限
    roleHasPermission(roleName, permission) {
        const role = this.roles.get(roleName);
        if (!role) return false;
        
        // 检查直接权限
        if (role.permissions.includes(permission)) {
            return true;
        }
        
        // 检查继承权限
        for (const parentRole of role.inherits) {
            if (this.roleHasPermission(parentRole, permission)) {
                return true;
            }
        }
        
        return false;
    }
}

// 权限中间件
const permissionMiddleware = (permission) => {
    return async (req, res, next) => {
        try {
            const token = req.headers.authorization?.replace('Bearer ', '');
            const decoded = jwtManager.verifyToken(token);
            
            if (!rbacManager.hasPermission(decoded.userId, permission)) {
                return res.status(403).json({
                    error: 'Insufficient permissions',
                    required: permission
                });
            }
            
            req.user = decoded;
            next();
        } catch (error) {
            res.status(401).json({ error: 'Unauthorized' });
        }
    };
};

3.2.2 权限配置

# 权限配置文件
permissions:
  # 用户管理权限
  user.create: "创建用户"
  user.read: "查看用户"
  user.update: "更新用户"
  user.delete: "删除用户"
  
  # 农场管理权限
  farm.create: "创建农场"
  farm.read: "查看农场"
  farm.update: "更新农场"
  farm.delete: "删除农场"
  
  # 动物管理权限
  animal.create: "添加动物"
  animal.read: "查看动物"
  animal.update: "更新动物信息"
  animal.delete: "删除动物"
  
  # 系统管理权限
  system.config: "系统配置"
  system.monitor: "系统监控"
  system.backup: "数据备份"

roles:
  # 超级管理员
  super_admin:
    permissions:
      - "*"  # 所有权限
  
  # 系统管理员
  admin:
    permissions:
      - "user.*"
      - "farm.*"
      - "animal.*"
      - "system.config"
      - "system.monitor"
  
  # 农场主
  farm_owner:
    permissions:
      - "farm.read"
      - "farm.update"
      - "animal.*"
  
  # 普通用户
  user:
    permissions:
      - "farm.read"
      - "animal.read"

4. 数据安全

4.1 数据加密

4.1.1 传输加密

# Nginx SSL配置
server {
    listen 443 ssl http2;
    server_name www.xlxumu.com;
    
    # SSL证书配置
    ssl_certificate /etc/letsencrypt/live/www.xlxumu.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.xlxumu.com/privkey.pem;
    
    # SSL安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # HSTS配置
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # 其他安全头
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';" always;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# 强制HTTPS重定向
server {
    listen 80;
    server_name www.xlxumu.com;
    return 301 https://$server_name$request_uri;
}

4.1.2 存储加密

// 数据库字段加密
const crypto = require('crypto');

class FieldEncryption {
    constructor() {
        this.algorithm = 'aes-256-gcm';
        this.keyLength = 32;
        this.ivLength = 16;
        this.tagLength = 16;
        this.masterKey = process.env.ENCRYPTION_MASTER_KEY;
    }
    
    // 生成数据加密密钥
    generateDataKey() {
        return crypto.randomBytes(this.keyLength);
    }
    
    // 加密数据
    encrypt(plaintext, dataKey) {
        const iv = crypto.randomBytes(this.ivLength);
        const cipher = crypto.createCipher(this.algorithm, dataKey, iv);
        
        let encrypted = cipher.update(plaintext, 'utf8', 'hex');
        encrypted += cipher.final('hex');
        
        const tag = cipher.getAuthTag();
        
        return {
            encrypted: encrypted,
            iv: iv.toString('hex'),
            tag: tag.toString('hex')
        };
    }
    
    // 解密数据
    decrypt(encryptedData, dataKey) {
        const decipher = crypto.createDecipher(
            this.algorithm,
            dataKey,
            Buffer.from(encryptedData.iv, 'hex')
        );
        
        decipher.setAuthTag(Buffer.from(encryptedData.tag, 'hex'));
        
        let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
        decrypted += decipher.final('utf8');
        
        return decrypted;
    }
    
    // 加密敏感字段
    encryptSensitiveFields(data, fields) {
        const dataKey = this.generateDataKey();
        const encryptedData = { ...data };
        
        fields.forEach(field => {
            if (data[field]) {
                encryptedData[field] = this.encrypt(data[field], dataKey);
            }
        });
        
        // 加密数据密钥
        encryptedData._dataKey = this.encryptDataKey(dataKey);
        
        return encryptedData;
    }
    
    // 解密敏感字段
    decryptSensitiveFields(encryptedData, fields) {
        const dataKey = this.decryptDataKey(encryptedData._dataKey);
        const data = { ...encryptedData };
        
        fields.forEach(field => {
            if (encryptedData[field]) {
                data[field] = this.decrypt(encryptedData[field], dataKey);
            }
        });
        
        delete data._dataKey;
        return data;
    }
    
    // 使用主密钥加密数据密钥
    encryptDataKey(dataKey) {
        const iv = crypto.randomBytes(this.ivLength);
        const cipher = crypto.createCipher(this.algorithm, this.masterKey, iv);
        
        let encrypted = cipher.update(dataKey, null, 'hex');
        encrypted += cipher.final('hex');
        
        const tag = cipher.getAuthTag();
        
        return {
            encrypted: encrypted,
            iv: iv.toString('hex'),
            tag: tag.toString('hex')
        };
    }
    
    // 使用主密钥解密数据密钥
    decryptDataKey(encryptedDataKey) {
        const decipher = crypto.createDecipher(
            this.algorithm,
            this.masterKey,
            Buffer.from(encryptedDataKey.iv, 'hex')
        );
        
        decipher.setAuthTag(Buffer.from(encryptedDataKey.tag, 'hex'));
        
        let decrypted = decipher.update(encryptedDataKey.encrypted, 'hex');
        decrypted += decipher.final();
        
        return decrypted;
    }
}

4.2 数据脱敏

// 数据脱敏工具
class DataMasking {
    // 手机号脱敏
    maskPhone(phone) {
        if (!phone || phone.length < 11) return phone;
        return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
    }
    
    // 身份证号脱敏
    maskIdCard(idCard) {
        if (!idCard || idCard.length < 15) return idCard;
        return idCard.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2');
    }
    
    // 邮箱脱敏
    maskEmail(email) {
        if (!email || !email.includes('@')) return email;
        const [username, domain] = email.split('@');
        const maskedUsername = username.length > 2 
            ? username.substring(0, 2) + '*'.repeat(username.length - 2)
            : username;
        return `${maskedUsername}@${domain}`;
    }
    
    // 银行卡号脱敏
    maskBankCard(cardNumber) {
        if (!cardNumber || cardNumber.length < 16) return cardNumber;
        return cardNumber.replace(/(\d{4})\d{8}(\d{4})/, '$1********$2');
    }
    
    // 姓名脱敏
    maskName(name) {
        if (!name || name.length < 2) return name;
        return name.charAt(0) + '*'.repeat(name.length - 1);
    }
    
    // 地址脱敏
    maskAddress(address) {
        if (!address || address.length < 10) return address;
        return address.substring(0, 6) + '*'.repeat(address.length - 6);
    }
    
    // 批量脱敏
    maskObject(obj, maskRules) {
        const masked = { ...obj };
        
        Object.keys(maskRules).forEach(field => {
            if (masked[field]) {
                const maskType = maskRules[field];
                switch (maskType) {
                    case 'phone':
                        masked[field] = this.maskPhone(masked[field]);
                        break;
                    case 'email':
                        masked[field] = this.maskEmail(masked[field]);
                        break;
                    case 'idCard':
                        masked[field] = this.maskIdCard(masked[field]);
                        break;
                    case 'bankCard':
                        masked[field] = this.maskBankCard(masked[field]);
                        break;
                    case 'name':
                        masked[field] = this.maskName(masked[field]);
                        break;
                    case 'address':
                        masked[field] = this.maskAddress(masked[field]);
                        break;
                }
            }
        });
        
        return masked;
    }
}

// 使用示例
const dataMasking = new DataMasking();

// API响应数据脱敏中间件
const maskingMiddleware = (maskRules) => {
    return (req, res, next) => {
        const originalSend = res.send;
        
        res.send = function(data) {
            if (typeof data === 'object' && data !== null) {
                if (Array.isArray(data)) {
                    data = data.map(item => dataMasking.maskObject(item, maskRules));
                } else {
                    data = dataMasking.maskObject(data, maskRules);
                }
            }
            
            originalSend.call(this, data);
        };
        
        next();
    };
};

4.3 数据备份与恢复

#!/bin/bash
# secure-backup.sh - 安全备份脚本

BACKUP_DIR="/secure-backup"
ENCRYPTION_KEY_FILE="/etc/backup-encryption.key"
DATE=$(date +%Y%m%d_%H%M%S)

# 创建加密密钥(首次运行)
create_encryption_key() {
    if [ ! -f "$ENCRYPTION_KEY_FILE" ]; then
        openssl rand -base64 32 > "$ENCRYPTION_KEY_FILE"
        chmod 600 "$ENCRYPTION_KEY_FILE"
        chown root:root "$ENCRYPTION_KEY_FILE"
    fi
}

# 加密备份文件
encrypt_backup() {
    local source_file=$1
    local encrypted_file="${source_file}.enc"
    
    openssl enc -aes-256-cbc -salt -in "$source_file" -out "$encrypted_file" -pass file:"$ENCRYPTION_KEY_FILE"
    
    if [ $? -eq 0 ]; then
        rm "$source_file"  # 删除明文备份
        echo "✅ 备份文件已加密: $encrypted_file"
    else
        echo "❌ 备份文件加密失败"
        return 1
    fi
}

# 解密备份文件
decrypt_backup() {
    local encrypted_file=$1
    local decrypted_file="${encrypted_file%.enc}"
    
    openssl enc -aes-256-cbc -d -in "$encrypted_file" -out "$decrypted_file" -pass file:"$ENCRYPTION_KEY_FILE"
    
    if [ $? -eq 0 ]; then
        echo "✅ 备份文件已解密: $decrypted_file"
    else
        echo "❌ 备份文件解密失败"
        return 1
    fi
}

# 安全备份主函数
secure_backup() {
    echo "开始安全备份: $DATE"
    
    # 创建备份目录
    mkdir -p "$BACKUP_DIR"
    
    # 创建加密密钥
    create_encryption_key
    
    # 备份数据库
    echo "备份数据库..."
    docker exec mysql-master mysqldump -u root -p${MYSQL_ROOT_PASSWORD} \
        --single-transaction \
        --routines \
        --triggers \
        --all-databases > "$BACKUP_DIR/mysql_backup_$DATE.sql"
    
    # 加密数据库备份
    encrypt_backup "$BACKUP_DIR/mysql_backup_$DATE.sql"
    
    # 备份配置文件
    echo "备份配置文件..."
    tar -czf "$BACKUP_DIR/config_backup_$DATE.tar.gz" ./config ./nginx .env.production
    encrypt_backup "$BACKUP_DIR/config_backup_$DATE.tar.gz"
    
    # 生成备份校验和
    echo "生成备份校验和..."
    find "$BACKUP_DIR" -name "*_$DATE.*.enc" -exec sha256sum {} \; > "$BACKUP_DIR/checksums_$DATE.txt"
    
    echo "安全备份完成"
}

# 验证备份完整性
verify_backup() {
    local checksum_file=$1
    
    if [ ! -f "$checksum_file" ]; then
        echo "校验和文件不存在: $checksum_file"
        return 1
    fi
    
    echo "验证备份完整性..."
    sha256sum -c "$checksum_file"
    
    if [ $? -eq 0 ]; then
        echo "✅ 备份完整性验证通过"
    else
        echo "❌ 备份完整性验证失败"
        return 1
    fi
}

# 主函数
case $1 in
    "backup")
        secure_backup
        ;;
    "decrypt")
        decrypt_backup $2
        ;;
    "verify")
        verify_backup $2
        ;;
    *)
        echo "使用方法: $0 {backup|decrypt <file>|verify <checksum_file>}"
        ;;
esac

5. 网络安全

5.1 防火墙配置

#!/bin/bash
# firewall-config.sh - 防火墙配置脚本

# 清空现有规则
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X

# 设置默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许SSH修改为非标准端口
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT

# 允许HTTP和HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 允许内网访问数据库端口
iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s 172.16.0.0/12 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.0.0/16 --dport 3306 -j ACCEPT

# 允许Redis访问
iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp -s 172.16.0.0/12 --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.0.0/16 --dport 6379 -j ACCEPT

# 防止DDoS攻击
iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

# 防止端口扫描
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A INPUT -m recent --name portscan --remove
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -j DROP

# 记录被丢弃的包
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# 保存规则
iptables-save > /etc/iptables/rules.v4

echo "防火墙配置完成"

5.2 入侵检测系统

# fail2ban配置
# /etc/fail2ban/jail.local
[DEFAULT]
# 禁用时间(秒)
bantime = 3600
# 查找时间窗口(秒)
findtime = 600
# 最大重试次数
maxretry = 3
# 忽略的IP地址
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

[nginx-botsearch]
enabled = true
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 7200

# 自定义过滤器
# /etc/fail2ban/filter.d/nginx-botsearch.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP.*" (404|444) .*$
ignoreregex =
#!/bin/bash
# intrusion-detection.sh - 入侵检测脚本

LOG_FILE="/var/log/intrusion-detection.log"
ALERT_EMAIL="security@xlxumu.com"

# 检查异常登录
check_suspicious_logins() {
    echo "检查异常登录..." | tee -a $LOG_FILE
    
    # 检查失败登录次数
    failed_logins=$(grep "Failed password" /var/log/auth.log | grep "$(date +%b\ %d)" | wc -l)
    if [ $failed_logins -gt 10 ]; then
        echo "警告: 今日失败登录次数过多 ($failed_logins)" | tee -a $LOG_FILE
        send_alert "异常登录检测" "今日失败登录次数: $failed_logins"
    fi
    
    # 检查异常IP
    suspicious_ips=$(grep "Failed password" /var/log/auth.log | grep "$(date +%b\ %d)" | awk '{print $11}' | sort | uniq -c | sort -nr | head -5)
    if [ ! -z "$suspicious_ips" ]; then
        echo "可疑IP地址:" | tee -a $LOG_FILE
        echo "$suspicious_ips" | tee -a $LOG_FILE
    fi
}

# 检查异常网络连接
check_network_connections() {
    echo "检查异常网络连接..." | tee -a $LOG_FILE
    
    # 检查大量连接的IP
    high_conn_ips=$(netstat -an | grep :80 | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10)
    echo "高连接数IP:" | tee -a $LOG_FILE
    echo "$high_conn_ips" | tee -a $LOG_FILE
    
    # 检查异常端口连接
    unusual_ports=$(netstat -tuln | grep -v -E "(22|80|443|3306|6379|27017)" | grep LISTEN)
    if [ ! -z "$unusual_ports" ]; then
        echo "异常监听端口:" | tee -a $LOG_FILE
        echo "$unusual_ports" | tee -a $LOG_FILE
        send_alert "异常端口检测" "发现异常监听端口: $unusual_ports"
    fi
}

# 检查文件完整性
check_file_integrity() {
    echo "检查文件完整性..." | tee -a $LOG_FILE
    
    # 检查关键系统文件
    critical_files=("/etc/passwd" "/etc/shadow" "/etc/ssh/sshd_config" "/etc/sudoers")
    
    for file in "${critical_files[@]}"; do
        if [ -f "$file" ]; then
            current_hash=$(sha256sum "$file" | awk '{print $1}')
            stored_hash_file="/var/lib/integrity/${file//\//_}.hash"
            
            if [ -f "$stored_hash_file" ]; then
                stored_hash=$(cat "$stored_hash_file")
                if [ "$current_hash" != "$stored_hash" ]; then
                    echo "警告: 文件 $file 已被修改" | tee -a $LOG_FILE
                    send_alert "文件完整性检测" "关键文件 $file 已被修改"
                fi
            else
                # 首次运行,存储哈希值
                mkdir -p "/var/lib/integrity"
                echo "$current_hash" > "$stored_hash_file"
            fi
        fi
    done
}

# 检查恶意进程
check_malicious_processes() {
    echo "检查恶意进程..." | tee -a $LOG_FILE
    
    # 检查高CPU使用率进程
    high_cpu_processes=$(ps aux --sort=-%cpu | head -10 | awk '$3 > 80 {print $2, $11}')
    if [ ! -z "$high_cpu_processes" ]; then
        echo "高CPU使用率进程:" | tee -a $LOG_FILE
        echo "$high_cpu_processes" | tee -a $LOG_FILE
    fi
    
    # 检查可疑进程名
    suspicious_processes=$(ps aux | grep -E "(nc|netcat|ncat|socat|wget|curl)" | grep -v grep)
    if [ ! -z "$suspicious_processes" ]; then
        echo "可疑进程:" | tee -a $LOG_FILE
        echo "$suspicious_processes" | tee -a $LOG_FILE
        send_alert "可疑进程检测" "发现可疑进程: $suspicious_processes"
    fi
}

# 发送告警
send_alert() {
    local subject=$1
    local message=$2
    
    # 发送邮件告警
    echo "$message" | mail -s "$subject" "$ALERT_EMAIL"
    
    # 发送钉钉告警
    curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
         -H 'Content-Type: application/json' \
         -d "{\"msgtype\": \"text\",\"text\": {\"content\": \"🚨 安全告警: $subject\\n$message\"}}"
}

# 主函数
main() {
    echo "=== 入侵检测开始 $(date) ===" | tee -a $LOG_FILE
    
    check_suspicious_logins
    check_network_connections
    check_file_integrity
    check_malicious_processes
    
    echo "=== 入侵检测完成 ===" | tee -a $LOG_FILE
}

main

6. 应用安全

6.1 输入验证与过滤

// 输入验证中间件
const validator = require('validator');
const xss = require('xss');

class InputValidator {
    // 通用验证规则
    static rules = {
        username: {
            required: true,
            minLength: 3,
            maxLength: 20,
            pattern: /^[a-zA-Z0-9_]+$/,
            message: '用户名只能包含字母、数字和下划线长度3-20位'
        },
        email: {
            required: true,
            validator: validator.isEmail,
            message: '请输入有效的邮箱地址'
        },
        phone: {
            required: true,
            pattern: /^1[3-9]\d{9}$/,
            message: '请输入有效的手机号码'
        },
        password: {
            required: true,
            minLength: 8,
            maxLength: 128,
            pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/,
            message: '密码必须包含大小写字母、数字和特殊字符长度8-128位'
        }
    };
    
    // 验证单个字段
    static validateField(value, rule) {
        const errors = [];
        
        // 必填验证
        if (rule.required && (!value || value.toString().trim() === '')) {
            errors.push('该字段为必填项');
            return errors;
        }
        
        if (!value) return errors;
        
        const stringValue = value.toString();
        
        // 长度验证
        if (rule.minLength && stringValue.length < rule.minLength) {
            errors.push(`最小长度为 ${rule.minLength}`);
        }
        
        if (rule.maxLength && stringValue.length > rule.maxLength) {
            errors.push(`最大长度为 ${rule.maxLength}`);
        }
        
        // 正则验证
        if (rule.pattern && !rule.pattern.test(stringValue)) {
            errors.push(rule.message || '格式不正确');
        }
        
        // 自定义验证器
        if (rule.validator && !rule.validator(stringValue)) {
            errors.push(rule.message || '验证失败');
        }
        
        return errors;
    }
    
    // 验证对象
    static validate(data, rules) {
        const errors = {};
        
        Object.keys(rules).forEach(field => {
            const fieldErrors = this.validateField(data[field], rules[field]);
            if (fieldErrors.length > 0) {
                errors[field] = fieldErrors;
            }
        });
        
        return {
            isValid: Object.keys(errors).length === 0,
            errors: errors
        };
    }
    
    // XSS过滤
    static sanitizeInput(input) {
        if (typeof input === 'string') {
            return xss(input, {
                whiteList: {}, // 不允许任何HTML标签
                stripIgnoreTag: true,
                stripIgnoreTagBody: ['script']
            });
        }
        
        if (typeof input === 'object' && input !== null) {
            const sanitized = {};
            Object.keys(input).forEach(key => {
                sanitized[key] = this.sanitizeInput(input[key]);
            });
            return sanitized;
        }
        
        return input;
    }
    
    // SQL注入防护
    static escapeSql(input) {
        if (typeof input === 'string') {
            return input.replace(/[\0\x08\x09\x1a\n\r"'\\\%]/g, function (char) {
                switch (char) {
                    case "\0":
                        return "\\0";
                    case "\x08":
                        return "\\b";
                    case "\x09":
                        return "\\t";
                    case "\x1a":
                        return "\\z";
                    case "\n":
                        return "\\n";
                    case "\r":
                        return "\\r";
                    case "\"":
                    case "'":
                    case "\\":
                    case "%":
                        return "\\" + char;
                    default:
                        return char;
                }
            });
        }
        return input;
    }
}

// 验证中间件
const validationMiddleware = (rules) => {
    return (req, res, next) => {
        // XSS过滤
        req.body = InputValidator.sanitizeInput(req.body);
        req.query = InputValidator.sanitizeInput(req.query);
        req.params = InputValidator.sanitizeInput(req.params);
        
        // 输入验证
        const validation = InputValidator.validate(req.body, rules);
        
        if (!validation.isValid) {
            return res.status(400).json({
                error: 'Validation failed',
                details: validation.errors
            });
        }
        
        next();
    };
};

6.2 API安全

// API安全中间件
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const cors = require('cors');

// 速率限制
const createRateLimit = (windowMs, max, message) => {
    return rateLimit({
        windowMs: windowMs,
        max: max,
        message: {
            error: 'Too many requests',
            message: message,
            retryAfter: Math.ceil(windowMs / 1000)
        },
        standardHeaders: true,
        legacyHeaders: false,
        // 自定义键生成器基于IP和用户ID
        keyGenerator: (req) => {
            return req.user ? `${req.ip}-${req.user.id}` : req.ip;
        },
        // 跳过成功的请求
        skipSuccessfulRequests: true
    });
};

// 不同类型的速率限制
const rateLimits = {
    // 通用API限制
    general: createRateLimit(15 * 60 * 1000, 100, '请求过于频繁,请稍后再试'),
    
    // 登录限制
    auth: createRateLimit(15 * 60 * 1000, 5, '登录尝试过于频繁请15分钟后再试'),
    
    // 注册限制
    register: createRateLimit(60 * 60 * 1000, 3, '注册请求过于频繁请1小时后再试'),
    
    // 密码重置限制
    passwordReset: createRateLimit(60 * 60 * 1000, 3, '密码重置请求过于频繁请1小时后再试'),
    
    // 文件上传限制
    upload: createRateLimit(60 * 60 * 1000, 10, '文件上传过于频繁请1小时后再试')
};

// CORS配置
const corsOptions = {
    origin: function (origin, callback) {
        const allowedOrigins = [
            'https://www.xlxumu.com',
            'https://admin.xlxumu.com',
            'https://api.xlxumu.com'
        ];
        
        // 允许移动应用和开发环境
        if (!origin || allowedOrigins.includes(origin) || 
            (process.env.NODE_ENV === 'development' && origin.includes('localhost'))) {
            callback(null, true);
        } else {
            callback(new Error('Not allowed by CORS'));
        }
    },
    credentials: true,
    optionsSuccessStatus: 200,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
};

// 安全头配置
const helmetOptions = {
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'"],
            scriptSrc: ["'self'"],
            imgSrc: ["'self'", "data:", "https:"],
            connectSrc: ["'self'"],
            fontSrc: ["'self'"],
            objectSrc: ["'none'"],
            mediaSrc: ["'self'"],
            frameSrc: ["'none'"]
        }
    },
    hsts: {
        maxAge: 31536000,
        includeSubDomains: true,
        preload: true
    }
};

// API安全中间件组合
const apiSecurity = (app) => {
    // 基础安全头
    app.use(helmet(helmetOptions));
    
    // CORS配置
    app.use(cors(corsOptions));
    
    // 通用速率限制
    app.use('/api/', rateLimits.general);
    
    // 特定路由的速率限制
    app.use('/api/auth/login', rateLimits.auth);
    app.use('/api/auth/register', rateLimits.register);
    app.use('/api/auth/reset-password', rateLimits.passwordReset);
    app.use('/api/upload', rateLimits.upload);
    
    // 请求大小限制
    app.use(express.json({ limit: '10mb' }));
    app.use(express.urlencoded({ extended: true, limit: '10mb' }));
    
    // 隐藏技术栈信息
    app.disable('x-powered-by');
    
    // API版本控制
    app.use('/api/v1', require('./routes/v1'));
    
    // 404处理
    app.use('/api/*', (req, res) => {
        res.status(404).json({
            error: 'API endpoint not found',
            path: req.path,
            method: req.method
        });
    });
    
    // 错误处理
    app.use((error, req, res, next) => {
        // 记录错误日志
        console.error('API Error:', {
            error: error.message,
            stack: error.stack,
            url: req.url,
            method: req.method,
            ip: req.ip,
            userAgent: req.get('User-Agent')
        });
        
        // 不暴露内部错误信息
        if (process.env.NODE_ENV === 'production') {
            res.status(500).json({
                error: 'Internal server error',
                message: 'Something went wrong'
            });
        } else {
            res.status(500).json({
                error: error.message,
                stack: error.stack
            });
        }
    });
};

6.3 文件上传安全

// 文件上传安全配置
const multer = require('multer');
const path = require('path');
const crypto = require('crypto');
const sharp = require('sharp');

class SecureFileUpload {
    constructor() {
        this.allowedMimeTypes = {
            image: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
            document: ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
            excel: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
        };
        
        this.maxFileSizes = {
            image: 5 * 1024 * 1024, // 5MB
            document: 10 * 1024 * 1024, // 10MB
            excel: 20 * 1024 * 1024 // 20MB
        };
        
        this.uploadDir = './uploads';
        this.quarantineDir = './quarantine';
    }
    
    // 文件类型检测
    detectFileType(buffer) {
        // 检查文件头魔数
        const signatures = {
            'image/jpeg': [0xFF, 0xD8, 0xFF],
            'image/png': [0x89, 0x50, 0x4E, 0x47],
            'image/gif': [0x47, 0x49, 0x46],
            'application/pdf': [0x25, 0x50, 0x44, 0x46]
        };
        
        for (const [mimeType, signature] of Object.entries(signatures)) {
            if (this.checkSignature(buffer, signature)) {
                return mimeType;
            }
        }
        
        return null;
    }
    
    // 检查文件签名
    checkSignature(buffer, signature) {
        if (buffer.length < signature.length) return false;
        
        for (let i = 0; i < signature.length; i++) {
            if (buffer[i] !== signature[i]) return false;
        }
        
        return true;
    }
    
    // 文件名安全化
    sanitizeFilename(filename) {
        // 移除危险字符
        const sanitized = filename.replace(/[^a-zA-Z0-9.-]/g, '_');
        
        // 生成唯一文件名
        const ext = path.extname(sanitized);
        const name = path.basename(sanitized, ext);
        const hash = crypto.randomBytes(8).toString('hex');
        
        return `${name}_${hash}${ext}`;
    }
    
    // 病毒扫描集成ClamAV
    async scanForVirus(filePath) {
        return new Promise((resolve, reject) => {
            const { exec } = require('child_process');
            
            exec(`clamscan --no-summary ${filePath}`, (error, stdout, stderr) => {
                if (error) {
                    if (error.code === 1) {
                        // 发现病毒
                        resolve({ infected: true, virus: stdout.trim() });
                    } else {
                        // 扫描错误
                        reject(new Error('Virus scan failed'));
                    }
                } else {
                    // 文件安全
                    resolve({ infected: false });
                }
            });
        });
    }
    
    // 图片安全处理
    async processImage(inputPath, outputPath) {
        try {
            // 使用sharp重新处理图片移除EXIF数据
            await sharp(inputPath)
                .jpeg({ quality: 90, progressive: true })
                .png({ compressionLevel: 9 })
                .removeAlpha()
                .toFile(outputPath);
            
            return true;
        } catch (error) {
            console.error('Image processing failed:', error);
            return false;
        }
    }
    
    // 创建安全的multer配置
    createMulterConfig(fileType) {
        const storage = multer.diskStorage({
            destination: (req, file, cb) => {
                cb(null, this.uploadDir);
            },
            filename: (req, file, cb) => {
                const safeFilename = this.sanitizeFilename(file.originalname);
                cb(null, safeFilename);
            }
        });
        
        const fileFilter = (req, file, cb) => {
            // 检查MIME类型
            if (!this.allowedMimeTypes[fileType].includes(file.mimetype)) {
                return cb(new Error(`不支持的文件类型: ${file.mimetype}`));
            }
            
            cb(null, true);
        };
        
        return multer({
            storage: storage,
            limits: {
                fileSize: this.maxFileSizes[fileType],
                files: 5 // 最多5个文件
            },
            fileFilter: fileFilter
        });
    }
    
    // 文件上传后处理
    async postProcessFile(file) {
        const filePath = file.path;
        
        try {
            // 1. 检查文件头
            const buffer = require('fs').readFileSync(filePath);
            const detectedType = this.detectFileType(buffer);
            
            if (!detectedType || detectedType !== file.mimetype) {
                throw new Error('文件类型不匹配');
            }
            
            // 2. 病毒扫描
            const scanResult = await this.scanForVirus(filePath);
            if (scanResult.infected) {
                // 移动到隔离区
                const quarantinePath = path.join(this.quarantineDir, file.filename);
                require('fs').renameSync(filePath, quarantinePath);
                throw new Error(`检测到病毒: ${scanResult.virus}`);
            }
            
            // 3. 图片特殊处理
            if (file.mimetype.startsWith('image/')) {
                const processedPath = filePath + '.processed';
                const success = await this.processImage(filePath, processedPath);
                
                if (success) {
                    require('fs').renameSync(processedPath, filePath);
                } else {
                    throw new Error('图片处理失败');
                }
            }
            
            return {
                success: true,
                file: {
                    filename: file.filename,
                    originalname: file.originalname,
                    mimetype: file.mimetype,
                    size: file.size,
                    path: filePath
                }
            };
            
        } catch (error) {
            // 删除有问题的文件
            if (require('fs').existsSync(filePath)) {
                require('fs').unlinkSync(filePath);
            }
            
            throw error;
        }
    }
}

// 使用示例
const secureUpload = new SecureFileUpload();

// 图片上传路由
app.post('/api/upload/image', 
    secureUpload.createMulterConfig('image').single('image'),
    async (req, res) => {
        try {
            if (!req.file) {
                return res.status(400).json({ error: '没有上传文件' });
            }
            
            const result = await secureUpload.postProcessFile(req.file);
            res.json(result);
            
        } catch (error) {
            res.status(400).json({ error: error.message });
        }
    }
);

7. 安全监控与审计

7.1 安全日志记录

// 安全审计日志
class SecurityAuditLogger {
    constructor() {
        this.winston = require('winston');
        this.logger = this.winston.createLogger({
            level: 'info',
            format: this.winston.format.combine(
                this.winston.format.timestamp(),
                this.winston.format.json()
            ),
            transports: [
                new this.winston.transports.File({ 
                    filename: '/var/log/security/security-audit.log',
                    maxsize: 100 * 1024 * 1024, // 100MB
                    maxFiles: 10
                }),
                new this.winston.transports.Console({
                    format: this.winston.format.simple()
                })
            ]
        });
    }
    
    // 记录认证事件
    logAuthEvent(event, userId, ip, userAgent, success, details = {}) {
        this.logger.info('AUTH_EVENT', {
            event: event,
            userId: userId,
            ip: ip,
            userAgent: userAgent,
            success: success,
            timestamp: new Date().toISOString(),
            details: details
        });
    }
    
    // 记录权限事件
    logPermissionEvent(userId, resource, action, granted, ip) {
        this.logger.info('PERMISSION_EVENT', {
            userId: userId,
            resource: resource,
            action: action,
            granted: granted,
            ip: ip,
            timestamp: new Date().toISOString()
        });
    }
    
    // 记录数据访问事件
    logDataAccess(userId, dataType, recordId, action, ip) {
        this.logger.info('DATA_ACCESS', {
            userId: userId,
            dataType: dataType,
            recordId: recordId,
            action: action,
            ip: ip,
            timestamp: new Date().toISOString()
        });
    }
    
    // 记录安全事件
    logSecurityEvent(eventType, severity, description, ip, details = {}) {
        this.logger.warn('SECURITY_EVENT', {
            eventType: eventType,
            severity: severity,
            description: description,
            ip: ip,
            timestamp: new Date().toISOString(),
            details: details
        });
    }
    
    // 记录系统事件
    logSystemEvent(eventType, description, details = {}) {
        this.logger.info('SYSTEM_EVENT', {
            eventType: eventType,
            description: description,
            timestamp: new Date().toISOString(),
            details: details
        });
    }
}

// 审计中间件
const auditMiddleware = (auditLogger) => {
    return (req, res, next) => {
        const startTime = Date.now();
        
        // 记录请求开始
        const requestId = require('crypto').randomUUID();
        req.requestId = requestId;
        
        // 重写res.json以记录响应
        const originalJson = res.json;
        res.json = function(data) {
            const endTime = Date.now();
            const duration = endTime - startTime;
            
            // 记录API访问
            auditLogger.logger.info('API_ACCESS', {
                requestId: requestId,
                method: req.method,
                url: req.url,
                ip: req.ip,
                userAgent: req.get('User-Agent'),
                userId: req.user?.id,
                statusCode: res.statusCode,
                duration: duration,
                timestamp: new Date().toISOString()
            });
            
            // 记录敏感操作
            if (['POST', 'PUT', 'DELETE'].includes(req.method)) {
                auditLogger.logDataAccess(
                    req.user?.id,
                    req.url.split('/')[2], // 提取资源类型
                    req.params.id,
                    req.method,
                    req.ip
                );
            }
            
            return originalJson.call(this, data);
        };
        
        next();
    };
};

7.2 实时安全监控

// 实时安全监控系统
class SecurityMonitor {
    constructor() {
        this.redis = require('redis').createClient();
        this.alerts = [];
        this.thresholds = {
            failedLogins: { count: 5, window: 300 }, // 5分钟内5次失败
            apiCalls: { count: 1000, window: 60 }, // 1分钟内1000次调用
            dataAccess: { count: 100, window: 300 } // 5分钟内100次数据访问
        };
    }
    
    // 检查失败登录
    async checkFailedLogins(ip) {
        const key = `failed_logins:${ip}`;
        const count = await this.redis.incr(key);
        
        if (count === 1) {
            await this.redis.expire(key, this.thresholds.failedLogins.window);
        }
        
        if (count >= this.thresholds.failedLogins.count) {
            this.triggerAlert('FAILED_LOGIN_THRESHOLD', {
                ip: ip,
                count: count,
                threshold: this.thresholds.failedLogins.count
            });
        }
    }
    
    // 检查API调用频率
    async checkApiCalls(userId, endpoint) {
        const key = `api_calls:${userId}:${endpoint}`;
        const count = await this.redis.incr(key);
        
        if (count === 1) {
            await this.redis.expire(key, this.thresholds.apiCalls.window);
        }
        
        if (count >= this.thresholds.apiCalls.count) {
            this.triggerAlert('API_RATE_LIMIT', {
                userId: userId,
                endpoint: endpoint,
                count: count,
                threshold: this.thresholds.apiCalls.count
            });
        }
    }
    
    // 触发安全告警
    triggerAlert(alertType, data) {
        const alert = {
            id: require('crypto').randomUUID(),
            type: alertType,
            timestamp: new Date().toISOString(),
            data: data,
            severity: this.getAlertSeverity(alertType)
        };
        
        this.alerts.push(alert);
        this.sendAlert(alert);
    }
    
    // 获取告警严重程度
    getAlertSeverity(alertType) {
        const severityMap = {
            'FAILED_LOGIN_THRESHOLD': 'HIGH',
            'API_RATE_LIMIT': 'MEDIUM',
            'SUSPICIOUS_ACTIVITY': 'HIGH',
            'DATA_BREACH_ATTEMPT': 'CRITICAL'
        };
        
        return severityMap[alertType] || 'LOW';
    }
    
    // 发送告警
    async sendAlert(alert) {
        // 发送到监控系统
        console.log('🚨 安全告警:', alert);
        
        // 发送邮件通知
        if (alert.severity === 'CRITICAL' || alert.severity === 'HIGH') {
            await this.sendEmailAlert(alert);
        }
        
        // 发送钉钉通知
        await this.sendDingTalkAlert(alert);
        
        // 记录到数据库
        await this.saveAlertToDatabase(alert);
    }
}

7.3 安全事件响应

#!/bin/bash
# security-incident-response.sh - 安全事件响应脚本

INCIDENT_LOG="/var/log/security/incidents.log"
BACKUP_DIR="/secure-backup/incident-$(date +%Y%m%d_%H%M%S)"

# 事件响应等级
declare -A RESPONSE_LEVELS=(
    ["LOW"]="记录日志"
    ["MEDIUM"]="通知管理员"
    ["HIGH"]="立即响应"
    ["CRITICAL"]="紧急响应"
)

# 记录安全事件
log_incident() {
    local severity=$1
    local event_type=$2
    local description=$3
    local affected_systems=$4
    
    echo "$(date '+%Y-%m-%d %H:%M:%S') [$severity] $event_type: $description (影响系统: $affected_systems)" >> $INCIDENT_LOG
}

# 隔离受影响系统
isolate_system() {
    local system_ip=$1
    
    echo "隔离系统: $system_ip"
    
    # 阻止该IP的所有连接
    iptables -I INPUT -s $system_ip -j DROP
    iptables -I OUTPUT -d $system_ip -j DROP
    
    # 记录隔离操作
    log_incident "HIGH" "SYSTEM_ISOLATION" "系统已被隔离" "$system_ip"
}

# 紧急备份
emergency_backup() {
    echo "执行紧急备份..."
    
    mkdir -p $BACKUP_DIR
    
    # 备份关键数据
    docker exec mysql-master mysqldump -u root -p${MYSQL_ROOT_PASSWORD} --all-databases > $BACKUP_DIR/emergency_db_backup.sql
    
    # 备份配置文件
    cp -r ./config $BACKUP_DIR/
    cp -r ./nginx $BACKUP_DIR/
    
    # 备份日志文件
    cp -r /var/log $BACKUP_DIR/
    
    echo "紧急备份完成: $BACKUP_DIR"
}

# 收集取证信息
collect_forensics() {
    local incident_id=$1
    local forensics_dir="/var/log/security/forensics/$incident_id"
    
    mkdir -p $forensics_dir
    
    echo "收集取证信息..."
    
    # 系统信息
    uname -a > $forensics_dir/system_info.txt
    ps aux > $forensics_dir/processes.txt
    netstat -tuln > $forensics_dir/network_connections.txt
    
    # 用户信息
    who > $forensics_dir/logged_users.txt
    last -n 50 > $forensics_dir/login_history.txt
    
    # 文件系统信息
    find /tmp -type f -mtime -1 > $forensics_dir/recent_tmp_files.txt
    find /var/log -name "*.log" -mtime -1 -exec ls -la {} \; > $forensics_dir/recent_logs.txt
    
    # 网络流量
    tcpdump -i any -w $forensics_dir/network_traffic.pcap -c 1000 &
    
    echo "取证信息收集完成: $forensics_dir"
}

# 事件响应主函数
incident_response() {
    local severity=$1
    local event_type=$2
    local description=$3
    local affected_systems=$4
    
    local incident_id="INC-$(date +%Y%m%d%H%M%S)"
    
    echo "=== 安全事件响应开始 ==="
    echo "事件ID: $incident_id"
    echo "严重程度: $severity"
    echo "事件类型: $event_type"
    echo "描述: $description"
    echo "影响系统: $affected_systems"
    
    # 记录事件
    log_incident $severity $event_type "$description" "$affected_systems"
    
    # 根据严重程度执行响应
    case $severity in
        "CRITICAL")
            echo "执行紧急响应..."
            emergency_backup
            collect_forensics $incident_id
            isolate_system $affected_systems
            send_critical_alert "$incident_id" "$description"
            ;;
        "HIGH")
            echo "执行高级响应..."
            collect_forensics $incident_id
            send_high_alert "$incident_id" "$description"
            ;;
        "MEDIUM")
            echo "执行中级响应..."
            send_medium_alert "$incident_id" "$description"
            ;;
        "LOW")
            echo "记录低级事件..."
            ;;
    esac
    
    echo "=== 安全事件响应完成 ==="
}

# 发送告警通知
send_critical_alert() {
    local incident_id=$1
    local description=$2
    
    # 发送邮件
    echo "🚨 紧急安全事件 - $incident_id: $description" | mail -s "紧急安全告警" security@xlxumu.com
    
    # 发送短信(集成短信服务)
    curl -X POST "https://sms-api.example.com/send" \
         -H "Authorization: Bearer $SMS_TOKEN" \
         -d "phone=13800138000&message=紧急安全事件: $incident_id"
    
    # 发送钉钉通知
    curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=$DINGTALK_TOKEN" \
         -H 'Content-Type: application/json' \
         -d "{\"msgtype\": \"text\",\"text\": {\"content\": \"🚨 紧急安全事件\\n事件ID: $incident_id\\n描述: $description\\n请立即处理\"}}"
}

# 使用示例
case $1 in
    "test")
        incident_response "HIGH" "INTRUSION_ATTEMPT" "检测到入侵尝试" "192.168.1.100"
        ;;
    "isolate")
        isolate_system $2
        ;;
    "backup")
        emergency_backup
        ;;
    "forensics")
        collect_forensics $2
        ;;
    *)
        echo "使用方法: $0 {test|isolate <ip>|backup|forensics <incident_id>}"
        ;;
esac

8. 安全培训与意识

8.1 安全培训计划

培训对象 培训内容 频率 时长
开发人员 安全编码、OWASP Top 10、代码审计 季度 4小时
运维人员 系统安全、网络安全、应急响应 季度 6小时
管理人员 安全管理、合规要求、风险评估 半年 2小时
全体员工 安全意识、钓鱼邮件识别、密码安全 月度 1小时

8.2 安全检查清单

8.2.1 日常安全检查

  • 检查系统补丁更新状态
  • 审查用户权限分配
  • 检查防火墙规则
  • 监控异常登录活动
  • 验证备份完整性
  • 检查SSL证书有效期
  • 审查安全日志
  • 测试入侵检测系统

8.2.2 月度安全评估

  • 漏洞扫描
  • 渗透测试
  • 代码安全审计
  • 权限审计
  • 安全配置检查
  • 应急预案演练
  • 安全培训效果评估
  • 合规性检查

9. 应急预案

9.1 数据泄露应急预案

flowchart TD
    A[发现数据泄露] --> B[立即隔离]
    B --> C[评估影响范围]
    C --> D[通知相关人员]
    D --> E[收集证据]
    E --> F[修复漏洞]
    F --> G[恢复服务]
    G --> H[事后分析]
    H --> I[改进措施]

9.2 系统入侵应急预案

  1. 发现阶段

    • 监控系统告警
    • 异常行为检测
    • 用户举报
  2. 响应阶段

    • 立即隔离受影响系统
    • 保护现场证据
    • 通知安全团队
  3. 恢复阶段

    • 清除恶意代码
    • 修复安全漏洞
    • 恢复正常服务
  4. 总结阶段

    • 事件分析报告
    • 改进安全措施
    • 更新应急预案

10. 总结

10.1 安全管理要点

  1. 全面防护:从网络、系统、应用、数据多个层面构建安全防护体系
  2. 持续监控建立7×24小时安全监控和告警机制
  3. 快速响应:制定完善的安全事件响应流程和应急预案
  4. 定期评估:定期进行安全评估和渗透测试
  5. 人员培训:提高全员安全意识和技能水平

10.2 安全发展规划

  1. 短期目标1-3个月

    • 完善基础安全防护
    • 建立安全监控体系
    • 制定安全管理制度
  2. 中期目标3-6个月

    • 实施零信任架构
    • 建立安全运营中心
    • 完善应急响应能力
  3. 长期目标6-12个月

    • 通过等保2.0认证
    • 建立安全文化
    • 实现自动化安全运营

10.3 联系方式


本文档将根据安全威胁变化和业务发展需要持续更新