# 存取控制

本頁說明 go-pve-qemu 的三層防護：CORS 來源限制、`ALLOW_IPS` 白名單，以及每台 VM 的狀態與鎖定檢查。

## 第一層：CORS

所有請求經過 CORS 中介層：

| `Origin` | 回應 |
|---|---|
| 私有 IP（`10.0.0.0/8`、`172.16.0.0/12`、`192.168.0.0/16`），且與伺服器所在 `/24` 子網相同 | `Access-Control-Allow-Origin` 回傳該 Origin |
| 其他來源 | 不設定 `Access-Control-Allow-Origin` |
| 無 `Origin`（curl、伺服器端呼叫） | 不受影響 |

伺服器子網取自第一個非 loopback、私有網段的 IPv4 介面；找不到時以 `192.168.0.*` 計。允許的方法為 `GET`、`POST`、`OPTIONS`，`OPTIONS` 預檢直接回 `204`。

CORS 只約束瀏覽器，不是身分驗證。

## 第二層：`ALLOW_IPS`

所有寫入端點（install、start、stop、shutdown、reboot、destroy、set/*）先比對來源 IP：

| `ALLOW_IPS` | 行為 |
|---|---|
| `0.0.0.0` | 全部放行 |
| `192.168.0.10,192.168.0.20` | 只放行列出的 IP |
| 未設定或空字串 | 全部拒絕 |

來源 IP 取自 Gin 的 `c.ClientIP()`。服務未設定受信任代理，Gin 預設會採用 `X-Forwarded-For`／`X-Real-IP` 標頭，因此 API 直接對外時，用戶端可偽造來源 IP；請只在受控網段內開放此服務。

被拒絕時的回應：

| 端點類型 | 回應 |
|---|---|
| 同步端點 | `403 this IP is not allowed to perform this action` |
| SSE 端點 | `200`，內容為一行 `data: {"message": "...this IP is not allowed to perform this action"}` |

查詢端點（health、list、status）不檢查 `ALLOW_IPS`。

## 第三層：VM 狀態與停用清單

需要指定 VM 的寫入端點會以 `pvesh get /cluster/resources` 與 [`.go_qemu_disabled`](/zh/state-files) 檢查目標 VM：

| 檢查 | 失敗回應 |
|---|---|
| VM 在停用清單中 | `400 this IP is not allowed to be controlled` |
| 要求執行中但 VM 已停止 | `400 VM is not running` |
| 要求停止但 VM 執行中 | `400 VM is running` |
| 叢集資料或停用清單讀取失敗 | `500 failed to get VM list: ...` |

| 要求 VM 執行中 | 要求 VM 停止 |
|---|---|
| stop、shutdown、reboot | start、destroy、set/cpu、set/memory、set/disk、set/node |

SSE 端點的檢查失敗同樣以一行 `data:` 回傳錯誤訊息。
