英文:
How to make drupal see client IP behind nginx Reverse Proxy->Varnish->Apache stack?
问题
我正在使用nginx作为反向代理,处理端口80到443的重定向,然后到一个varnish缓存(端口8181),再转发到一个运行在Apache2.4后端(端口8182)的Drupal(7.69)站点。
我已经配置了nginx来转发客户端IP,如下所示:
proxy_pass http://127.0.0.1:8181;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
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 https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_set_header Host $host;
在Varnish的vcl_recv中,我添加了以下内容:
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
在Apache中,我安装了remoteip模块,并设置了以下配置:
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
在Drupal的settings.php中,我有以下设置:
$conf['reverse_proxy'] = True;
$conf['reverse_proxy_header'] = 'X-Forwarded-For';
$conf['reverse_proxy_addresses'] = array('127.0.0.1');
但是Drupal似乎仍然只看到并记录本地主机(127.0.0.1)的IP,而不是真实客户端IP。因此,表单被记录为由服务器本身而不是真实用户提交。
我想知道是否我的Varnish配置有问题,因为我还从nginx代理并绕过Varnish直接访问一个论坛,该论坛绕过了Drupal(它是SMF),但在同一个Apache配置上运行;论坛能够很好地记录来自nginx发送的客户端IP(使用相同的头部更改和Apache remoteip配置)。
我会感激您的指导和建议。
英文:
I'm using nginx as a reverse proxy that handles port 80 -> 443 redirect and then onto a varnish cache (port 8181) that talks to an Apache2.4 backend (port 8182) serving a drupal (7.69) site.
I've configured nginx to forward the client IP as:
proxy_pass http://127.0.0.1:8181;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
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 https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_set_header Host $host;
In varnish vcl_recv I'm adding:
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
In apache I have installed remoteip module and set the following config:
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
In drupal's settings.php I have
$conf['reverse_proxy'] = True;
$conf['reverse_proxy_header'] = 'X-Forwarded-For';
$conf['reverse_proxy_addresses'] = array('127.0.0.1');
...But drupal seems to be nonetheless seeing and loggin only the localhost (127.0.0.1) ip rather than the genuine client IP. So forms are being logged as submitted not from the genuine user but the server itself.
I'm wondering if my varnish config is off, because I'm also proxying from nginx and bypassing varnish to go directly to a forum which bypasses drupal (it's SMF) but runs on the same apache config; the forum is logging the client IPs sent from nginx (using the same header changes and apache remoteip config) just fine.
I'd be grateful for guidance / suggestions.
答案1
得分: 1
Varnish
关于 X-Forwarded-For
的您的Varnish配置在理论上是正确的。
实际上,您甚至不需要在Varnish中设置 X-Forwarded-For
,因为Varnish会自动处理这个。
Drupal配置
就Drupal配置而言,这可能与 reverse_proxy_header
有关。我偶然发现了Drupal 7文档的这一部分:https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/ip_address/7.x。
那个页面上的关键部分是以下代码:
$reverse_proxy_header = variable_get('reverse_proxy_header', 'HTTP_X_FORWARDED_FOR');
显然,通过配置参数,这个 ip_address()
函数可以意识到 X-Forwarded-For
头。
然而,该头部的格式不是官方的HTTP格式,而是PHP $_SERVER
超全局变量存储的方式。在这种情况下,格式将是 HTTP_X_FORWARDED_FOR
。
所以请尝试将 $conf['reverse_proxy_header'] = 'X-Forwarded-For';
替换为 $conf['reverse_proxy_header'] = 'HTTP_X_FORWARDED_FOR';
。
英文:
Varnish
Your Varnish configuration for X-Forwarded-For
is correct, in theory.
In practice you don't even need to set X-Forwarded-For
in Varnish, because Varnish will do this automatically.
Drupal configuration
As far as Drupal configuration goes, it may have something to do with the reverse_proxy_header
. I stumbled upon this piece of Drupal 7 documentation: https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/ip_address/7.x.
The crucial part of the code on that page is the following:
$reverse_proxy_header = variable_get('reverse_proxy_header', 'HTTP_X_FORWARDED_FOR');
Apparently this ip_address()
function can be made aware of the X-Forwarded-For
header through a configuration parameter.
However, the header format is not the official HTTP format, but rather the way that the PHP $_SERVER
superglobal stores it. In this case the format would be HTTP_X_FORWARDED_FOR
.
So please try replacing $conf['reverse_proxy_header'] = 'X-Forwarded-For';
with $conf['reverse_proxy_header'] = 'HTTP_X_FORWARDED_FOR';
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论