nginx 反向代理(打通网络)

251 阅读3分钟

背景

我们在做开发时会有一些情况需要,生产测试互访。但是这种网络打通的机器较少。我们可以通过nginx反向代理来打通网络。

任意请求转发配置

http {
  resolver  8.8.8.8 valid=5s;

  server {
    listen 80;
    server_name _;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_buffering off;
      proxy_pass "http://$host";
    }
  }
}

Nginx 配置文件片段展示了一个基本的反向代理设置。在这个配置中,Nginx 作为反向代理将请求转发到一个与请求的主机名相同的后端服务器。以下是对这个配置的详细解释:

配置解析

  1. resolver 8.8.8.8 valid=5s;

    • 这行配置定义了一个 DNS 解析器,使用 Google 的公共 DNS 服务器 8.8.8.8valid=5s 指定了解析结果的缓存时间为 5 秒。这在需要动态解析主机名时非常有用,例如在 proxy_pass 中使用变量时。
  2. server

    • 定义了一个监听在 80 端口的服务器块,server_name _; 表示匹配所有主机名请求。
  3. location /

    • 处理所有路径为 / 的请求。
  4. proxy_set_header 指令

    • 这些指令用于设置请求转发到后端服务器时的 HTTP 头:
      • X-Real-IP:将客户端的真实 IP 地址传递给后端服务器。
      • Host:传递原始请求的主机头。
      • X-Forwarded-For:传递客户端的原始 IP 地址以及代理链。
      • X-Forwarded-Proto:传递使用的协议(HTTP 或 HTTPS)。
  5. proxy_buffering off;

    • 关闭代理缓冲。这意味着响应数据会立即传递给客户端,而不是先缓存在 Nginx 中。这在某些需要实时传输数据的场景中很有用。
  6. proxy_pass "http://$host";

    • 将请求转发到一个与请求主机名相对应的后端服务器。这里使用了 $host 变量,它包含了请求中的主机名。这意味着 Nginx 会尝试将请求转发到与请求主机名相同的后端服务器。

注意事项

  • 使用 $host 作为 proxy_pass 的目标可能会导致安全问题,因为它依赖于客户端发送的 Host 头。如果未正确配置,可能导致未授权的请求被转发到错误的后端服务器。
  • 如果使用 $host,确保后端服务器能够处理所有可能的主机名,或者使用更严格的 server_name 配置来限制接受的主机名。 (nginx $host 内置变量 详解
  • 在生产环境中,通常会将 proxy_pass 指向一个具体的后端服务器或负载均衡群组,而不是依赖请求的主机名。

这个配置适用于简单的反向代理场景,但在复杂环境中,可能需要进一步的安全和性能优化。

也可以通过如下方式来限制转发范围:

if ($host = 'xx.xxx.com') {
  proxy_pass http://xx.xxx.com';
}

另一种方式通过请求头中的ProxyAddr 进行跳转

location = / { 
proxy_pass $http_ProxyAddr; // proxyAddr是请求的实际地址 proxy_set_header 
Cookie "$http_SessionId"; // sessionId为cookie
}

在这个 Nginx 配置片段中,你尝试使用变量 $http_ProxyAddr$http_SessionId 来设置 proxy_passCookie 头。然而,直接这样使用可能会导致一些问题。以下是对这个配置的分析和建议:

配置解析

  1. location = /

    • 这个 location 块仅匹配请求路径为 / 的请求。
  2. proxy_pass $http_ProxyAddr;

    • 这里你试图使用 $http_ProxyAddr 作为 proxy_pass 的目标。需要注意的是,Nginx 中的 $http_ 前缀变量通常用于访问请求头中的值。如果请求头中有一个名为 ProxyAddr 的头,这样的用法是可以的。然而,这种用法不常见,通常情况下,proxy_pass 的目标是一个固定的 URL 或通过其他方式计算出的变量。
  3. proxy_set_header Cookie "$http_SessionId";

    • 同样地,$http_SessionId 试图从请求头中获取 SessionId 的值,并将其作为 Cookie 头发送给后端。确保请求中确实有一个 SessionId 头,否则这个变量会为空。

注意事项

  • 安全性:直接使用来自请求头的值来设置 proxy_pass 目标可能会引发安全问题,尤其是如果这些值是由客户端提供的。确保这些值是可信的。

  • 变量存在性:确保请求中确实有这些头(ProxyAddrSessionId),否则这些变量会是空的,可能导致意外行为。

  • 调试和验证:在生产环境中使用前,建议在开发或测试环境中验证这些配置,以确保其行为符合预期。

  • 替代方案:如果 ProxyAddrSessionId 是你在应用逻辑中生成的,可能需要在应用层面设置这些值,而不是依赖请求头。

如果这些头是来自客户端的自定义头,确保在应用层面有适当的验证和处理逻辑,以防止可能的安全漏洞。

多次跳转处理

  server {
    listen 80 default_server;
    server_name _ ;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header ProxyAddr $host;
      proxy_buffering off;

      if ($host = 'a.com') {
        proxy_pass http://b.com;
      }
      if ($host = 'b.com') {
             proxy_pass http://$http_ProxyAddr;
      }
    }
  }

