Files
CLICD/Mofang/README.md
2026-06-13 02:49:23 +08:00

550 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLICD 魔方财务对接模块
这是用于智简魔方 / IDCSMART 的 CLICD 服务器模块。模块通过 CLICD API 完成实例开通、删除、开关机、重启、重装、改密、资源变更、流量重置、NAT 端口映射管理、实例信息展示和 WebSSH 入口。
## 文件结构
```text
clicd.php
README.md
handlers/
webssh.php
templates/
firewall.html
info.html
nat.html
```
安装时请保持目录结构不变,将整个 `clicd` 目录放入魔方服务器模块目录:
```text
public/plugins/servers/clicd/
```
## 服务器配置
在魔方后台添加服务器时,模块名称选择 `clicd`
CLICD 面板地址建议使用 HTTPS
```text
主机名 = https://0.0.0.0:8999
```
也可以拆分填写:
```text
IP地址 = 0.0.0.0
端口 = 8999
secure = 开启
```
API Key 可以填写在以下任意一个字段中:
```text
Hash
密码
```
模块请求 CLICD 时会同时携带:
```text
X-API-Key: clicd_sk_xxxx
Authorization: Bearer clicd_sk_xxxx
Content-Type: application/json
```
## 产品配置项
| 字段 | 说明 |
| --- | --- |
| `virtualization` | 虚拟化类型,`lxc``kvm` |
| `template_id` | CLICD 模板 / 镜像 ID |
| `vcpu` | CPU 核心数 |
| `cpu_percent` | CPU 使用率限制,`0` 表示不额外限制 |
| `ram_mb` | 内存,单位 MB |
| `disk_gb` | 系统盘,单位 GB |
| `network_bw_mbps` | 带宽,单位 Mbps |
| `traffic_mode` | `total` 总流量,或 `in_out` 入 / 出分开 |
| `monthly_traffic_gb` | 月流量 GB |
| `traffic_in_gb` | 入站流量 GB`in_out` 模式使用 |
| `traffic_out_gb` | 出站流量 GB`in_out` 模式使用 |
| `io_speed_mbps` | 磁盘 IO 限制,`0` 表示不限制 |
| `port_mapping_count` | 开通时分配的 NAT 端口数量,最小 2 |
| `snapshot_limit` | 快照配额 |
| `extra_ports` | 额外映射的容器端口,逗号分隔,例如 `80,443` |
| `assign_ipv6` | 开通时是否自动分配 IPv6 |
| `sync_expiry` | 是否同步魔方到期时间到 CLICD |
客户产品的 `domain` 会作为 CLICD 容器名称。模块会自动把不适合作为容器名的字符替换为 `-`
## 开通后字段同步
开通、同步、重装、改密后,模块会从 CLICD 容器详情拉取最新信息并写回魔方主机表:
| 魔方字段 | 写入内容 |
| --- | --- |
| `dedicatedip` | NAT 外网 IP,优先使用 API 返回的公网字段,否则使用服务器 IP |
| `username` | 固定写入 `root` |
| `password` | CLICD 返回的 SSH 密码,兼容魔方 `cmf_encrypt()` |
| `port` | CLICD 返回的 `ssh_port` |
| `domainstatus` | CLICD 状态为 `running` 时写 `Active`,否则写 `Suspended` |
如果接口返回的密码是 `***` 这类脱敏值,模块不会覆盖魔方里已有密码。
## 客户区页面
模块提供三个客户区选项卡:
```text
实例信息
NAT转发
防火墙
```
客户区按钮提供:
```text
WebSSH
```
## 实例信息
实例信息页展示:
- 实例名称、运行状态、SSH 地址、IPv6
- CPU、内存、负载、磁盘圆环状态
- 月流量进度
- CPU 使用率、内存使用、网络流量、磁盘 IO 图表
- IPv4、SSH 端口、SSH 密码、资源配置、到期时间
图表数据通过客户区懒加载接口获取,不会强制刷新整个魔方页面。页面首次打开会加载一次数据,之后由用户选择是否自动刷新:
```text
不刷新
10 秒
1 分钟
5 分钟
10 分钟
```
也可以点击“立即刷新”手动刷新一次。当前 CLICD 用量接口返回的是实时值,不是历史数组;图表曲线由客户区前端持续采样生成。若需要打开页面立即显示历史曲线,需要 CLICD 额外提供历史指标接口。
流量显示支持智能单位,小流量会显示 B / KB / MB,大流量显示 GB,例如:
```text
370.5 KB / 100 GB
```
模块会优先调用:
```text
GET /api/v1/containers/{name}/usage
GET /api/v1/containers/{name}/traffic
```
如果 `/api/v1/containers/{name}/usage` 不可用,模块会在容器详情存在 `uuid` 时尝试兼容:
```text
GET /api/containers/{uuid}/usage
```
已兼容的常见用量字段包括:
```text
cpu_usage_pct
memory_usage_bytes
disk_usage_bytes
network_rx_bps
network_tx_bps
disk_read_bps
disk_write_bps
rx_used_bytes
tx_used_bytes
total_used_bytes
limit_gb
used_pct
```
## NAT 转发
NAT 转发是独立页面,支持:
- 查看端口映射
- 获取随机可用端口
- 添加端口映射
- 修改端口映射
- 删除端口映射
删除端口映射时使用页面内确认弹窗,不使用浏览器自带确认框。
使用的 CLICD API
```text
GET /api/v1/containers/{id|uuid|name}
GET /api/v1/containers/{id}/random-port
POST /api/v1/containers/{id}/port-mappings
PUT /api/v1/containers/{id}/port-mappings/{index}
DELETE /api/v1/containers/{id}/port-mappings/{index}
```
添加 / 修改 NAT 映射时必须使用 JSON 请求体,例如:
```json
{
"container_port": 8080,
"host_port": 61320,
"protocol": "tcp",
"description": "HTTP"
}
```
## 防火墙
防火墙是独立客户区页面,支持:
- 查看防火墙启用状态、默认动作和规则列表
- 启用 / 停用防火墙
- 设置默认动作:未匹配拒绝或未匹配放行
- 添加规则
- 编辑规则
- 删除规则
- 单独启用 / 停用某条规则
页面会先在前端修改规则列表和开关状态,点击“保存设置”后才统一同步到 CLICD。这样可以避免每次切换开关、修改默认动作或编辑规则时都立即请求后端,减少客户区卡顿。
注意:防火墙关闭时也可以保存规则;关闭只表示暂时不接管该容器流量,不代表规则必须清空。
使用的 CLICD API
```text
GET /api/v1/containers/{id}/firewall
PUT /api/v1/containers/{id}/firewall
```
更新防火墙时必须使用 JSON 请求体,例如:
```json
{
"enabled": true,
"default_action": "ACCEPT",
"rules": [
{
"id": "",
"network": "ipv4",
"direction": "in",
"protocol": "tcp",
"port": "22",
"source_ip": "",
"action": "ACCEPT",
"description": "Allow SSH",
"enabled": true
}
]
}
```
规则字段说明:
| 字段 | 说明 |
| --- | --- |
| `network` | 网络范围,常用 `ipv4`,也支持 `ipv6` / `all` |
| `direction` | 方向,`in` 入站,`out` 出站 |
| `protocol` | 协议,`tcp``udp` |
| `port` | 端口,可填写单端口、逗号分隔端口或端口段,例如 `22``80,443``8000-9000` |
| `source_ip` | 来源 IP / CIDR,留空表示任意来源 |
| `action` | 动作,`ACCEPT` 放行,`DROP` 拒绝 |
| `description` | 规则描述 |
| `enabled` | 是否启用该规则 |
IPv4 NAT 入站规则的端口按容器内部端口匹配,不是宿主机公网端口。例如公网 `22023 -> 容器 22`,防火墙规则端口应填写 `22`
## WebSSH
WebSSH 按钮会调用:
```text
POST /api/v1/ssh-ticket
```
请求体:
```json
{
"container_name": "example-vm"
}
```
接口返回 60 秒有效票据后,模块会打开本地 handler:
```text
/plugins/servers/clicd/handlers/webssh.php
```
浏览器会从该页面直连 CLICD
```text
wss://0.0.0.0:8999/api/ssh?container=example-vm
Sec-WebSocket-Protocol: clicd-ticket.xxxxx
```
注意:WebSSH 受浏览器安全策略和 CLICD 后端 Origin 校验影响。魔方客户区通常是 HTTPS,因此 CLICD 面板也必须启用 HTTPS/WSS。请把魔方服务器配置里的 `主机名` 改为 `https://0.0.0.0:8999`,或把 `secure` 设为 `开启`
新版 CLICD 已支持 WebSSH Origin 放行。部署时需要在 CLICD 后端把魔方财务客户区域名加入 WebSSH Origin 白名单,例如:
```text
https://www.example.com
```
如果 WebSSH 页面显示 `WebSocket error``Disconnected code=1006`,但直接以 CLICD 自身 Origin 测试能返回 `101 Switching Protocols`,通常说明 CLICD 后端未放行魔方客户区域名的 WebSocket Origin。此时请检查 CLICD 的 WebSSH Origin 白名单配置;前端页面无法伪造浏览器 Origin。
## 支持的魔方操作
| 魔方操作 | CLICD API |
| --- | --- |
| 连接测试 | `GET /api/v1/dashboard` |
| 开通 | `POST /api/v1/containers` |
| 删除 | `DELETE /api/v1/containers/{name}/delete` |
| 开机 | `POST /api/v1/containers/{name}/start` |
| 关机 | `POST /api/v1/containers/{name}/stop` |
| 重启 | `POST /api/v1/containers/{name}/restart` |
| 重装 | `POST /api/v1/containers/{name}/reinstall` |
| 改密 | `POST /api/v1/containers/{name}/reset-password` |
| 重置流量 | `POST /api/v1/containers/{name}/traffic-reset` |
| 变更资源 | `PUT /api/v1/containers/{name}/resource-limit` |
| 变更流量 | `PUT /api/v1/containers/{name}/traffic-limit` |
| 同步到期 | `PUT /api/v1/containers/{name}/expiry` |
| 查询防火墙 | `GET /api/v1/containers/{id}/firewall` |
| 更新防火墙 | `PUT /api/v1/containers/{id}/firewall` |
| WebSSH | `POST /api/v1/ssh-ticket` |
## 建议 API 权限
API Key 至少需要以下权限,具体名称以 CLICD 后端实际权限系统为准:
```text
dashboard:read
container:read
container:create
container:power
container:delete
container:reinstall
container:password
container:traffic
container:resize
container:port
container:firewall
task:read
ssh-ticket:create
```
如果 API Key 使用 `*``admin:*`,通常可以覆盖上述权限。
## 建议先测试的 curl
连接测试:
```bash
curl -H "X-API-Key: clicd_sk_xxxx" \
https://0.0.0.0:8999/api/v1/dashboard
```
容器详情:
```bash
curl -H "X-API-Key: clicd_sk_xxxx" \
https://0.0.0.0:8999/api/v1/containers/example-vm
```
资源用量:
```bash
curl -H "X-API-Key: clicd_sk_xxxx" \
https://0.0.0.0:8999/api/v1/containers/example-vm/usage
```
流量统计:
```bash
curl -H "X-API-Key: clicd_sk_xxxx" \
https://0.0.0.0:8999/api/v1/containers/example-vm/traffic
```
修改 NAT
```bash
curl --location --request PUT \
"https://0.0.0.0:8999/api/v1/containers/10/port-mappings/1" \
--header "X-API-Key: clicd_sk_xxxx" \
--header "Authorization: Bearer clicd_sk_xxxx" \
--header "Content-Type: application/json" \
--data-raw '{"container_port":8081,"host_port":61320,"protocol":"tcp","description":"HTTP"}'
```
查询防火墙:
```bash
curl -H "X-API-Key: clicd_sk_xxxx" \
https://0.0.0.0:8999/api/v1/containers/10/firewall
```
更新防火墙:
```bash
curl --location --request PUT \
"https://0.0.0.0:8999/api/v1/containers/10/firewall" \
--header "X-API-Key: clicd_sk_xxxx" \
--header "Content-Type: application/json" \
--data-raw '{"enabled":true,"default_action":"ACCEPT","rules":[{"id":"","network":"ipv4","direction":"in","protocol":"tcp","port":"22","source_ip":"","action":"ACCEPT","description":"Allow SSH","enabled":true}]}'
```
创建 WebSSH 票据:
```bash
curl --location --request POST \
"https://0.0.0.0:8999/api/v1/ssh-ticket" \
--header "X-API-Key: clicd_sk_xxxx" \
--header "Content-Type: application/json" \
--data-raw '{"container_name":"example-vm"}'
```
## 常见问题
### NAT 修改不生效
确认请求体必须是 JSON,不要使用 `multipart/form-data`。正确请求头:
```text
Content-Type: application/json
```
### 防火墙获取提示“不支持的方法”
请确认模块版本已经包含防火墙页签修复。客户区防火墙列表应通过模块公开的 `firewallList` 调用,再由模块向 CLICD 发起:
```text
GET /api/v1/containers/{id}/firewall
```
如果页面或二开代码直接把读取请求改成 `POST /api/v1/containers/{id}/firewall`,CLICD 会返回“不支持的方法”。
### 防火墙保存后规则为空
请确认更新接口最终发往 CLICD 的请求体是 JSON,并且包含 `rules` 数组。防火墙关闭时也可以保存规则,`enabled: false` 不应自动清空 `rules`
正确请求体示例:
```json
{
"enabled": false,
"default_action": "ACCEPT",
"rules": [
{
"id": "",
"network": "ipv4",
"direction": "in",
"protocol": "tcp",
"port": "22",
"source_ip": "",
"action": "ACCEPT",
"description": "Allow SSH",
"enabled": true
}
]
}
```
### 图表刚打开只有一条横线
CLICD 当前用量接口返回的是实时值,不是历史序列。页面刚打开时只有一个采样点,所以会显示当前值横线。选择 `10 秒` 自动刷新或点击“立即刷新”多采样几次后,会逐步形成折线。
### 流量显示为 0
旧版本只显示 GB,小流量换算后会被四舍五入成 `0 GB`。当前版本已改为智能单位,会显示 B / KB / MB / GB。
### 防火墙
防火墙是独立客户区页面,支持:
- 查看防火墙启用状态、默认动作和规则列表
- 启用 / 停用防火墙
- 设置默认动作:未匹配拒绝或未匹配放行
- 添加规则
- 编辑规则
- 删除规则
- 单独启用 / 停用某条规则
页面会先在前端修改规则列表和开关状态,点击“保存设置”后才统一同步到 CLICD。这样可以避免每次切换开关、修改默认动作或编辑规则时都立即请求后端,减少客户区卡顿。
注意:防火墙关闭时也可以保存规则;关闭只表示暂时不接管该容器流量,不代表规则必须清空。
使用的 CLICD API
```text
GET /api/v1/containers/{id}/firewall
PUT /api/v1/containers/{id}/firewall
```
更新防火墙时必须使用 JSON 请求体,例如:
```json
{
"enabled": true,
"default_action": "ACCEPT",
"rules": [
{
"id": "",
"network": "ipv4",
"direction": "in",
"protocol": "tcp",
"port": "22",
"source_ip": "",
"action": "ACCEPT",
"description": "Allow SSH",
"enabled": true
}
]
}
```
规则字段说明:
| 字段 | 说明 |
| --- | --- |
| `network` | 网络范围,常用 `ipv4`,也支持 `ipv6` / `all` |
| `direction` | 方向,`in` 入站,`out` 出站 |
| `protocol` | 协议,`tcp``udp` |
| `port` | 端口,可填写单端口、逗号分隔端口或端口段,例如 `22``80,443``8000-9000` |
| `source_ip` | 来源 IP / CIDR,留空表示任意来源 |
| `action` | 动作,`ACCEPT` 放行,`DROP` 拒绝 |
| `description` | 规则描述 |
| `enabled` | 是否启用该规则 |
IPv4 NAT 入站规则的端口按容器内部端口匹配,不是宿主机公网端口。例如公网 `22023 -> 容器 22`,防火墙规则端口应填写 `22`
## WebSSH 打不开或提示不安全 WebSocket
请确认 CLICD 面板已经启用 HTTPS/WSS,并且魔方服务器配置使用 HTTPS:
```text
server_host = https://0.0.0.0:8999
```
如果仍然使用 `http://`,模块会生成 `ws://` 地址,HTTPS 客户区页面会被浏览器拦截。
如果 WSS 证书正常但仍返回 `Forbidden` 或浏览器显示 `code=1006`,请检查 CLICD 的 WebSSH Origin 白名单。新版 CLICD 已支持放行魔方财务域名,需要把魔方客户区访问域名完整加入白名单,例如:
```text
https://www.example.com
```
注意需要填写浏览器实际访问魔方客户区时的协议和域名,`http` / `https`、带不带 `www` 都要与实际访问地址一致。
### 开通后魔方里的 IP、端口、密码不对
执行“同步状态”或重装 / 改密后,模块会重新拉取容器详情。请确认 CLICD 容器详情接口能返回:
```text
ssh_port
ssh_password
status
```
公网 IP 优先使用 `nat_public_ip/public_ip/host_ip/external_ip/node_ip/nat_host` 等字段;如果接口没有返回,则使用魔方服务器配置的 IP。