使用Node.js在Amazon ELB后面获取远程IP地址

14

我的一个Node应用程序运行在Amazon机器上,使用弹性负载均衡器(ELB)。但是,远程IP地址似乎总是相同的。我使用以下代码在Node中获取客户端的IP地址(通过Connect/Express):

req.socket.remoteAddress

我从节点文档中没有得到任何其他提示。有什么提示吗?


如果您正在使用TCP模式的ELB,请参考https://dev59.com/rGMl5IYBdhLWcg3w966L。 - josh3736
5个回答

10

如果您正在使用express,可以按照文档的说明,为您的express实例启用trust proxy,然后req.ip将会填充正确的IP地址。

通过通过app.enable('trust proxy')来启用“trust proxy”设置,Express将知道它位于代理之后并且可以相信X-Forwarded-*头字段,否则很容易被伪造。

启用此设置会产生几个微妙的影响。第一个是X-Forwarded-Proto可能被反向代理设置为告诉应用程序它是https或简单的http。此值由req.protocol反映。

这一更改的第二个影响是req.ip和req.ips值将填充X-Forwarded-For列表中的地址。

以下是示例:

var app = express();
app.enable('trust proxy');
// ...

app.use(function(req, res, next) {
  console.log('client ip address:', req.ip);
  return next();
});

我其实在过去几年中一直在使用它,但忘记了这个问题 :) 谢谢你再次提出它! - Johann Philipp Strathausen
3
Express 4改变了处理“trust proxy”选项的方式,因此您可以使用类似于app.set('trust proxy', 1)的内容来仅信任您的负载均衡器。 - Juicy Scripter
顺便提一下,在亚马逊的情况下,我认为值必须是“2”,一个用于实际机器上的nginx,另一个是实际负载均衡器。 - Johann Philipp Strathausen

8
这个答案对我很有用,谢谢。但你也可以尝试:
var ip_address = null;
if(req.headers['x-forwarded-for']){
    ip_address = req.headers['x-forwarded-for'];
}
else {
    ip_address = req.connection.remoteAddress;
}
sys.puts( ip_address );

2
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; 根据以上代码,获取客户端 IP 地址。 - bithavoc
在NodeJS中没有req.connection.remoteAddress - 它被移除了吗? - Redsandro

6

您需要获取ELB实例的IP,并且需要从头文件中获取x-forwarded-for值。由于我不是一个node.js大师,我在http://forum.webfaction.com/viewtopic.php?id=4500找到了这段代码。

例如:

var http = require( 'http' ),
sys = require( 'sys' );

http.createServer(
        function( req, res ) {
                        var ip_address = null;
                        try {
                                ip_address = req.headers['x-forwarded-for'];
                        }
                        catch ( error ) {
                                ip_address = req.connection.remoteAddress;
                        }
                        sys.puts( ip_address );
        }
);

很酷,谢谢,我刚试过了,它能正常工作。我不知道那个头信息。 - Johann Philipp Strathausen
7
如果 req.headers['x-forwarded-for'] 不存在,这不是一个错误。ip_address 将只是 undefinedip_address = req.headers['x-forwarded-for'] || req.connection.remoteAddress; 这行代码可以完成工作。 - don_jones

1
这里选中的正确答案是危险的,因为AWS ELB会按预期更改顺序:https://github.com/koajs/koa/issues/1094#issuecomment-345861282 Express、koa等通常采用最左边的项,而ELB将其作为最右边的项。
(express文档):

如果为true,则客户端的IP地址被理解为X-Forwarded-For头部中最左边的条目。


1

如果使用 express.js

app.set('trust proxy', 2)

而不是

app.enable('trust proxy')

因为 app.enable('trust proxy') 使用 x-forwarded-for 头部中最左边的 IP,所以很容易被手动提供 x-forwarded-for 头部来欺骗。

app.set('trust proxy', 2) 则指定了从 x-forwarded-for 头部从右到左计算的跳数。例如,如果有一个 AWS 负载均衡器,则 2 将是正确的计数数字,因为每个新的跳转 IP 都会添加到 x-forwarded-for 头部的末尾。

如果您使用其他内容,则可以采用类似的方式。只需获取 req.headers['x-forwarded-for'],按逗号拆分,然后从右到左计算跳数,直到排除负载均衡器 IP 为止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接