alpkeskin/rota
GitHub: alpkeskin/rota
Rota 是一款高性能代理轮换平台,提供自动化 IP 管理、实时健康监控、多策略轮换和可视化仪表板,解决大规模代理基础设施的运维与调度难题。
Stars: 375 | Forks: 56
Rota - Proxy Rotation Platform

## 🎯 概述
**Rota** 是一个现代化的全栈代理轮换平台,将企业级的代理管理与美观、实时的 Web 仪表板结合在一起。Rota 在设计时充分考虑了性能和可扩展性,能够每秒处理数千个请求,同时通过直观的界面提供全面的监控、分析和控制功能。
无论您是在进行网页抓取、安全研究、负载测试,还是需要大规模的可靠代理管理,Rota 都能通过以下特性提供完整的解决方案:
- **高性能核心**:基于 Go 的极速代理服务器,具备智能轮换策略
- **实时仪表板**:现代化的 Next.js Web 界面,提供实时指标和监控
- **时间序列分析**:基于 TimescaleDB 的存储,用于历史分析和洞察
- **生产就绪**:基于 Docker 的部署,包含健康检查、平滑关闭和监控
## ✨ 核心特性
### 核心代理服务器
- 🚀 **高性能**:以极低的延迟处理数千个并发请求
- 🔄 **智能轮换**:多种轮换策略(随机、轮询、最少连接、基于时间)
- 🤖 **自动化管理**:实时代理池监控,自动移除不健康的代理
- 🌍 **多协议**:全面支持 HTTP、HTTPS、SOCKS4、SOCKS4A 和 SOCKS5
- ✅ **健康检查**:内置代理验证机制,维护健康的代理池
- 🔒 **身份验证**:支持代理服务器的基本认证
- ⚡ **速率限制**:可配置的速率限制,防止滥用
- 🔗 **代理链**:兼容上游代理(Burp Suite、OWASP ZAP 等)
- ⏱️ **可配置超时**:精细控制请求超时和重试
- 🔁 **重定向支持**:可选的 HTTP 重定向跟随
### 代理来源与自动导入
- 📥 **远程 TXT 列表**:添加指向 `ip:port` 代理列表的 URL —— 自动按计划获取
- 🕐 **独立间隔**:每个来源都有各自的刷新间隔(以分钟为单位)
- 🔁 **后台调度器**:每分钟自动获取过期来源
- 🌍 **来源专属协议**:为每个列表分配 HTTP、HTTPS、SOCKS4、SOCKS4a 或 SOCKS5
### GeoIP 与地理分布
- 🗺️ **自动 GeoIP**:通过 [ip-api.com](http://ip-api.com) 对代理进行地理定位(免费,无需 API key)
- 🏙️ **城市级数据**:每个代理包含国家、地区、城市、ISP、纬度、经度
- 🔍 **地理浏览器**:仪表板中提供可展开的国家树并支持下钻到城市
- ♻️ **自动充实**:每次获取来源后自动更新地理数据
### 代理池
- 🗂️ **命名池**:按国家、城市、ISP 或自定义标签的任意组合对代理进行分组
- ☑️ **多重过滤器构建器**:选择地理位置、ISP 子字符串或代理标签 —— 可在一个池中自由组合
- 🔄 **自动 / 手动同步**:`sync_mode: auto` 在每次导入时重建成员关系;`manual` 保持冻结状态,直到您显式触发同步
- 🔁 **轮换策略**:每个池支持 `roundrobin`、`random` 或 `sticky`(每个 IP 保持 N 个请求)
- ⚡ **异步健康检查**:对任何 URL 运行健康检查;实时显示进度
- ⏱️ **计划检查**:每个池的 Cron 风格计划 (`*/30 * * * *`)
- 📤 **导出**:将代理池列表下载为 `.txt` 或 `.csv` (`GET /api/v1/pools/{id}/export?format=txt|csv`)
- 🔔 **Webhook 告警**:针对每个池的告警规则 —— 当活跃代理数量降至阈值以下时触发 POST/GET webhook,支持配置冷却时间
### 用户级代理池认证
- 👤 **代理用户**:使用 bcrypt 密码创建用户,每个用户分配一个主代理池和有序的备用池
- 🔗 **使用方法**:`http://user:pass@host:8000` —— 代理通过用户的代理池链进行路由
- 🔄 **自动故障转移**:如果池中没有活跃 IP,请求会依次传递到备用池
- 🔁 **重试逻辑**:每次重试都会选择一个新的代理;失败的 IP 在该请求中会被排除
- 📊 **全面跟踪**:跟踪每个代理的所有请求、成功率和响应时间
- ⚡ **用户级速率限制**:支持为每个用户设置可选的 `requests_per_minute` 上限(0 = 无限制)
### 安全
- 🔐 **JWT 认证**:所有 API endpoint 都需要有效的 JWT token;过期时浏览器会自动重定向到登录页面,并提示“Session expired”
- 🔑 **Bcrypt 管理员凭证**:仪表板密码在数据库中以 bcrypt 哈希形式存储
- 🔄 **修改密码**:通过设置 UI 更新用户名/密码(需要当前密码)
- 🌐 **仅限公共 endpoint**:`GET /health` 和 `POST /auth/login`
- 🛡️ **认证暴力破解防护**:在 N 次失败尝试后封锁 IP,并在请求速率超过阈值时进行全局锁定(均可通过 `.env` 配置)
- 🏷️ **代理标签**:使用自定义标签标记代理,以便进行精细的代理池过滤
- 🧹 **死代理清理**:可配置自动移除长期失败或低质量的代理
### Web 仪表板
- 📊 **实时指标**:实时统计、图表和系统监控
- 🔄 **代理管理**:通过 UI 添加、编辑、删除和测试代理
- 📝 **实时日志**:基于 WebSocket 的实时日志流
- 💻 **系统监控**:CPU、内存、磁盘和 runtime 指标
- ⚙️ **配置**:通过 Web 界面管理设置
- 🎨 **现代化 UI**:美观、响应式的设计,支持暗黑模式
- 📱 **移动端友好**:在所有设备上提供完全响应式体验
### 数据与分析
- 📈 **时间序列存储**:使用 TimescaleDB 进行高效的历史数据存储
- 🔍 **请求历史**:跟踪所有代理请求及其详细的元数据
- 📉 **性能分析**:分析代理随时间变化的性能
- 🎯 **使用洞察**:了解流量模式和代理利用率
### DevOps 与部署
- 🐳 **Docker 原生**:生产就绪的容器化部署
- 🔧 **轻松配置**:所有配置均通过 `.env` 进行 —— 有关所有选项,请参见 `.env.example`
- 🏥 **健康检查**:内置用于监控的健康 endpoint
- 🛑 **平滑关闭**:清理连接并平滑关闭
- 📊 **可观测性**:结构化的 JSON 日志记录和指标 endpoint
## 🚀 快速开始
### 使用 Docker Compose(推荐)
启动和运行 Rota 的最快方法:
```
# 1. 克隆仓库
git clone https://github.com/alpkeskin/rota.git
cd rota
# 2. 创建环境文件
cp .env.example .env
# 对于本地开发,默认配置即可直接使用。
# 对于生产环境:将 NEXT_PUBLIC_API_URL 设置为您的公共 API URL。
# 3. 启动所有服务
docker compose up -d
# 4. 检查服务状态
docker compose ps
```
**访问各项服务:**
- 🌐 **仪表板**:http://localhost:3000
- 🔧 **API**:http://localhost:8001
- 🔄 **代理**:http://localhost:8000
- 🗄️ **数据库**:localhost:5432
**仪表板的默认凭证:**
- 用户名:`admin`
- 密码:`admin`
### 配置
所有设置均通过单个 `.env` 文件控制(有关所有选项及描述,请参见 `.env.example`):
| 变量 | 默认值 | 描述 |
|---|---|---|
| `NEXT_PUBLIC_API_URL` | `http://localhost:8001` | API 的公开 URL —— 供浏览器使用 |
| `PROXY_PORT` | `8000` | 代理服务器的主机端口 |
| `API_PORT` | `8001` | REST API 的主机端口 |
| `DASHBOARD_PORT` | `3000` | Web 仪表板的主机端口 |
| `ROTA_ADMIN_USER` | `admin` | 初始仪表板用户名(仅注入一次) |
| `ROTA_ADMIN_PASSWORD` | `admin` | 初始仪表板密码(仅注入一次,最少 6 个字符) |
| `DB_PASSWORD` | `rota_password` | TimescaleDB 密码 |
| `LOG_LEVEL` | `info` | 日志详细程度:`debug`、`info`、`warn`、`error` |
| `AUTH_IP_MAX_ATTEMPTS` | `10` | 封锁 IP 前的失败登录尝试次数 |
| `AUTH_IP_WINDOW_MINUTES` | `10` | 统计每个 IP 失败次数的滑动窗口(分钟) |
| `AUTH_IP_BLOCK_MINUTES` | `30` | 被封锁的 IP 不能尝试登录的时长 |
| `AUTH_GLOBAL_MAX_PER_MINUTE` | `1000` | 在全局锁定前,所有 IP 每分钟的最大登录尝试总数 |
| `AUTH_GLOBAL_LOCKOUT_MINUTES` | `1` | 全局登录锁定的持续时间 |
### 生产环境部署
对于生产环境,至少需设置:
```
# .env
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
DB_PASSWORD=a-strong-random-password
ROTA_ADMIN_PASSWORD=a-strong-password
```
然后重新构建仪表板(更改 `NEXT_PUBLIC_API_URL` 时需要此操作,因为它在构建时会被打包进 Next.js bundle 中):
```
docker compose up -d --build
```
### 使用 Docker
拉取并运行核心服务:
```
# 从 GitHub Container Registry 拉取
docker pull ghcr.io/alpkeskin/rota:latest
# 使用基础配置运行
docker run -d \
--name rota-core \
-p 8000:8000 \
-p 8001:8001 \
-e DB_HOST=your-db-host \
-e DB_USER=rota \
-e DB_PASSWORD=your-password \
ghcr.io/alpkeskin/rota:latest
```
### 从源码构建
```
# 前提条件:Go 1.25.3+、Node.js 20+、带有 TimescaleDB 的 PostgreSQL 16+
# 克隆仓库
git clone https://github.com/alpkeskin/rota.git
cd rota
# 启动 Core
cd core
cp .env .env.local # Configure your environment
make install
make dev
# 启动 Dashboard(在新终端中)
cd dashboard
npm install
cp .env.local .env.local # Configure API URL
npm run dev
```
### 测试代理
```
# 通过 Rota proxy 路由流量
curl -x http://localhost:8000 https://api.ipify.org?format=json
# 按用户池路由(在 dashboard 中创建 Proxy User 之后)
curl -x http://myuser:mypassword@localhost:8000 https://api.ipify.org?format=json
# 使用环境变量
export HTTP_PROXY=http://localhost:8000
export HTTPS_PROXY=http://localhost:8000
curl https://api.ipify.org?format=json
```
## 📚 API 文档
### 交互式 API 文档 (Swagger)
Rota 通过 Swagger UI 提供交互式 API 文档。核心服务运行后,您可以在此访问:
```
http://localhost:8001/docs
```
Swagger 界面允许您:
- 📖 浏览所有可用的 API endpoint
- 🧪 直接从浏览器测试 API 请求
- 📝 查看 request/response schema
- 🔍 探索身份验证要求
**快速访问:**
- **Swagger UI**:http://localhost:8001/docs
- **OpenAPI Spec**:http://localhost:8001/docs/swagger.json
## 🏗️ 架构
Rota 采用现代化的 monorepo 构建,包含三个主要组件:
```
┌─────────────────────────────────────────────────────────────┐
│ Rota Platform │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Dashboard │───▶│ Core (API) │───▶│ TimescaleDB │ │
│ │ Next.js │ │ Go │ │ PostgreSQL │ │
│ │ Port 3000 │ │ Port 8001 │ │ Port 5432 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────┐ │
│ └───────────▶│ Proxy Server │ │
│ │ Go │ │
│ │ Port 8000 │ │
│ └──────────────┘ │
│ │ │
└──────────────────────────────┼──────────────────────────────┘
▼
┌──────────────────┐
│ Proxy Pool │
│ (External IPs) │
└──────────────────┘
```
### 轮换策略
- **Random**:为每个请求随机选择一个代理
- **Round Robin**:将请求均匀分配到所有代理
- **Least Connections**:路由到活动连接最少的代理
- **Time-Based**:按固定时间间隔轮换代理
## 🐳 部署
### 生产环境部署
#### 使用 Docker Compose
```
# 生产环境配置
docker compose -f docker-compose.yml up -d
# 启用自动重启
docker compose up -d --restart=unless-stopped
```
## 🗂️ 代理来源与代理池
### 代理来源的工作原理
1. 转到仪表板中的 **Proxy Sources**
2. 添加一个指向纯文本代理列表(每行一个 `ip:port`)的 URL
3. 选择协议和刷新间隔
4. 点击 **Fetch Now** 或等待调度器
系统将:
- 下载并解析列表
- 将代理 upsert 到数据库中(忽略重复项)
- 自动为每个新代理查找 GeoIP 数据
- 重新同步所有启用了 `Auto-sync` 的代理池
### 地理分布与代理池
代理进行地理定位后,打开 **Proxy Pools → Geo Distribution** 标签页:
- 浏览所有包含代理的国家;点击国家以展开城市
- 勾选单个国家或城市;自由组合它们
- 点击 **Create Pool from selection** —— 代理池将被立即创建并填充
代理池还支持 **ISP 过滤器**(子字符串匹配,OR 逻辑)和 **标签过滤器**(AND 逻辑 —— 代理必须包含所有指定的标签)。您可以按任意组合结合地理位置 + ISP + 标签。
#### 代理池同步模式
| 模式 | 行为 |
|------|-----------|
| `auto` | 代理池成员在每次导入代理或地理数据充实后自动重建 |
| `manual` | 成员仅在您按下 **Sync** 时改变 —— 适用于精选代理池 |
#### 导出代理池
```
# 纯文本 — 每行一个 protocol://ip:port
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8001/api/v1/pools/{id}/export?format=txt" -o pool.txt
# CSV — 包含状态、地理位置、ISP、成功率
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8001/api/v1/pools/{id}/export?format=csv" -o pool.csv
```
#### Webhook 告警
为代理池添加告警规则,以便在活跃代理数量降至阈值以下时收到通知:
```
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
"http://localhost:8001/api/v1/pools/{id}/alert-rules" \
-d '{
"enabled": true,
"min_active_proxies": 10,
"webhook_url": "https://hooks.slack.com/...",
"cooldown_minutes": 30
}'
```
发送给 webhook 的 payload:
```
{
"event": "pool.degraded",
"pool_id": 1,
"pool_name": "US Residential",
"active_proxies": 3,
"total_proxies": 50,
"threshold": 10,
"fired_at": "2026-04-02T04:30:00Z"
}
```
### 用户级路由
1. 为每个位置/用例创建代理池
2. 转到 **Proxy Users**,点击 **Add User**
3. 设置主代理池和可选的备用代理池(按优先级顺序)
4. 配置整个链的最大重试次数以及可选的 `requests_per_minute` 上限
用户连接方式如下:
```
http://username:password@your-proxy-host:8000
```
如果主代理池中没有活跃 IP,请求会自动传递到下一个备用代理池。
## 🔐 API 身份验证
所有 API endpoint 都需要通过 `POST /api/v1/auth/login` 获取的 JWT bearer token。
```
# 登录
TOKEN=$(curl -s -X POST http://localhost:8001/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"yourpassword"}' | jq -r '.token')
# 使用 token
curl -H "Authorization: Bearer $TOKEN" http://localhost:8001/api/v1/proxies
```
公共 endpoint(无需 token):
- `GET /health`
- `POST /api/v1/auth/login`
### 力破解防护
登录 endpoint 具有两个独立的速率限制机制:
| 机制 | 触发条件 | 响应 |
|-----------|---------|----------|
| **单 IP 封锁** | 在 `AUTH_IP_WINDOW_MINUTES` 分钟内,来自某个 IP 的失败尝试次数 ≥ `AUTH_IP_MAX_ATTEMPTS` | `429` —— 该 IP 将被封禁 `AUTH_IP_BLOCK_MINUTES` 分钟 |
| **全局锁定** | 所有 IP 每分钟的总尝试次数 ≥ `AUTH_GLOBAL_MAX_PER_MINUTE` | `429` —— 在 `AUTH_GLOBAL_LOCKOUT_MINUTES` 分钟内禁止所有人登录 |
两种响应都包含 `Retry-After` header。所有阈值均可通过 `.env` 配置。
当收到 `401` 响应时,仪表板会自动重定向到登录页面,并显示 *"Session expired"* 消息。
## 🤝 贡献
欢迎任何贡献!我们感谢能为项目带来价值的有意义的贡献。
### 如何贡献
1. **Fork 本仓库**
2. **创建功能分支**:`git checkout -b feature/amazing-feature`
3. **进行更改**
4. **提交更改**:`git commit -m 'Add amazing feature'`
5. **推送到分支**:`git push origin feature/amazing-feature`
6. **发起 Pull Request**
### 贡献指南
- 编写清晰、描述性的提交信息
- 为新功能添加测试
- 根据需要更新文档
- 遵循现有的代码风格和约定
- 提交 PR 前确保所有测试均通过
- 每个 pull request 仅包含一个功能/修复
**注意**:不包含重大改进或修复的 pull request 将不予接受。
### 开发工作流
```
# 1. 创建 feature 分支
git checkout -b feature/my-feature
# 2. 进行更改并测试
make test
# 3. 提交更改
git add .
git commit -m "feat: add my feature"
# 4. 推送并创建 PR
git push origin feature/my-feature
```
## 📝 许可证
本项目基于 Apache License 2.0 授权 —— 有关详细信息,请参阅 [LICENSE](LICENSE) 文件。
标签:EVTX分析, Go, Ruby工具, TimescaleDB, 代理轮换, 日志审计, 测试用例, 请求拦截, 负载均衡, 运维监控