跳至主要內容

Nginx 请求头相关配置

鸟书大约 14 分钟webnginxconfig 配置proxy_set_header

Nginx 请求头相关配置

proxy_set_header Host $host

proxy_set_header Host $host; 这一行的作用是确保在代理请求发送到后端服务器时,Host 请求头会被正确地设置。

Host 请求头在 HTTP 协议中用于指定请求的目标服务器和端口号。这对于虚拟主机的实现至关重要,因为不同的域名(或子域名)可以映射到同一台物理服务器上的不同网站。当一个客户端发送请求时,Host 头告诉服务器哪个虚拟主机或网站应该处理这个请求。

在 Nginx 作为反向代理的情况下,原始请求会到达 Nginx,然后 Nginx 再将请求转发给后端服务器。然而,当 Nginx 转发请求时,如果不显式设置 Host 头,后端服务器接收到的 Host 头可能会是 Nginx 的监听地址,而不是客户端请求中指定的域名。

proxy_set_header Host $host; 确保了 Nginx 在转发请求时将原始请求中的 Host 头部原封不动地传递给后端服务器。这里的 $host 是 Nginx 的一个预定义变量,它包含了请求中 Host 头部的原始值。

例如,如果客户端向 birdbook.com.cn 发送请求,Host 头部将包含 birdbook.com.cn。即使 Nginx 的监听地址是 192.168.1.10,Nginx 也会确保后端服务器接收到的 Host 头部仍然是 birdbook.com.cn

这在处理虚拟主机和子域名时尤为重要,因为后端服务器可能需要根据 Host 头部来决定如何处理请求,例如查找正确的配置、数据库或文件路径。

总之,proxy_set_header Host $host; 保证了后端服务器能够获得正确的 Host 信息,从而能够正确地识别和处理请求。

proxy_set_header X-Real-IP $remote_addr

proxy_set_header X-Real-IP $remote_addr; 这一行的作用是设置一个名为X-Real-IP的HTTP请求头,其值为发起请求的实际客户端的IP地址。

当Nginx作为反向代理服务器时,它接收来自客户端的请求,然后将这些请求转发给后端服务器。在转发请求的过程中,Nginx可能会修改或添加一些HTTP头部信息,以提供关于请求的附加信息给后端服务器。

$remote_addr 是Nginx的一个预定义变量,它包含了发起请求的客户端的IP地址。当Nginx将请求转发给后端服务器时,它本身看起来像是请求的源头,后端服务器看到的客户端IP地址实际上是Nginx的IP地址,而不是实际客户端的IP地址。

通过设置 proxy_set_header X-Real-IP $remote_addr; Nginx会在转发的请求中添加一个X-Real-IP头部,其值就是实际客户端的IP地址。这样,后端服务器就可以通过读取这个头部来获取真实客户端的IP地址,这对于日志记录、统计分析、地理定位、安全策略(如IP黑名单或白名单)等用途非常重要。

例如,如果你在后端服务器的日志配置中设置了记录 X-Real-IP 头部,那么在日志文件中,你将能够看到每个请求的真实来源IP,而不是Nginx服务器的IP。

需要注意的是,当Nginx运行在负载均衡器、防火墙或云服务环境中时,实际客户端的IP地址可能经过NAT(网络地址转换)或由其他中间设备修改。在这种情况下,$remote_addr 可能不是真正的客户端IP。为了解决这个问题,你可以使用 real_ip 模块和 set_real_ip_from 指令来更准确地确定客户端的IP地址。

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 这一行用于处理和传递客户端的 IP 地址信息,特别是在多层代理或负载均衡环境下。

X-Forwarded-For 是一个常用的 HTTP 标头,用于记录客户端 IP 地址和代理服务器的信息。当一个 HTTP 请求通过多个代理服务器时,每个代理服务器都会在 X-Forwarded-For 标头中添加自己的 IP 地址,以便后端服务器可以追踪请求的完整路径。

