nginx - 使用 NGINX 将代理链生成的多个 IP 限制为仅客户端 IP?
问题描述
我正在运行 NGINX(版本 1.17.3)作为系统设置的最后一步,如下所示:
客户端 -> HAProxy(SSL 终止)-> Varnish -> NGINX
它运行良好,但如果我查看 NGINX 日志,我会看到客户端 IP和127.0.0.1,以逗号分隔。排在第二位的 127.0.0.1 是 Varnish。
有没有办法告诉 NGINX 忽略第二个地址,这样:
1.2.3.4, 127.0.0.1
变得公正
1.2.3.4
?
我的问题不是第二个 IP 出现在日志中——我本身并不关心这一点——而是它将它传递给在 NGINX 后面运行的某些软件,如果它们期望一个 IP,就会弄乱它们.
谢谢!
解决方案
解决此问题的最佳方法是使用PROXY 协议在 HAProxy 和 Varnish 之间进行连接。
此协议将客户端连接信息存储在 TCP 包中,并沿各个跃点传输此信息。
要求是您的代理服务器支持此协议。幸运的是 Varnish 和 HAProxy 可以。
对于 HAProxy,send-proxy-v2
只需在后端定义中添加一个额外属性即可。
对于 Varnish,您需要确保打开了支持 PROXY 的侦听端口。
HAProxy 示例配置
这是一个过于简化的 HAProxy 示例配置,它支持send-proxy-v
:
defaults
mode http
frontend http-in-proxy
bind *:80
default_backend servers-proxy
backend servers-proxy
server server1-proxy varnish.example.com:8443 send-proxy-v2
为简单起见,我没有终止 TLS,但我只是通过 PROXY 协议向 Varnish 发送纯 HTTP。
清漆代理示例
下面是一个使用 PROXY 支持打开的额外监听端口的示例:
varnishd -a :80 -a :8443,PROXY -f /etc/varnish/default.vcl -s malloc,2g
如您所见,常规 HTTP 端口是80
,而 PROXY 端口是8443
。HAProxy 配置也引用该端口。
那 X-Forwarded-For 标头呢?
成功设置 PROXY 协议后,您现在可以从准确的X-Forwarded-For
标头中受益。
Varnish 将使用它从 PROXY 协议获得的值,不再需要链接这些X-Forwarded-For
值。
如果连接HAProxy的客户端IP地址是, Nginx中1.2.3.4
的header就是。X-Forwarded-For
X-Forwarded-For: 1.2.3.4
额外奖励:TLS 信息。
PROXY 协议不仅存储原始客户端 IP 地址,还存储有关请求协议的信息。
proxy
以下是用于确定原始连接是通过 HTTP 还是 HTTPS 建立的 VMOD 示例:
vcl 4.1;
import proxy;
sub vcl_recv {
if (proxy.is_ssl()) {
set req.http.X-Forwarded-Proto = "https";
} else {
set req.http.X-Forwarded-Proto = "http";
}
}
sub vcl_hash {
hash_data(req.http.X-Forwarded-Proto);
}
注意:此示例还将通过将
X-Forwarded-Proto
标头的值添加到缓存对象的哈希值来创建基于协议的缓存变体。
这是另一个使用 PROXY 协议提取更多 TLS 信息的示例:
vcl 4.1;
import proxy;
sub vcl_deliver {
set resp.http.alpn = proxy.alpn();
set resp.http.authority = proxy.authority();
set resp.http.ssl = proxy.is_ssl();
set resp.http.ssl-version = proxy.ssl_version();
set resp.http.ssl-cipher = proxy.ssl_cipher();
set resp.http.client-has-cert-sess = proxy.client_has_cert_sess();
set resp.http.client-has-cert-conn = proxy.client_has_cert_conn();
}
后备方案
我希望我让您相信 PROXY 协议非常强大。但是,如果您不打算使用 PROXY 协议,您仍然可以提取X-Forwarded-For
VCL 代码中标头的第一个值。
这是在 VCL 中执行此操作的方法:
sub vcl_recv {
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For,"^([^,]+)(,[^,]+)*","\1");
}
然后,该值将以现成的格式呈现给您的 Nginx 服务器。
推荐阅读
- javascript - 指向新屏幕的单元格中的 Ag-grid 按钮
- javascript - javascript中的独立离线反向地理编码库
- python - 根据索引动态获取嵌套列表
- arduino - ESP32 上的 Waveshare 电子墨水显示屏
- node.js - 在 2 个 ejs 文件之间传递选择值
- ios - Xcode 12 'carthage update' 总线错误 10 - 运行大量框架时
- variables - HUE,HIVE如何在可变环境中存储Table.Column?
- node.js - AWS dynamoDB - batchWrite - 提供的关键元素与架构不匹配
- javascript - 为什么在 JavaScript 中不允许 let 和 const 关键字变量重新声明,而 var 关键字变量是允许的?
- sql - 每个房东评价的客人的平均年龄是多少?