攻击面总览

flowchart TD
    subgraph Internet[互联网]
        ATK[攻击者]
    end

    subgraph VPS[VPS 服务器]
        subgraph NginxLayer[Nginx 反向代理]
            NG80[端口 80]
            NG443[端口 443]
        end

        subgraph FW[防火墙 - ufw]
            FW22[22 SSH]
            FW80[80 HTTP]
            FW443[443 HTTPS]
        end

        subgraph Container[Docker 容器]
            AstrBot
            NapCat
        end

        AstrBot --> Config[cmd_config.json<br>API Keys / Secrets]
        NapCat --> QQData[QQ 登录缓存<br>会话凭证]
    end

    ATK -.->|扫描| NG443
    ATK -.->|爆破| AstrBot
    ATK -.->|弱Token| NapCat

第二章:AstrBot 安全加固

修改默认密码

AstrBot 首次安装的默认密码为 astrbot / astrbot,必须立即修改。

在 WebUI 右上角头像 -> 修改密码,或直接编辑配置文件:

{
  "dashboard": {
    "username": "your-admin-user",
    "password": "md5_hashed_password",
    "password_change_required": true
  }
}

开启 TOTP 两步验证

AstrBot 支持 TOTP(基于时间的一次性密码),在 WebUI -> 设置中启用。配合 Authenticator App 使用。

最小权限原则

{
  "admins_id": ["仅你的QQ号"],
  "enable_id_white_list": true,
  "id_whitelist": ["仅允许的QQ号群组"]
}

配置安全选项

{
  "platform_settings": {
    "enable_id_white_list": true,
    "wl_ignore_admin_on_group": true,
    "wl_ignore_admin_on_friend": true
  },
  "provider_settings": {
    "llm_safety_mode": true,
    "safety_mode_strategy": "system_prompt"
  },
  "content_safety": {
    "also_use_in_response": true,
    "internal_keywords": {
      "enable": true,
      "extra_keywords": ["敏感词列表"]
    }
  }
}

API Key 保护

  • DeepSeek/OpenAI API Key 明文存储在 cmd_config.json 中,必须限制该文件的访问权限
  • 不要在日志中输出 API Key
  • 在 DeepSeek 控制台设置用量上限告警阈值,防止被滥用产生高额费用
# 限制配置文件权限
chmod 600 /root/astrbot/data/cmd_config.json
chown root:root /root/astrbot/data/cmd_config.json

第四章:Nginx 安全加固

安全头配置

server {
    listen 443 ssl;
    server_name bot.yourdomain.com;
 
    # SSL 配置
    ssl_certificate /path/to/fullchain.cer;
    ssl_certificate_key /path/to/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
 
    # 安全头
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
 
    # 隐藏 Nginx 版本
    server_tokens off;
 
    # 请求大小限制(防止大 payload 攻击)
    client_max_body_size 10M;
 
    location / {
        proxy_pass http://127.0.0.1:6185;
        # ... 其他配置
    }
}

屏蔽非目标域名的访问

server {
    listen 443 ssl;
    server_name _;  # 未匹配的域名
    return 444;     # 直接断开连接,不响应
}

限流配置

# 在 http 块中定义限流区域
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
 
# 在 location 中应用
location /login {
    limit_req zone=login burst=2 nodelay;
    proxy_pass http://127.0.0.1:6185;
}

日志监控

# 自定义日志格式
log_format security '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent"';
 
# 启用访问日志
access_log /var/log/nginx/bot_access.log security;

配置日志轮转:

cat > /etc/logrotate.d/nginx-bot << 'EOF'
/var/log/nginx/bot_*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    sharedscripts
    postrotate
        systemctl reload nginx
    endscript
}
EOF

第六章:操作系统安全

自动安全更新

apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades

监控与告警

简单的日志监控脚本:

#!/bin/bash
# /usr/local/bin/security_check.sh
 
# 检查失败的 SSH 登录
FAILED_SSH=$(grep "Failed password" /var/log/auth.log | wc -l)
if [ $FAILED_SSH -gt 10 ]; then
    echo "警告: 检测到 $FAILED_SSH 次失败的 SSH 登录" | mail -s "安全告警" your@email.com
fi
 
# 检查 Docker 容器状态
for container in napcat astrbot; do
    if ! docker ps --format '{{.Names}}' | grep -q $container; then
        echo "警告: 容器 $container 未运行" | mail -s "服务告警" your@email.com
    fi
done

添加到 cron:

*/30 * * * * /usr/local/bin/security_check.sh

相关知识点