背景
我们在做开发时会有一些情况需要,生产测试互访。但是这种网络打通的机器较少。我们可以通过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 作为反向代理将请求转发到一个与请求的主机名相同的后端服务器。以下是对这个配置的详细解释:
配置解析
-
resolver 8.8.8.8 valid=5s;- 这行配置定义了一个 DNS 解析器,使用 Google 的公共 DNS 服务器
8.8.8.8。valid=5s指定了解析结果的缓存时间为 5 秒。这在需要动态解析主机名时非常有用,例如在proxy_pass中使用变量时。
- 这行配置定义了一个 DNS 解析器,使用 Google 的公共 DNS 服务器
-
server块- 定义了一个监听在 80 端口的服务器块,
server_name _;表示匹配所有主机名请求。
- 定义了一个监听在 80 端口的服务器块,
-
location /块- 处理所有路径为
/的请求。
- 处理所有路径为
-
proxy_set_header指令- 这些指令用于设置请求转发到后端服务器时的 HTTP 头:
X-Real-IP:将客户端的真实 IP 地址传递给后端服务器。Host:传递原始请求的主机头。X-Forwarded-For:传递客户端的原始 IP 地址以及代理链。X-Forwarded-Proto:传递使用的协议(HTTP 或 HTTPS)。
- 这些指令用于设置请求转发到后端服务器时的 HTTP 头:
-
proxy_buffering off;- 关闭代理缓冲。这意味着响应数据会立即传递给客户端,而不是先缓存在 Nginx 中。这在某些需要实时传输数据的场景中很有用。
-
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_pass 和 Cookie 头。然而,直接这样使用可能会导致一些问题。以下是对这个配置的分析和建议:
配置解析
-
location = /- 这个
location块仅匹配请求路径为/的请求。
- 这个
-
proxy_pass $http_ProxyAddr;- 这里你试图使用
$http_ProxyAddr作为proxy_pass的目标。需要注意的是,Nginx 中的$http_前缀变量通常用于访问请求头中的值。如果请求头中有一个名为ProxyAddr的头,这样的用法是可以的。然而,这种用法不常见,通常情况下,proxy_pass的目标是一个固定的 URL 或通过其他方式计算出的变量。
- 这里你试图使用
-
proxy_set_header Cookie "$http_SessionId";- 同样地,
$http_SessionId试图从请求头中获取SessionId的值,并将其作为Cookie头发送给后端。确保请求中确实有一个SessionId头,否则这个变量会为空。
- 同样地,
注意事项
-
安全性:直接使用来自请求头的值来设置
proxy_pass目标可能会引发安全问题,尤其是如果这些值是由客户端提供的。确保这些值是可信的。 -
变量存在性:确保请求中确实有这些头(
ProxyAddr和SessionId),否则这些变量会是空的,可能导致意外行为。 -
调试和验证:在生产环境中使用前,建议在开发或测试环境中验证这些配置,以确保其行为符合预期。
-
替代方案:如果
ProxyAddr和SessionId是你在应用逻辑中生成的,可能需要在应用层面设置这些值,而不是依赖请求头。
如果这些头是来自客户端的自定义头,确保在应用层面有适当的验证和处理逻辑,以防止可能的安全漏洞。
多次跳转处理
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 指令的地址 无法动态解析的域名
详细解释
-
动态解析失败:
- 如果你在
proxy_pass或其他需要解析的指令中使用动态变量(如$host),Nginx 需要在请求处理时解析这些域名。没有配置resolver(或配置的无法解析当前域名) 会导致 Nginx 无法解析这些动态域名,从而导致请求失败。
- 如果你在
-
默认解析行为:
- Nginx 在启动时会解析所有静态定义的域名,并在运行时不重新解析。因此,对于静态配置的域名(例如
proxy_pass http://www.baidu.com;),Nginx 在启动时就会解析并缓存 IP 地址。这种情况下不需要resolver,因为解析在启动时已经完成。
- Nginx 在启动时会解析所有静态定义的域名,并在运行时不重新解析。因此,对于静态配置的域名(例如
-
错误信息:
- 如果解析失败,Nginx 可能会在错误日志中记录类似“no resolver defined to resolve $host”的错误信息,提示需要配置
resolver。
- 如果解析失败,Nginx 可能会在错误日志中记录类似“no resolver defined to resolve $host”的错误信息,提示需要配置
解决方案
- 配置
resolver指令:- 为了支持动态域名解析,可以在 Nginx 配置中添加
resolver指令,指定一个或多个 DNS 服务器。例如:http { resolver 8.8.8.8 8.8.4.4 valid=300s; (配置自己公司的域名解析地址) ... } - 这样,Nginx 可以在运行时动态解析域名。
- 为了支持动态域名解析,可以在 Nginx 配置中添加
Nginx 启动时解析静态定义的域名时 DNS 地址是在哪里取的
Nginx 在启动时解析静态定义的域名时,使用的是操作系统的默认 DNS 解析机制。这通常包括以下几个来源:
-
/etc/resolv.conf文件:- 在大多数 Unix 和 Linux 系统上,DNS 服务器信息通常存储在
/etc/resolv.conf文件中。这个文件列出了系统默认使用的 DNS 服务器地址。 - Nginx 启动时会使用这些 DNS 服务器来解析配置中静态定义的域名。
- 在大多数 Unix 和 Linux 系统上,DNS 服务器信息通常存储在
-
操作系统的默认设置:
- 在 Windows 系统上,DNS 解析通常通过网络设置中配置的 DNS 服务器进行。
-
系统缓存:
- 操作系统可能会缓存 DNS 解析结果,以加快后续的解析速度。
需要注意的是,Nginx 在启动时解析的域名是指那些在配置文件中直接指定的静态域名(如 proxy_pass http://www.example.com;),而不是通过变量动态指定的域名(如 proxy_pass http://$host;)。对于后者,需要在 Nginx 配置中明确指定 resolver 指令以支持运行时的动态解析。