HTTP API 文档
学习如何使用 Port Rocket 的 HTTP API 接口进行端口扫描和任务管理
开始使用
提示:
在使用 HTTP API 前,您需要先安装 Port Rocket。请参考 安装指南 完成安装。
Port Rocket 提供 RESTful API,允许通过 HTTP 请求执行扫描任务和管理系统。API 服务可以通过以下命令启动:
go-port-rocket api --port 8080
安全提示:
默认情况下,系统会使用默认用户名 CC11001100
并自动生成随机密码,启动时会在控制台显示这些信息。
强烈建议您使用 --admin-user
和 --admin-password
参数手动指定认证凭据,尤其是在生产环境中。
推荐的生产环境启动方式:
go-port-rocket api \
--port 8080 \
--admin-user your_custom_username \
--admin-password your_secure_password \
--jwt-secret your_custom_jwt_secret
API 的基本规范如下:
- 基本 URL 格式:
http://[host]:[port]/api/v1/...
- 响应格式:
JSON
- 认证方式:
JWT (Bearer Token)
API 服务选项
选项 | 描述 | 默认值 |
---|---|---|
--host |
API服务监听地址 | 0.0.0.0 |
--port |
API服务监听端口 | 8080 |
--admin-user |
管理员用户名 | CC11001100 |
--admin-password |
管理员密码 | 自动生成的随机密码 |
--jwt-secret |
JWT密钥(不指定时自动生成,不会显示) | 自动生成 |
--redis-addr |
Redis服务器地址 | localhost:6379 |
--redis-pass |
Redis密码 | - |
--redis-db |
Redis数据库编号 | 0 |
--max-workers |
最大工作线程数 | 10 |
--queue-size |
任务队列大小 | 100 |
--enable-auth |
启用认证 | true |
完整配置启动示例
go-port-rocket api \
--port 8080 \
--enable-auth \
--admin-user admin \
--admin-password secure_password \
--jwt-secret your-secret-key \
--redis-addr localhost:6379 \
--redis-pass your-password \
--redis-db 0 \
--max-workers 10 \
--queue-size 100
认证
API 服务默认启用认证。要访问受保护的端点,客户端需要先获取 JWT 令牌。
默认认证凭据
在启动 API 服务时,系统会使用以下认证凭据:
- 如果通过
--admin-user
和--admin-password
指定了凭据,则使用指定的值 - 如果未指定,则使用默认用户名
CC11001100
并自动生成随机密码 - 生成的随机密码会在服务启动时显示在控制台上
提示:
在生产环境中,务必使用 --admin-user
和 --admin-password
参数手动设置安全的凭据。
获取令牌
POST /api/v1/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password"
}
成功响应示例:
{
"status": "success",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": "2023-07-01T12:00:00Z"
}
}
使用令牌
获取令牌后,将其添加到后续请求的 Authorization 头中:
GET /api/v1/scan/tasks
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
扫描 API
创建扫描任务
POST /api/v1/scan
Authorization: Bearer <token>
Content-Type: application/json
{
"target": "192.168.1.1",
"ports": "80,443",
"scan_type": "tcp",
"timeout": "5s",
"workers": 100,
"output_format": "json",
"pretty_output": true,
"enable_os": true,
"enable_service": true,
"version_intensity": 7,
"guess_os": false,
"limit_os_scan": false
}
响应示例:
{
"task_id": "c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca",
"status": "pending"
}
请求参数说明
参数 | 类型 | 描述 | 是否必填 | 默认值 | 示例 |
---|---|---|---|---|---|
target |
string | 扫描目标 (IP、域名或CIDR) | 是 | - | "192.168.1.1" 或 "example.com" 或 "10.0.0.0/24" |
ports |
string | 端口范围,可以是单个端口、多个端口(逗号分隔)或端口范围 | 是 | - | "80" 或 "80,443,8080" 或 "1-1024" |
scan_type |
string | 扫描类型,支持 tcp、udp 或 syn | 否 | "tcp" | "tcp" |
timeout |
string | 单个端口扫描超时时间,支持时间单位 (s, ms) | 否 | "5s" | "5s" 或 "500ms" |
workers |
int | 并发扫描的工作线程数 | 否 | 100 | 100 |
output_format |
string | 输出格式,支持 json、text、xml 或 html | 否 | "json" | "json" |
pretty_output |
bool | 是否美化输出格式(适用于 JSON 和 XML) | 否 | false | true |
enable_os |
bool | 是否启用操作系统检测 | 否 | false | true |
enable_service |
bool | 是否启用服务和版本检测 | 否 | false | true |
version_intensity |
int | 版本检测强度,范围 0-9,数值越大越详细但速度越慢 | 否 | 7 | 7 |
guess_os |
bool | 是否根据开放端口推测操作系统 | 否 | false | true |
limit_os_scan |
bool | 是否限制操作系统扫描的端口数量来提高速度 | 否 | false | true |
响应字段说明
字段 | 类型 | 描述 |
---|---|---|
status |
string | 操作状态,成功为 "success",失败为 "error" |
data.task_id |
string | 任务唯一标识符,用于后续查询任务状态和获取结果 |
data.status |
string | 任务初始状态,通常为 "queued" |
data.created_at |
string | 任务创建时间,ISO 8601 格式 |
任务管理
获取任务列表
GET /api/v1/scan/tasks
Authorization: Bearer <token>
查询参数:
参数 | 类型 | 描述 | 是否必填 | 默认值 | 示例 |
---|---|---|---|---|---|
page |
int | 页码,用于分页 | 否 | 1 | 2 |
per_page |
int | 每页显示的任务数量 | 否 | 10 | 20 |
status |
string | 按状态筛选任务 | 否 | - | completed |
响应示例:
{
"status": "success",
"data": {
"tasks": [
{
"task_id": "c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca",
"target": "192.168.1.1",
"status": "completed",
"created_at": "2023-06-15T10:15:30Z",
"completed_at": "2023-06-15T10:16:15Z"
},
{
"task_id": "d82f3a7c-5b1e-4c8a-9f5d-89e12c9b3c4a",
"target": "example.com",
"status": "running",
"created_at": "2023-06-15T10:20:30Z",
"completed_at": null
}
],
"total": 2,
"page": 1,
"per_page": 10
}
}
获取任务详情
GET /api/v1/scan/tasks/{task_id}
Authorization: Bearer <token>
URL 参数:
参数 | 类型 | 描述 | 是否必填 | 示例 |
---|---|---|---|---|
task_id |
string | 任务的唯一标识符 | 是 | c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca |
响应示例:
{
"status": "success",
"data": {
"task_id": "c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca",
"target": "192.168.1.1",
"ports": "80,443",
"scan_type": "tcp",
"status": "completed",
"created_at": "2023-06-15T10:15:30Z",
"started_at": "2023-06-15T10:15:35Z",
"completed_at": "2023-06-15T10:16:15Z",
"result_available": true
}
}
获取任务结果
GET /api/v1/scan/tasks/{task_id}/result
Authorization: Bearer <token>
URL 参数:
参数 | 类型 | 描述 | 是否必填 | 示例 |
---|---|---|---|---|
task_id |
string | 任务的唯一标识符 | 是 | c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca |
响应示例:
{
"status": "success",
"data": {
"scan_result": {
"target": "192.168.1.1",
"ports": [
{
"port": 80,
"protocol": "tcp",
"state": "open",
"service": "http",
"version": "Apache httpd 2.4.46"
},
{
"port": 443,
"protocol": "tcp",
"state": "open",
"service": "https",
"version": "Apache httpd 2.4.46"
}
],
"os": {
"name": "Linux",
"version": "4.15.0-99-generic",
"confidence": 96
},
"scan_time": "45.2s"
}
}
}
取消任务
DELETE /api/v1/scan/tasks/{task_id}
Authorization: Bearer <token>
URL 参数:
参数 | 类型 | 描述 | 是否必填 | 示例 |
---|---|---|---|---|
task_id |
string | 任务的唯一标识符 | 是 | d82f3a7c-5b1e-4c8a-9f5d-89e12c9b3c4a |
响应示例:
{
"status": "success",
"message": "Task cancelled successfully"
}
系统 API
系统状态
GET /api/v1/system/status
Authorization: Bearer <token>
响应示例:
{
"queue_size": 2,
"worker_count": 8,
"running_tasks": 1,
"max_workers": 10,
"queue_capacity": 100
}
系统指标
GET /api/v1/system/metrics
Authorization: Bearer <token>
响应示例:
{
"status": "success",
"data": {
"requests_total": 1580,
"scans_total": 155,
"scan_success_rate": 98.2,
"avg_scan_time": "35.7s",
"resource_usage": {
"cpu_usage": [
{ "time": "2023-06-15T10:00:00Z", "value": 22.5 },
{ "time": "2023-06-15T10:05:00Z", "value": 24.8 },
{ "time": "2023-06-15T10:10:00Z", "value": 25.4 }
],
"memory_usage": [
{ "time": "2023-06-15T10:00:00Z", "value": 480.2 },
{ "time": "2023-06-15T10:05:00Z", "value": 495.3 },
{ "time": "2023-06-15T10:10:00Z", "value": 512.6 }
]
}
}
}
示例
使用 curl 创建扫描任务
curl -X POST \
http://localhost:8080/api/v1/scan \
-H 'Authorization: Bearer <your-token>' \
-H 'Content-Type: application/json' \
-d '{
"target": "example.com",
"ports": "80,443",
"scan_type": "tcp",
"enable_service": true,
"enable_os": true
}'
使用 curl 获取任务结果
curl -X GET \
http://localhost:8080/api/v1/scan/tasks/c91e0e9b-f869-4b15-a1cd-74e8c5afd8ca/result \
-H 'Authorization: Bearer <your-token>'
使用 curl 获取系统状态
curl -X GET \
http://localhost:8080/api/v1/system/status \
-H 'Authorization: Bearer <your-token>'
使用 Python 创建并检查任务
import requests
import json
import time
# 配置
API_URL = "http://localhost:8080/api/v1"
TOKEN = "your-token"
HEADERS = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
# 创建扫描任务
scan_data = {
"target": "example.com",
"ports": "80,443,8080",
"scan_type": "tcp",
"enable_service": True,
"enable_os": True
}
response = requests.post(f"{API_URL}/scan", headers=HEADERS, json=scan_data)
task = response.json()
task_id = task["data"]["task_id"]
print(f"Created task: {task_id}")
# 等待任务完成
while True:
response = requests.get(f"{API_URL}/scan/tasks/{task_id}", headers=HEADERS)
task_status = response.json()["data"]["status"]
print(f"Task status: {task_status}")
if task_status in ["completed", "failed"]:
break
time.sleep(5)
# 获取结果
if task_status == "completed":
response = requests.get(f"{API_URL}/scan/tasks/{task_id}/result", headers=HEADERS)
result = response.json()
print(json.dumps(result, indent=2))
使用 JavaScript/Node.js 创建任务
const axios = require('axios');
// 配置
const API_URL = 'http://localhost:8080/api/v1';
const TOKEN = 'your-token';
const HEADERS = {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json'
};
// 创建扫描任务函数
async function createScanTask() {
try {
const scanData = {
target: '192.168.1.1',
ports: '22,80,443',
scan_type: 'tcp',
timeout: '3s',
workers: 50,
enable_os: true,
enable_service: true
};
const response = await axios.post(`${API_URL}/scan`, scanData, { headers: HEADERS });
const taskId = response.data.data.task_id;
console.log(`Task created with ID: ${taskId}`);
return taskId;
} catch (error) {
console.error('Error creating scan task:', error.response?.data || error.message);
}
}
// 获取任务状态函数
async function getTaskStatus(taskId) {
try {
const response = await axios.get(`${API_URL}/scan/tasks/${taskId}`, { headers: HEADERS });
return response.data.data.status;
} catch (error) {
console.error('Error getting task status:', error.response?.data || error.message);
return null;
}
}
// 获取任务结果函数
async function getTaskResult(taskId) {
try {
const response = await axios.get(`${API_URL}/scan/tasks/${taskId}/result`, { headers: HEADERS });
return response.data;
} catch (error) {
console.error('Error getting task result:', error.response?.data || error.message);
return null;
}
}
// 主函数
async function main() {
// 创建任务
const taskId = await createScanTask();
if (!taskId) return;
// 轮询任务状态
let status;
do {
await new Promise(resolve => setTimeout(resolve, 5000)); // 等待5秒
status = await getTaskStatus(taskId);
console.log(`Task status: ${status}`);
} while (status === 'queued' || status === 'running');
// 获取结果
if (status === 'completed') {
const result = await getTaskResult(taskId);
console.log('Scan result:');
console.log(JSON.stringify(result, null, 2));
}
}
main();
使用 Go 创建任务
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
const (
APIURL = "http://localhost:8080/api/v1"
Token = "your-token"
)
// 扫描请求结构体
type ScanRequest struct {
Target string `json:"target"`
Ports string `json:"ports"`
ScanType string `json:"scan_type"`
Timeout string `json:"timeout"`
Workers int `json:"workers"`
EnableOS bool `json:"enable_os"`
EnableService bool `json:"enable_service"`
VersionIntensity int `json:"version_intensity"`
}
// 任务响应结构体
type TaskResponse struct {
Status string `json:"status"`
Data struct {
TaskID string `json:"task_id"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
} `json:"data"`
}
// 任务状态响应结构体
type TaskStatusResponse struct {
Status string `json:"status"`
Data struct {
TaskID string `json:"task_id"`
Status string `json:"status"`
ResultAvailable bool `json:"result_available"`
} `json:"data"`
}
func main() {
// 创建扫描任务
taskID, err := createScanTask()
if err != nil {
fmt.Printf("创建任务失败: %v\n", err)
return
}
fmt.Printf("创建任务成功,ID: %s\n", taskID)
// 轮询任务状态
for {
status, done, err := getTaskStatus(taskID)
if err != nil {
fmt.Printf("获取任务状态失败: %v\n", err)
break
}
fmt.Printf("任务状态: %s\n", status)
if done {
// 获取结果
result, err := getTaskResult(taskID)
if err != nil {
fmt.Printf("获取任务结果失败: %v\n", err)
} else {
fmt.Printf("任务结果: %s\n", result)
}
break
}
time.Sleep(5 * time.Second)
}
}
// 创建扫描任务
func createScanTask() (string, error) {
scanReq := ScanRequest{
Target: "example.com",
Ports: "80,443,8080",
ScanType: "tcp",
Timeout: "5s",
Workers: 100,
EnableOS: true,
EnableService: true,
VersionIntensity: 7,
}
reqBody, err := json.Marshal(scanReq)
if err != nil {
return "", err
}
client := &http.Client{}
req, err := http.NewRequest("POST", APIURL+"/scan", bytes.NewBuffer(reqBody))
if err != nil {
return "", err
}
req.Header.Add("Authorization", "Bearer "+Token)
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var taskResp TaskResponse
if err := json.Unmarshal(body, &taskResp); err != nil {
return "", err
}
return taskResp.Data.TaskID, nil
}
// 获取任务状态
func getTaskStatus(taskID string) (string, bool, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", fmt.Sprintf("%s/scan/tasks/%s", APIURL, taskID), nil)
if err != nil {
return "", false, err
}
req.Header.Add("Authorization", "Bearer "+Token)
resp, err := client.Do(req)
if err != nil {
return "", false, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", false, err
}
var statusResp TaskStatusResponse
if err := json.Unmarshal(body, &statusResp); err != nil {
return "", false, err
}
done := statusResp.Data.Status == "completed" || statusResp.Data.Status == "failed"
return statusResp.Data.Status, done, nil
}
// 获取任务结果
func getTaskResult(taskID string) (string, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", fmt.Sprintf("%s/scan/tasks/%s/result", APIURL, taskID), nil)
if err != nil {
return "", err
}
req.Header.Add("Authorization", "Bearer "+Token)
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}