iDev1ce/project_s
GitHub: iDev1ce/project_s
一款将网络安全威胁情报报告自动转换为 STIX 2.1 Bundle 的自动化工具。
Stars: 0 | Forks: 0
# 报告转 STIX Bundle 生成器
通过 Web UI、FastAPI 后端和基于 Docker 的部署,将网络安全威胁情报报告转换为 **STIX 2.1 bundles**。
## 功能
该应用按四个阶段处理报告:
1. **提取代理(Extractor agent)**:从源文档构建初步结构化表示。
2. **验证代理(Verifier agent)**:移除不支持的项目,增强证据与上下文,保留支持的语义实体。
3. **关系构建器(Relationship builder)**:在验证后添加确定性关系。
4. **STIX 导出器(STIX exporter)**:将结果序列化为 STIX 2.1 JSON Bundle。
Web 应用允许用户上传报告并下载生成的 STIX Bundle。
## 特性
- 提取:
- 文件哈希
- IPv4 地址
- 域名
- 恶意软件
- 攻击模式
- 威胁行为者
- 行动
- 战役
- 从最终指标中过滤良性/引用/公共服务域名
- 在验证后添加确定性关系
- 导出有效的 STIX 2.1 JSON Bundle
- 通过单一同源反向代理支持浏览器上传
- 支持 Docker Compose 部署
- 使用 Let's Encrypt IP 证书在公网上支持 HTTPS
## 架构
### 处理流水线
```
Document
-> Extractor Agent
-> Verifier Agent
-> Relationship Builder
-> STIX Exporter
-> STIX 2.1 JSON bundle
```
### Web 技术栈
```
Browser
-> Nginx :80 / :443
-> / frontend
-> /api/* FastAPI
-> process_report(...)
-> STIX bundle response
```
因为前端与 API 服务于同一反向代理之后,浏览器使用单一同源并避免了 CORS 问题。
## 仓库结构
```
project_s/
docker-compose.yml
.env
pyproject.toml
uv.lock
README.md
api/
Dockerfile
frontend/
index.html
nginx/
default.conf.template
src/
project_s/
app.py
pipeline.py
config.py
main.py
agents/
tools/
models/
```
## 要求
- Python 3.11+ 或 3.12+
- `uv`
- Docker + Docker Compose
- Nginx 容器
- 有效的 OpenAI API 密钥
- 公网 IP 地址(若使用 Let's Encrypt IP 证书)
- 对端口 **80** 和 **443** 的公网入站访问
## 环境配置
在项目根目录创建 `.env` 文件:
```
OPENAI_API_KEY=replace_me
SERVER_IP=replace_with_public_ip
STIX_OUTPUT_DIR=/tmp/stix
```
### 变量
- `OPENAI_API_KEY`
用于模型支持的提取/验证流程。
- `SERVER_IP`
用于 Nginx 配置模板与证书路径。
- `STIX_OUTPUT_DIR`
生成的 STIX Bundle 输出目录。
## 本地开发
安装依赖:
```
uv sync
```
运行 API:
```
uv run uvicorn project_s.app:app --host 0.0.0.0 --port 8000
```
运行 CLI:
```
uv run python -m project_s.main convert /path/to/report.pdf --output-name stix_bundle_final.json
```
## FastAPI 端点
### POST /api/convert
**请求**
- `multipart/form-data`
- 字段名:`file`
**响应**
- 生成的 STIX 2.1 JSON Bundle
前端使用同源路径:
```
fetch('/api/convert', {
method: 'POST',
body: formData,
})
```
## Docker 部署
构建并启动服务栈:
```
docker compose up -d --build
```
检查状态:
```
docker compose ps
```
检查日志:
```
docker compose logs -f api
docker compose logs -f nginx
```
打开站点:
```
http://
```
若已配置 HTTPS:
```
https://
```
## Nginx
本项目使用 Nginx 配置模板,使反向代理能够在启动时从 Docker Compose 读取 `SERVER_IP`。
### `nginx/default.conf.template`
```
server {
listen 80;
server_name ${SERVER_IP};
location /.well-known/acme-challenge/ {
root /srv;
}
location / {
return 301 https://${SERVER_IP}$request_uri;
}
}
server {
listen 443 ssl http2;
server_name ${SERVER_IP};
ssl_certificate /etc/letsencrypt/live/${SERVER_IP}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${SERVER_IP}/privkey.pem;
client_max_body_size 100M;
location /api/ {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
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;
}
location / {
root /srv;
try_files $uri /index.html;
}
}
```
### 重要说明
保持以下格式:
```
proxy_pass http://api:8000;
```
不要在此处添加尾部斜杠,否则上游路径处理可能会改变。
## Docker Compose
典型的 Compose 配置:
```
version: "3.9"
services:
api:
build:
context: .
dockerfile: api/Dockerfile
container_name: stix-api
restart: unless-stopped
expose:
- "8000"
environment:
PYTHONPATH: /app/src
OPENAI_API_KEY: ${OPENAI_API_KEY}
STIX_OUTPUT_DIR: ${STIX_OUTPUT_DIR}
volumes:
- ./src:/app/src:z
nginx:
image: nginx:alpine
container_name: stix-nginx
restart: unless-stopped
depends_on:
- api
ports:
- "80:80"
- "443:443"
environment:
SERVER_IP: ${SERVER_IP}
volumes:
- ./frontend:/srv:ro,z
- ./nginx/default.conf.template:/etc/nginx/templates/default.conf.template:ro,z
- /etc/letsencrypt:/etc/letsencrypt:ro,z
```
若主机启用了 SELinux,建议添加 `:z` 后缀以支持绑定挂载。
## Let's Encrypt IP 证书
该部署使用 **Let's Encrypt IP 证书** 与 Nginx。
### 要求
- 公网 IP
- 端口 **80** 可从互联网访问
- 端口 **443** 可从互联网访问
- Certbot 版本足够新以支持 IP 证书
### 生成证书
临时停止 Nginx 以便 Certbot 绑定端口 80:
```
docker compose stop nginx
```
首先申请测试证书:
```
sudo certbot certonly --staging \
--preferred-profile shortlived \
--standalone \
--ip-address "${SERVER_IP}"
```
然后申请正式证书:
```
sudo certbot certonly \
--preferred-profile shortlived \
--standalone \
--ip-address "${SERVER_IP}"
```
若未在 Shell 中导出 `SERVER_IP`,请在运行命令时替换为实际公网 IP。
签发文件通常存储于:
```
/etc/letsencrypt/live//fullchain.pem
/etc/letsencrypt/live//privkey.pem
```
签发完成后重新启动服务栈:
```
docker compose up -d --build
```
测试 HTTPS:
```
curl -vk https://
```
## 证书续期
这些证书有效期较短,因此续期很重要。
干运行续期:
```
sudo certbot renew --dry-run
```
常见的手动续期流程:
```
docker compose stop nginx
sudo certbot renew
docker compose start nginx
```
之后可将其自动化,例如使用定时任务。
## 输出路径
项目应避免硬编码与操作系统相关的路径。
请使用 `STIX_OUTPUT_DIR` 而非在代码中嵌入具体路径。
示例:
```
STIX_OUTPUT_DIR=/tmp/stix
```
```
STIX_OUTPUT_DIR=C:/stix-output
```
## 故障排查
### 上传返回 `/convert` 的 404 错误
反向代理可能剥离了 `/api`。
正确的 upstream 配置:
```
location /api/ {
proxy_pass http://api:8000;
}
```
### 上传失败或连接重置
同时查看两个日志以复现问题:
```
docker compose logs -f nginx
docker compose logs -f api
```
### Certbot 生产环境失败
最常见的原因是端口 **80** 无法从公网访问。
从外部测试:
```
curl -v http:///
```
### HTTPS 在证书签发后失败
检查:
- 证书文件是否存在于预期路径
- Nginx 模板是否正确渲染
- 端口 80 和 443 是否开放
- Nginx 配置是否通过验证
```
docker compose exec nginx nginx -t
docker compose exec nginx cat /etc/nginx/conf.d/default.conf
```
## 推荐工作流
### 生产环境
- 使用 Docker Compose
- 通过 Nginx 终止 TLS
- 若无域名,使用 Let's Encrypt IP 证书
- 保持端口 80 可用以支持续期
## 后续改进
- 后台任务队列处理耗时报告
- 上传页面身份验证
- 更丰富的关系推理
- ATT&CK enrichment
- 持久化作业历史
- 健康检查与状态端点
标签:API, AV绕过, Docker, Docker Compose, FastAPI, FTP漏洞扫描, HTTPS, IP过滤, JSON序列化, Let's Encrypt, Nginx, STIX 2.1, TCP SYN 扫描, Web UI, 下载, 公开服务过滤, 关系构建, 前端, 单页应用, 反向代理, 后端, 哈希提取, 威胁报告转换, 威胁行为者, 安全数据转换, 安全监控, 安全编排, 安全防御评估, 战役, 攻击模式, 数据处理管道, 数据提取, 文件上传, 浏览器上传, 确定性关系, 结构化表示, 网络威胁情报, 网络安全, 证据上下文增强, 语义实体, 请求拦截, 逆向工具, 隐私保护, 零信任架构