> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/zh-tw/getting-started/reverse-proxy-and-domains.md).

# 反向代理與網域

將 MyIP 放在反向代理後方，將 API 存取限制於你的網域，並設定適合 curl 使用的 IP 端點。

MyIP 在埠號上提供純 HTTP 服務 `18966` 且不終結 TLS。對於任何公開部署，請在前面加上反向代理。

## 代理到 MyIP

沒有什麼特別需要設定。將你的代理指向埠號 `18966` 就完成了：

* **不需要處理 WebSocket 升級。** MyIP 的後端是純 HTTP。
* **無 `try_files` 或 SPA 重寫規則。** 前端伺服器已經會回退到 `index.html` 用於像這樣的客戶端路由 `/tools/whois`.
* **無 `/api` 的特殊處理。** 同一個伺服器會將 `/api` 在內部代理到後端。
* **不要加入代理層快取。** MyIP 會設定自己的 `Cache-Control` 依資產類別而定——帶雜湊的資產會在一年內保持不可變， `index.html` 會重新驗證， `/api/*` 預設為 `no-store`。覆寫它會在部署後提供過期頁面。

{% tabs %}
{% tab title="Nginx" %}
{% code title="/etc/nginx/sites-available/myip" %}

```nginx
server {
    listen 443 ssl http2;
    server_name myip.example.com;

    ssl_certificate     /etc/letsencrypt/live/myip.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myip.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:18966;
        proxy_http_version 1.1;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Caddy" %}
{% code title="Caddyfile" %}

```
myip.example.com {
    reverse_proxy 127.0.0.1:18966
}
```

{% endcode %}

Caddy 會處理 TLS 憑證並設定 `X-Forwarded-*` 標頭。
{% endtab %}
{% endtabs %}

### 重要的標頭

後端使用 Express 的 `trust proxy` 設為一跳，並依下列順序解析用戶端 IP：

1. `CF-Connecting-IP` （Cloudflare）
2. 的第一個項目 `X-Forwarded-For`
3. `CF-Connecting-IPv6`
4. socket 位址

速率限制與封鎖 IP 紀錄都會記錄該位址。如果你的代理沒有轉送 `X-Forwarded-For`，每位訪客都會看起來像同一個用戶端，速率限制也會一起套用到所有人。請參見 [安全性選項](/developer/zh-tw/configuration/security-options.md).

{% hint style="info" %}
**請求主體大小。** 共享診斷報告最多會向 `/api/report`傳送 500 KB，而如果你啟用 Sentry 前端通道， `/api/monitoring` 則可接受最大 10 MB 的信封。如果你將 `client_max_body_size` （Nginx 預設為 1 MB），請將其設得高於這些上限。
{% endhint %}

## `ALLOWED_DOMAINS` — 在真實網域上必須

每個 `/api/*` 路由後方有一個 `Referer` 檢查。請求會以 **403** 拒絕，除非 `Referer` 標頭的主機名稱是 `localhost` 或出現在 `ALLOWED_DOMAINS`.

這就是防止其他網站嵌入你的實例並使用你的 API 金鑰與速率限制的機制。這也是最常見的自架錯誤：應用程式載入了，但每個工具都失敗。

{% hint style="danger" %}
如果你將 MyIP 部署在 `https://myip.example.com` 並將 `ALLOWED_DOMAINS` 留空， **整個 API 會回傳 403**。頁面能渲染，但上面的任何功能都無法使用。
{% endhint %}

```bash
ALLOWED_DOMAINS="myip.example.com,www.myip.example.com"
```

精確行為如下，讓你第一次就設定正確：

| 規則           | 細節                                                              |
| ------------ | --------------------------------------------------------------- |
| 分隔符號         | 逗號。 **不含空格** — 項目會以字面值比對，而 `" b.com"` 永遠不會匹配任何內容。               |
| 比對           | 精確的主機名稱。 `example.com` 會 **不** 允許 `sub.example.com`，反之亦然。       |
| `www`        | 另一個獨立的主機名稱。如果兩者都可達，請兩者都列出。                                      |
| 埠號與路徑        | 忽略。 `example.com` 涵蓋 `https://example.com:8443/anything`.       |
| `localhost`  | 無論你如何設定，都一律允許。                                                  |
| 裸 IP 位址      | 視為主機名稱。若要透過 `http://192.168.1.10:18966`，請將 `192.168.1.10` 加入清單。 |
| 缺少 `Referer` | 會被拒絕並回傳 `{"error":"你在做什麼？"}`.                                   |
| 不允許的主機名稱     | 會被拒絕並回傳 `{"error":"拒絕存取"}`.                                     |

{% hint style="info" %}
缺少 `Referer` 一定會被拒絕，這就是為什麼 `curl https://myip.example.com/api/...` 會依設計回傳 403。此 API 是提供給應用程式自己的前端使用，不是用於直接腳本呼叫。
{% endhint %}

## 適合 curl 的 IP 端點

MyIP 有一個「命令列 API」面板，會向訪客顯示一個 `curl` 用來在終端機檢查其 IP 的單行指令。可選的 `/geo` 路徑會在回應中加入地理位置資訊：

```bash
curl 4.example.com
curl 4.example.com/geo
```

三個變數控制面板要列印哪些主機名稱：

| 變數                       | 面板項目            |
| ------------------------ | --------------- |
| `VITE_CURL_IPV4_DOMAIN`  | 取得此機器的 IPv4 位址  |
| `VITE_CURL_IPV6_DOMAIN`  | 取得此機器的 IPv6 位址  |
| `VITE_CURL_IPV64_DOMAIN` | 取得此機器偏好的網路出口 IP |

將它們指向可相應解析的主機名稱——僅 A、僅 AAAA，以及雙堆疊。

{% hint style="warning" %}
**三者都必須設定。** 只有在三者都設定完成時，前端才會顯示 curl 面板；如果有任何一個是空的，該功能就會保持隱藏，對話框也會顯示它不可用。
{% endhint %}

{% hint style="warning" %}
**這些是建置時變數。** 和所有 `VITE_*` 變數一樣，它們會由 Vite 烘焙進 JavaScript 套件中。執行時把它們傳給預先建置的 Docker 映像不會有任何作用——請在 `.env` 之前 `pnpm run build`中設定，或在 `docker build` 之前在你自己的映像中設定。請參見 [使用 Node.js 部署](/developer/zh-tw/getting-started/deploy-with-nodejs.md).
{% endhint %}

{% hint style="info" %}
**MyIP 不會實作 `/geo` 端點。** 這些變數只會告訴前端在 curl 面板中要列印哪些主機名稱。回應 `4.example.com/geo` 的服務是你另外執行的。將這些變數留空，功能就會直接關閉——請參見 [與 IPCheck.ing 綁定的功能](/developer/zh-tw/configuration/features-tied-to-ipcheck-ing.md).
{% endhint %}

## 疑難排解

<details>

<summary>頁面已載入，但每個工具都顯示錯誤</summary>

幾乎總是 `ALLOWED_DOMAINS`。打開瀏覽器的網路分頁，查看 `/api/*`上的 403 回應。回應本文會告訴你遇到的是哪種情況：

* `{"error":"拒絕存取"}` — 主機名稱不在清單中。請加入你在網址列輸入的完全相同主機名稱。
* `{"error":"你在做什麼？"}` — 沒有 `Referer` 到達後端。檢查你的代理或隱私擴充功能是否把它移除了。

變更後請重新啟動後端 `ALLOWED_DOMAINS`.

</details>

<details>

<summary>所有人同時觸發速率限制</summary>

你的代理沒有轉送真正的用戶端 IP，因此所有流量都匯聚到同一個位址。請加入 `X-Forwarded-For` （請參見上方的 Nginx 範例），然後重新啟動。

</details>

<details>

<summary>升級後仍顯示舊內容</summary>

檢查是否在代理或 CDN 上加了快取。MyIP 已經設定了適當的 `Cache-Control` 標頭；如果你的代理快取 `index.html` 時間更長，訪客就會一直載入一個其資產檔案已不存在的建置版本。

</details>

## 後續步驟

* [安全性選項](/developer/zh-tw/configuration/security-options.md) — 速率限制、降速、封鎖 IP 記錄
* [環境變數](/developer/zh-tw/reference/environment-variables.md)
* [API 端點](/developer/zh-tw/reference/api-endpoints.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/zh-tw/getting-started/reverse-proxy-and-domains.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
