> 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/getting-started/reverse-proxy-and-domains.md).

# 反向代理与域名

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. 套接字地址

该地址就是速率限制和被封 IP 记录所使用的地址。如果你的代理没有转发 `X-Forwarded-For`，那么每个访客都会被视为同一个客户端，速率限制也会一起作用于他们。参见 [安全选项](/developer/zh/configuration/security-options.md).

{% hint style="info" %}
**请求正文大小。** 共享诊断报告最多会向 `/api/report`上传 500 KB，如果你启用了 Sentry 前端隧道， `/api/monitoring` 则可接受最多 10 MB 的 envelope。如果你收紧 `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 bundle 中预先写入。运行时将它们传给预构建的 Docker 镜像不会有任何作用——请在 `.env` 之前 `pnpm run build`中设置它们，或者在 `docker build` 之前在你自己的镜像中设置。参见 [使用 Node.js 部署](/developer/zh/getting-started/deploy-with-nodejs.md).
{% endhint %}

{% hint style="info" %}
**MyIP 不实现 `/geo` 端点。** 这些变量只会告诉前端要在 curl 面板中显示哪些主机名。响应 `4.example.com/geo` 的服务是你另外单独运行的。将变量留空，功能就会保持关闭——参见 [与 IPCheck.ing 绑定的功能](/developer/zh/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/configuration/security-options.md) ——速率限制、降速、被封 IP 记录
* [环境变量](/developer/zh/reference/environment-variables.md)
* [API 端点](/developer/zh/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/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.
