# Avatar Proxy 和 CDN 热链保护

**URL:** <https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525>\
**Category:** Support\
**Created:** [2025年二月4日 22:18 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525 "2025-02-04T22:18:57Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![LotusJeff](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lotusjeff/32/477888_2.png) [@LotusJeff](https://meta.discourse.org/u/LotusJeff)\
**Post date:** [2025年二月4日 22:18 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/1 "2025-02-04T22:18:57Z")

</div>

我的 Discourse 站点包含大量图片。由于图片数量众多，我使用 S3/CDN 组合来存储和提供图片。在 CDN 中，我采取了各种措施来防止图片劫持。其中一项措施是阻止所有对图片的直接访问，只允许从定义的 hostname 列表访问。

Discourse 可以与此设置配合使用，但头像（Avatars）除外。当启用热链接保护时，头像将停止工作。

原因是 Discourse 对头像使用代理设置。HTML 使用代理链接来显示头像。链接结构为 `https://discourse.forum/user_avatar/discourse.forums/username/24/616_2.png`。  
一旦代理被解析，浏览器就会直接请求访问图片文件。

我的 CDN 在进行此直接请求时会阻止直接访问并返回 403。所有自定义头像都会变成剪影。

我们有什么选项可以移除代理？  
我们可以将头像更改为标准的图片文件结构吗？

---

<div class="post-metadata">

**Author:** ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)\
**Post date:** [2025年二月5日 06:30 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/2 "2025-02-05T06:30:40Z")

</div>

您不能将 Discourse 的 IP 地址列入白名单吗？

---

<div class="post-metadata">

**Author:** ![LotusJeff](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lotusjeff/32/477888_2.png) [@LotusJeff](https://meta.discourse.org/u/LotusJeff)\
**Post date:** [2025年二月5日 11:17 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/3 "2025-02-05T11:17:25Z")

</div>

直接访问链接的调用来自用户的 IP 地址。服务器会解析信息，但本地浏览器会执行调用。

---

<div class="post-metadata">

**Author:** ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)\
**Post date:** [2025年二月5日 12:30 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/4 "2025-02-05T12:30:10Z")

</div>

我不确定它是否那样工作。根据您的配置，代理实际上是代理还是CDN优先。您能否详细说明一下设置方式？

---

<div class="post-metadata">

**Author:** ![LotusJeff](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lotusjeff/32/477888_2.png) [@LotusJeff](https://meta.discourse.org/u/LotusJeff)\
**Post date:** [2025年二月5日 14:57 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/5 "2025-02-05T14:57:06Z")

</div>

> [@michaeld](#):
>
> 您能详细说明一下这是如何设置的吗？

我讨厌含糊不清的问题。你问“这个”的时候在想什么？

这是我当前的设置：

### Discourse 设置：

- 标准单容器安装
- 设置为子域名： forums.domain.tld
- 标准 S3 设置用于上传
- 上传文件保存在 S3 上

### S3 设置：

- Digital Ocean S3 存储桶
- 存储桶已开启外部访问
- 没有其他安全层或权限

### CDN 设置：

- bunny CDN
- 允许的引用者设置： domain.tld 和 \*.domain.tld
- 导致头像访问被禁止的开关是“阻止直接 URL 文件访问”。

开启后，所有头像都收到 403 错误。关闭后，头像可以正常显示。

非头像图片：

- Discourse 中的 URL： `https://cdn.domain.tld/optimized/3X/3/1/filename_#_size.jpeg`

头像图片：

- Discourse 中的 URL： `https://forums.domain.tld/user_avatar/forums.domain.tld/mazzini/48/776_2.png`

之前的一篇帖子 [头像如何存储和访问？](https://meta.discourse.org/t/how-are-avatars-stored-and-accessed/53065/1) 表明 Discourse 使用代理来处理头像。因此，头像的 URL 结构不是标准的图片 URL 结构。

在我的系统中，头像可以通过 S3 或 CDN 访问。这表明在某个地方/以某种方式，头像 URL 被转换为 CDN URL。

当这种情况发生时，CDN 会将该 URL 视为直接访问链接并以 403 错误阻止访问。

希望我回答了“这个”问题？

---

<div class="post-metadata">

**Author:** ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)\
**Post date:** [2025年二月5日 16:44 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/6 "2025-02-05T16:44:42Z")

</div>

> [@LotusJeff](#):
>
> I hate vague questions.

And I hate it when people respond like that when I am spending my time in helping them, so that makes it a draw 😉.

> [@LotusJeff](#):
>
> indicates Discourse uses a proxy for avatars. Hence, the URL structure for avatars is not a standard image URL structure.
> 
> Within my system, avatars are either available from the S3 or the CDN. This indicates that some where/some how the avatar URL is converted to a CDN URL.

Yes, and “proxy” means that the request passes _through_ Discourse. The request is not made by the browser to the CDN but by Discourse.

Did you set up the CDN as a full site CDN or as the S3 CDN ? I suspect the latter. And in that case the request is made by Discourse to the CDN, without a referrer. But the CDN can still recognize that it is a legit request because the request is originating from the Discourse IP. Hence my advice to whitelist it.

Edit: you could check by turning off the protection for a short while and looking at the logs in Bunny, and see which IP they’re coming from.

---

<div class="post-metadata">

**Author:** ![LotusJeff](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lotusjeff/32/477888_2.png) [@LotusJeff](https://meta.discourse.org/u/LotusJeff)\
**Post date:** [2025年二月5日 19:17 UTC](https://meta.discourse.org/t/avatar-proxy-and-cdn-hot-link-protection/350525/7 "2025-02-05T19:17:27Z")

</div>

我感谢您的帮助。在 IT 开发和支持领域工作了几十年后，含糊不清的问题和答复会产生不必要的额外工作。根据您的经验，我认为您也会同意这一点。

CDN 仅为 S3 存储桶设置。

在提交原始主题之前，我确实检查了与 403 错误相关的 Discourse IP 的 CDN 日志。它不在日志文件中。

根据您的评论，我回去重新分析了日志。在查看了最大的 IP 违规者后，我发现排名前几位是托管公司的网关。

挑战在于，我不想跟踪 Digital Ocean 的网关 IP 地址，以便我的 Discourse 服务器能够正确显示图像。

感谢您的协助。
