出站图片下载的 SSRF 防护

封面图与正文图片的地址来自用户可控的请求体与正文 HTML,插件会从 Halo 服务端主动拉取这些地址,属于典型的 SSRF 面。为此在统一下载入口施加了纵深防御:

  1. URL 结构校验:用 URI 解析器处理地址,仅允许 http/https,必须含合法主机名,禁止携带用户名/密码(userinfo)等易被用于绕过的结构。
  2. 解析后的 IP 校验:发起下载前解析目标主机的全部 IPv4/IPv6 地址,逐一拒绝环回、私网(站点本地)、链路本地、组播、未指定地址,以及运营商级 NAT(100.64.0.0/10,含云平台元数据地址)、IPv6 唯一本地地址(fc00::/7)与各类测试网段。
  3. 实际连接目标校验:下载客户端使用自定义地址解析器,在 Netty 真正建立连接前对解析到的每个 IP 再次执行同一套限制,堵住「预检解析到公网、连接时解析到内网」的 DNS rebinding(TOCTOU)时间差。
  4. 禁止重定向:下载客户端关闭自动重定向,遇到 3xx 直接拒绝,防止公网地址跳转到内网绕过校验。
  5. 超时与体积上限:为连接、读写与整体响应设置超时,并限制响应体最大 16 MB,避免出站请求长期占用连接、事件循环或内存。

说明:默认会拒绝内网/环回地址,因此封面与正文图片需为公网可访问的地址。若使用相对路径,请在 Halo「基本设置 - 外部访问地址」中配置可公网访问的站点地址(详见配置)。若 Halo 本身部署在内网、图片也位于内网地址,请按内网部署与图片下载白名单配置白名单。