$proxy_add_x_forwarded_for 是 Nginx 的一个特殊变量,它在代理请求时被自动设置。这个变量包含了之前代理服务器(如果有)添加到 X-Forwarded-For 标头中的 IP 地址列表,以及当前请求的客户端 IP 地址。

当 Nginx 作为反向代理转发请求时,proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 指令会将 $proxy_add_x_forwarded_for 的值设置为 X-Forwarded-For 标头的值。如果请求中已经有了 X-Forwarded-For 标头,Nginx 会将当前客户端的 IP 地址追加到标头的最前面;如果没有,Nginx 会创建一个新的 X-Forwarded-For 标头,并将客户端的 IP 地址作为唯一的元素。

例如,如果请求通过了两个 Nginx 代理实例:

  1. 第一个代理实例(A)接收到客户端请求,其 IP 地址为 192.168.1.1
  2. A 将请求转发给第二个代理实例(B),并设置 X-Forwarded-For: 192.168.1.1
  3. B 接收到请求,其 $proxy_add_x_forwarded_for 变量现在包含 192.168.1.1,B 的客户端 IP 地址为 192.168.2.1
  4. B 将请求转发给最终的后端服务器,并设置 X-Forwarded-For: 192.168.2.1, 192.168.1.1

最终,后端服务器会收到一个 X-Forwarded-For 标头,其中包含了所有代理服务器的 IP 地址,以及最初客户端的 IP 地址。

使用 X-Forwarded-For$proxy_add_x_forwarded_for 可以帮助后端服务器正确识别客户端的真实 IP 地址,这对于日志记录、安全审计、地理定位和限流等任务至关重要。然而,由于 X-Forwarded-For 标头可以被伪造,因此在安全敏感的应用中,应结合使用可信的代理列表或 IP 白名单来验证这个标头的准确性。

proxy_set_header X-Forwarded-Proto $scheme

proxy_set_header X-Forwarded-Proto $scheme; 这一行的作用是设置一个名为 X-Forwarded-Proto 的 HTTP 请求头,其值反映了客户端请求所使用的协议,即 httphttps

$scheme 是 Nginx 的一个预定义变量,它根据请求到达 Nginx 的方式自动获取正确的协议值。如果请求是通过 HTTP 发送的,$scheme 的值将是 http;如果请求是通过 HTTPS 发送的,$scheme 的值将是 https

当 Nginx 作为反向代理运行时,它可能接收来自客户端的 HTTP 或 HTTPS 请求,然后将这些请求转发给后端服务器。后端服务器可能无法直接判断原始请求的协议类型,尤其是在 Nginx 进行 SSL 终止(SSL termination)的情况下,即 Nginx 负责处理 SSL 加密和解密,而后端服务器只处理纯文本 HTTP 流量。

X-Forwarded-Proto 头部对于后端服务器来说非常重要,因为它可以帮助后端服务确定原始请求的协议类型。这在以下场景中尤其有用:

  1. 重定向:后端服务可能需要根据请求的协议类型进行重定向,例如,将 HTTP 请求重定向到 HTTPS。
  2. URL 构建:后端服务可能需要生成指向自身的链接或资源,这些链接的格式应与原始请求的协议匹配。
  3. 安全策略:后端服务可能基于请求的协议类型执行不同的安全策略,例如,只允许 HTTPS 请求访问某些资源。

通过在 Nginx 的代理设置中使用 proxy_set_header X-Forwarded-Proto $scheme;,后端服务器可以从 X-Forwarded-Proto 头部中获取原始请求的协议信息,从而能够做出正确的决策和响应。这有助于确保后端服务的行为与客户端期望的一致,无论请求是通过 HTTP 还是 HTTPS 发起的

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Upgrade $http_upgrade; 这一行用于处理 HTTP 升级请求,特别适用于 WebSocket 和其他需要从标准的 HTTP 协议升级到更高级协议的场景。

Upgrade 是一个特殊的 HTTP 请求头,用于通知服务器客户端想要升级连接到另一个协议。例如,WebSocket 使用这个头部来协商从 HTTP/HTTPS 到 WebSocket 协议的升级。在 WebSocket 的握手过程中,客户端发送一个带有 Upgrade: websocket 的请求头。