当我们想让 请求a.com域名的数据 在b.com机器上转发 用如上配置即可

遇到的问题:

域名解析异常

报错信息:
xxx.xxx.local could not be resolved (110: Operation timed out), client: 127.0.0.1, request: "GET /api/v21083169.1012693.17302508402220918 HTTP/1.1", host: "xxx.xxx.local"

原因是 Nginx 配置 resolver 指令的地址 无法动态解析的域名

详细解释

  1. 动态解析失败

    • 如果你在 proxy_pass 或其他需要解析的指令中使用动态变量(如 $host),Nginx 需要在请求处理时解析这些域名。没有配置 resolver(或配置的无法解析当前域名) 会导致 Nginx 无法解析这些动态域名,从而导致请求失败。
  2. 默认解析行为

    • Nginx 在启动时会解析所有静态定义的域名,并在运行时不重新解析。因此,对于静态配置的域名(例如 proxy_pass http://www.baidu.com;),Nginx 在启动时就会解析并缓存 IP 地址。这种情况下不需要 resolver,因为解析在启动时已经完成。
  3. 错误信息

    • 如果解析失败,Nginx 可能会在错误日志中记录类似“no resolver defined to resolve $host”的错误信息,提示需要配置 resolver

解决方案

  • 配置 resolver 指令
    • 为了支持动态域名解析,可以在 Nginx 配置中添加 resolver 指令,指定一个或多个 DNS 服务器。例如:
      http {
          resolver 8.8.8.8 8.8.4.4 valid=300s; (配置自己公司的域名解析地址)
          ...
      }
      
    • 这样,Nginx 可以在运行时动态解析域名。

Nginx 启动时解析静态定义的域名时 DNS 地址是在哪里取的

Nginx 在启动时解析静态定义的域名时,使用的是操作系统的默认 DNS 解析机制。这通常包括以下几个来源:

  1. /etc/resolv.conf 文件

    • 在大多数 Unix 和 Linux 系统上,DNS 服务器信息通常存储在 /etc/resolv.conf 文件中。这个文件列出了系统默认使用的 DNS 服务器地址。
    • Nginx 启动时会使用这些 DNS 服务器来解析配置中静态定义的域名。
  2. 操作系统的默认设置

    • 在 Windows 系统上,DNS 解析通常通过网络设置中配置的 DNS 服务器进行。
  3. 系统缓存

    • 操作系统可能会缓存 DNS 解析结果,以加快后续的解析速度。

需要注意的是,Nginx 在启动时解析的域名是指那些在配置文件中直接指定的静态域名(如 proxy_pass http://www.example.com;),而不是通过变量动态指定的域名(如 proxy_pass http://$host;)。对于后者,需要在 Nginx 配置中明确指定 resolver 指令以支持运行时的动态解析。

juejin.cn/post/743176…

参考:# nginx $host 内置变量 详解