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
}