HTTPQUERY
English

Host

用法

每个 HTTP/1.1 请求都包含一个 Host 头。该头启用虚拟主机功能,即一台拥有单个 IP 地址的服务器托管多个域名。若没有 Host,服务器将无法确定客户端想要访问的是哪个域名。

其值包含所请求的主机名以及一个可选的端口号,两者以冒号分隔。当未指定端口时,采用该方案的默认端口:HTTP 为 80 端口,HTTPS 为 443 端口。

服务器收到不带 Host 头的 HTTP/1.1 请求时,会返回 400 Bad Request。当请求包含多个 Host 头时也会返回相同的响应,因为这种歧义会使服务器无法选择正确的虚拟主机。

在 HTTP/2 与 HTTP/3 中,:authority 伪头字段取代了 Host。发送 HTTP/2 或 HTTP/3 请求的客户端会将主机信息放入 :authority。当网关将 HTTP/2 请求转换为 HTTP/1.1 时,网关会根据 :authority 值生成 Host 头。

Host 头不同于 Origin 头。Host 为每个请求标识目标服务器。Origin 标识跨源请求的来源,且仅出现在特定场景中,例如 CORS 预检请求和表单提交。

host

目标服务器的域名或 IP 地址。

port

可选的 TCP 端口号。当省略时,采用请求方案的默认端口(HTTP 为 80,HTTPS 为 443)。

Host: <host>:<port>

示例

对 Web 服务器的标准 HTTPS 请求会省略端口,因为 443 是 HTTPS 的默认端口。

GET /articles/http-headers HTTP/1.1
Host: example.re

当服务器运行在非标准端口上时,端口号会跟在主机名之后。

GET /api/status HTTP/1.1
Host: api.example.re:8443

对 IP 地址的请求会直接包含该地址。这种形式在开发环境和内部服务中很常见。

GET /health HTTP/1.1
Host: 192.168.1.100:3000

安全

当应用程序在未先验证 Host 值的情况下使用它来生成 URL(密码重置链接、规范 URL、重定向)时,就会发生 Host 头注入。攻击者发送一个带有伪造 Host 值的请求,导致应用程序生成指向攻击者控制域名的链接。

对照一份预期值白名单来验证 Host 头。在 nginx 中,定义一个带有 server_name 的默认兜底 server 块并返回 444。在 Django 中,将 ALLOWED_HOSTS 设为允许的域名列表。在 Rails 中,在应用环境中配置 host_authorization。浏览器将 Host 视为禁止的请求头,阻止客户端 JavaScript 修改该值,但服务器到服务器的请求以及像 curl 这样的工具则不受此限制。