在 Nginx 的配置与运维中,精准获取当前域名是实现动态路由、SSL 证书自动匹配以及安全重定向的基础。核心上文归纳是:在绝大多数场景下,应优先使用 $host 变量来获取当前域名,而非 $http_host 或 $server_name,因为它在保证功能完整性的同时,提供了最佳的安全性和兼容性。 正确理解并运用这些变量,不仅能解决多域名部署时的逻辑冲突,还能有效防范基于 Host 头的攻击,是构建高可用 Web 服务的必备技能。

深入解析 Nginx 获取当前域名的核心变量
在 Nginx 中,获取“当前域名”并非只有一个指令,不同的变量代表了不同的获取逻辑和优先级,理解它们的细微差别,是写出专业配置的前提。
$host:最推荐的通用变量
$host 是 Nginx 处理请求时最核心的变量,它的优先级逻辑非常严密:首先检查请求行中的域名(如 GET / HTTP/1.1 中的部分),如果请求行中没有,则检查请求头中的 Host 字段,如果这两者都不存在,它最终会回退到匹配该请求的 server_name 配置。
关键特性:Nginx 会自动过滤掉 $host 中的端口号(80 或 443),只保留纯净的域名,这使得它在用于重定向或作为路径参数时最为安全可靠,避免了因端口拼接导致的死循环或路径错误。
$http_host:原始请求头的忠实记录
该变量直接取自客户端发送的 HTTP 请求头中的 Host 字段,这意味着它包含了客户端提供的所有信息,通常包括端口号(example.com:8080)。
使用风险:如果客户端发送了一个伪造的或者格式错误的 Host 头,$http_host 会原封不动地传递下去,在缺乏严格校验的情况下直接使用该变量进行重定向或缓存键生成,可能会导致安全隐患,除非有特殊需求(如必须保留原始端口),否则不建议作为首选。
$server_name:配置文件中的静态定义
这个变量取自 nginx.conf 中 server 块里定义的 server_name 值,它并不代表客户端实际访问的域名,而是代表 Nginx 认为该虚拟主机应该响应的域名。
局限性:如果一个 server 块配置了通配符(如 *.example.com)或正则表达式,$server_name 可能会返回配置的原始字符串,而不是用户具体访问的子域名,用它来代表“当前访问域名”往往是不准确的。
实战场景中的专业解决方案
掌握了变量特性后,我们需要将其应用到具体的业务场景中,以解决实际问题。
HTTP 到 HTTPS 的智能强制跳转
在配置全站 HTTPS 时,很多初级配置会硬编码域名,但在多域名或 CDN 加速场景下,硬编码会导致维护困难。
专业配置方案:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
解析:使用 $host 而非硬编码,意味着该配置块可以复用于任意域名,当用户访问 example.com 时跳转到 https://example.com,访问 www.example.com 时跳转到 https://www.example.com,这种方式极大地提升了配置的灵活性和可维护性。

反向代理中的 Host 头传递
在 Nginx 作为反向代理时,后端服务器往往需要知道客户端原本访问的域名,以便生成正确的跳转链接或 Session Cookie。
专业配置方案:
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
解析:这里必须使用 proxy_set_header Host $host;,如果缺失此行,后端服务器收到的 Host 可能会是 Nginx 的 upstream 名称(如 backend_server),导致应用无法识别域名,从而造成资源加载失败(CSS/JS 404)或重定向错误。注意:如果后端应用需要处理非标准端口,则应考虑使用 $http_host,但通常情况下 $host 更符合标准 Web 架构。
基于域名的动态访问控制与日志分割
在运营多个虚拟主机或 SaaS 平台时,往往需要根据域名做不同的逻辑处理。
解决方案:
利用 map 指令结合 $host,可以实现复杂的动态逻辑。
map $host $root_path {
default /var/www/default;
example.com /var/www/site1;
app.example.com /var/www/app;
}
server {
...
root $root_path;
}
解析:这种配置允许在一个 server 块内处理成百上千个域名的根目录映射,而不需要为每个域名重复编写配置文件,这不仅精简了配置,还降低了管理开销。
安全视角:防范 Host 头攻击
从 E-E-A-T 的安全角度来看,直接信任并使用客户端传入的 Host 头存在风险,攻击者可以通过修改 HTTP Header 中的 Host 字段为恶意域名(如 evil.com),利用应用程序的信任机制进行密码重置投毒或缓存投毒。
独立见解与防御策略:
不要盲目信任 $http_host,在业务逻辑必须使用 Host 头进行跳转或生成链接时,应在 Nginx 层面建立一个“白名单”校验机制。
防御配置示例:
server {
listen 80;
server_name example.com www.example.com;
if ($host !~* ^(example.com|www.example.com)$) {
return 403;
}
# 后续业务处理...
}
解析:通过 if 指令校验 $host 变量,强制阻断不符合白名单的域名请求,这种“防御纵深”策略将安全拦截前置到 Web 服务器层,减轻了后端应用的压力,是专业运维的标准操作。

在 Nginx 中获取当前域名,看似简单,实则暗藏玄机。$host 变量凭借其优先级逻辑和自动清理端口的特性,成为了连接用户请求与服务器响应的最佳纽带。 无论是处理 HTTPS 跳转、反向代理传递,还是构建动态路由,合理运用 $host 并配合必要的安全校验,是构建高性能、高安全 Web 服务的基石,摒弃硬编码,拒绝盲目信任 $http_host,才能在复杂的网络环境中游刃有余。
相关问答
Q1:在 Nginx 配置 SSL 证书时,如何确保证书与当前访问的域名匹配?
A: Nginx 在处理 SSL 握手时,主要通过 SNI(Server Name Indication)技术来识别域名,Nginx 依据客户端发送的 SNI 信息(即请求行中的域名)来选择对应的 server 块和证书,虽然 $host 在 HTTP 阶段才发挥作用,但确保 server_name 指令包含了所有需要 SSL 证书的域名(或通配符),是实现正确匹配的关键。server_name 配置错误,Nginx 可能会返回默认证书或握手失败。
Q2:为什么有时候使用 $host 重定向后,URL 中会丢失端口号?
A: 这是 $host 变量的预期行为,如前所述,$host 的设计初衷是剥离端口号,只保留主机名,如果你的服务运行在非标准端口(如 8080),并且重定向后需要保留该端口,应该使用 $http_host 或者手动拼接 $server_port。return 301 https://$host:$server_port$request_uri;,但在标准 80/443 端口下,使用 $host 是最简洁的做法。
如果您在配置 Nginx 域名相关的过程中遇到了棘手的问题,或者有独特的配置技巧,欢迎在评论区分享您的经验,我们一起探讨交流。


