$http_upgrade 是 Nginx 中的一个内部变量,它在接收到带有 Upgrade 请求头的请求时被设置。如果请求中有 Upgrade 头,$http_upgrade 将包含该头的值;如果没有,则为空。

当 Nginx 作为反向代理工作,并且需要将请求代理到后端服务器时,proxy_set_header Upgrade $http_upgrade; 会确保 Nginx 正确地将 Upgrade 请求头传递给后端服务器。这对于 WebSocket 连接是必要的,因为 WebSocket 的握手过程依赖于 UpgradeConnection: Upgrade 头部。

如果 Nginx 没有正确转发 Upgrade 头部,后端服务器可能不会识别这是一个升级请求,从而导致 WebSocket 握手失败,连接不能建立。

此外,通常还会配合使用 proxy_set_header Connection "upgrade";,以确保连接保持打开并允许升级。这是因为 HTTP/1.1 默认在请求完成后关闭连接,但升级到 WebSocket 需要保持连接打开。

综上所述,proxy_set_header Upgrade $http_upgrade; 在 Nginx 中的作用是保证 HTTP 升级请求能够被正确处理和转发,这对于 WebSocket 和其他类似的协议至关重要。

proxy_set_header Connection "upgrade";

proxy_set_header Connection "upgrade"; 这一行用于确保代理请求支持协议升级,尤其是当涉及到如 WebSocket 这样的长连接协议时。

在 HTTP/1.1 中,Connection 请求头用于指示连接在响应完成后的行为。默认情况下,HTTP/1.1 使用持久连接(keep-alive),这意味着客户端和服务器之间的 TCP 连接在请求结束后保持打开,直到超时或显式关闭。

然而,当使用 WebSocket 或其他需要从 HTTP 升级到更高层协议的服务时,Connection 头必须被设置为 "upgrade"。这是因为在升级过程中,客户端和服务器同意将连接从 HTTP 升级到另一种协议,如 WebSocket,此时连接将不再遵循 HTTP 的规则,而是遵循新协议的规则。

在 Nginx 中,proxy_set_header Connection "upgrade"; 确保当代理请求到后端服务器时,Connection 头部被设置为 "upgrade"。这对于 WebSocket 连接至关重要,因为如果 Nginx 不正确地设置此头部,后端服务器可能不会理解这是一个升级请求,从而导致升级失败,WebSocket 连接无法建立。

通常,proxy_set_header Connection "upgrade"; 会与 proxy_set_header Upgrade $http_upgrade; 配合使用。Upgrade 头部用于指示升级到的协议类型,而 Connection 头部中的 "upgrade" 值则是告知服务器此连接期望升级到该协议。

总之,proxy_set_header Connection "upgrade"; 在 Nginx 中的作用是确保代理请求在需要协议升级(如从 HTTP 到 WebSocket)时能够正确地标识连接意图,从而顺利进行协议升级和建立长连接。

proxy_cache_bypass $http_upgrade;

proxy_cache_bypass $http_upgrade; 这一行指令用于控制 Nginx 的缓存机制,确保当请求中包含 Upgrade 头部时,这些请求不会被缓存。这对于 WebSocket 和其他需要实时通信的协议非常重要,因为这类协议通常要求服务器和客户端之间保持持续的双向通信,而不希望中间的代理服务器对这些交互进行缓存。

$http_upgrade 是 Nginx 的一个内部变量,它在请求包含 Upgrade 头部时被设置。当 Nginx 接收到带有 Upgrade 头部的请求时,$http_upgrade 变量将包含该头部的值。如果请求中没有 Upgrade 头部,$http_upgrade 将为空或未设置。

proxy_cache_bypass 指令用于指定哪些请求应绕过缓存。当 proxy_cache_bypass 后跟 $http_upgrade 时,Nginx 会检查请求中是否存在 Upgrade 头部。如果存在,请求将不会被缓存,而是直接转发给后端服务器。这是必需的,因为 WebSocket 升级请求和连接需要即时响应,而不能被缓存。

例如,在 WebSocket 的场景中,客户端会发送一个带有 Upgrade: websocket 的请求头,尝试与服务器建立 WebSocket 连接。如果 Nginx 被配置为缓存此类请求,那么 WebSocket 的握手过程可能被错误地缓存,导致连接无法正常升级或工作。为了避免这种情况,proxy_cache_bypass $http_upgrade; 确保了所有带有 Upgrade 头部的请求都被直接发送到后端服务器,而不经过缓存。

简而言之,proxy_cache_bypass $http_upgrade; 确保了 Nginx 不会对带有 Upgrade 头部的请求进行缓存,这对于 WebSocket 和其他实时通信协议的正确运作是必要的。

proxy_no_cache $http_upgrade

proxy_no_cache $http_upgrade; 这一行指令的作用与 proxy_cache_bypass $http_upgrade; 类似,都是为了防止带有 Upgrade 请求头的请求被缓存。然而,两者之间存在细微差别。

proxy_no_cache 指令用于控制 Nginx 是否对代理的响应进行缓存。当 proxy_no_cache 后跟 $http_upgrade 时,Nginx 会检查请求中是否包含 Upgrade 头部。如果存在 Upgrade 头部,Nginx 将不会缓存从后端服务器返回的响应。

$http_upgrade 是一个内部变量,当请求包含 Upgrade 头部时,该变量会被设置。如果请求是用于建立 WebSocket 连接或其他需要升级的连接类型,$http_upgrade 将包含该头部的值。

使用 proxy_no_cache $http_upgrade; 的主要目的是确保实时通信协议如 WebSocket 的正常工作。由于 WebSocket 需要保持一个持续的、双向的连接状态,任何对响应的缓存都可能导致通信异常,因为缓存的数据可能不再是实时的或有效的。

通过设置 proxy_no_cache $http_upgrade;,Nginx 保证了任何带有 Upgrade 请求头的请求及其响应都不会被缓存,从而确保了实时通信的准确性和时效性。

总结来说,proxy_no_cache $http_upgrade; 指令在 Nginx 中的作用是禁止对带有 Upgrade 请求头的请求的响应进行缓存,这对于需要即时响应和实时数据传输的应用场景(如 WebSocket)至关重要。

proxy_read_timeout xx

proxy_read_timeout 指令用于设置 Nginx 代理在等待从后端服务器读取响应数据时的最大等待时间。这是一个非常重要的参数,特别是在处理长时间运行的请求或实时通信协议(如 WebSocket)时。

proxy_read_timeout 的默认值通常是 60 秒。如果 Nginx 在指定的时间内未能从后端服务器接收到完整的响应,它将终止连接并返回一个错误给客户端。这个超时值对于确保 Nginx 的稳定性和响应性是必要的,因为它可以防止因后端服务器的延迟或故障而导致的无限等待。

当配置 WebSocket 支持时,通常会将 proxy_read_timeout 设置为一个较高的值,因为 WebSocket 连接可能在很长一段时间内保持活跃,但期间可能只有少量的数据传输。例如,你可能会看到类似以下的配置:

proxy_read_timeout 86400;

这里,86400 表示超时时间为 86400 秒,即 24 小时。这个值虽然非常高,但对于 WebSocket 连接来说是合理的,因为它们可能需要保持活动状态很长一段时间,而实际的数据传输可能只占其中很小的一部分时间。

需要注意的是,设置过高的 proxy_read_timeout 值可能会占用更多资源,因为 Nginx 将保持这些连接更长时间。因此,合理设置这个值取决于你的应用程序的需求、预期的后端响应时间和可用的系统资源。

总之,proxy_read_timeout 指令在 Nginx 中的作用是控制代理服务器等待后端响应的最长等待时间,这对于避免无限等待和及时处理后端延迟或故障情况非常重要。在配置 WebSocket 或其他长时间运行的连接时,可能需要根据具体需求调整这个超时值。