亚马逊 ELB 后面带有 node-js 的远程 IP 地址

Posted

技术标签:

【中文标题】亚马逊 ELB 后面带有 node-js 的远程 IP 地址【英文标题】:Remote IP address with node-js behind amazon ELB 【发布时间】:2011-10-31 15:33:10 【问题描述】:

我在弹性负载均衡器 (elb) 后面的亚马逊实例存储机器上有一个节点应用程序。但是,远程 IP 地址似乎总是相同的。我使用此代码在节点中获取客户端的 IP 地址(通过 connect/express):

req.socket.remoteAddress

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

【问题讨论】:

如果您在 TCP 模式下使用 ELB,请参阅***.com/q/17981943/201952 【参考方案1】:

这是一个解决方案如果您使用的是 express: 根据documentation,您可以为您的快速实例启用trust proxy,然后req.ip 将填充正确的IP 地址。

通过 app.enable('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();
);

【讨论】:

过去几年我实际上一直在使用这个,但忘记了这个问题 :) 感谢您再次提出! express 4 改变了trust proxy 选项的处理方式,因此您可以使用app.set('trust proxy', 1) 之类的东西来只信任您的负载均衡器 顺便说一下,在亚马逊的情况下,我认为该值必须是2,一个用于实际机器上的 nginx,另一个是实际的负载均衡器。【参考方案2】:

答案对我有用,谢谢。但你可以试试:

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 );

【讨论】:

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; 没有req.connection.remoteAddress - 它在 NodeJS 中被删除了吗?【参考方案3】:

您收到 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 );
        
);

【讨论】:

很酷,谢谢,刚刚尝试过,它可以工作。我不知道那个标题。 如果req.headers['x-forwarded-for'] 不存在,则不是错误。 ip_address 将只是 undefinedip_address = req.headers['x-forwarded-for'] || req.connection.remoteAddress;` 将完成这项工作【参考方案4】:

此处选择的正确答案很危险,因为 AWS ELB 会按预期切换顺序:https://github.com/koajs/koa/issues/1094#issuecomment-345861282

Express、koa等一般取最左边的item,而ELB则取最右边的item

(表达文档):

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

【讨论】:

【参考方案5】:

如果 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 标头的右到左计数的跃点数。 IE。如果有一个 AWS 负载均衡器,那么 2 将是正确的计数,因为每个新的跃点 ip 都会添加到 x-forwarded-for 标头的末尾。

如果您正在使用其他东西,请执行类似的方法。只需获取req.headers['x-forwarded-for'],用逗号分割,然后从右到左计算跃点,直到不排除负载均衡器 ip。

【讨论】:

以上是关于亚马逊 ELB 后面带有 node-js 的远程 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

在 AWS ELB 后面带有嵌入式 Undertow 的 Spring Boot - HTTP 到 HTTPS 重定向

如何配置 AWS ELB 以阻止某些 IP 地址? (已知的垃圾邮件发送者)[关闭]

为啥从亚马逊弹性负载均衡器后面发送重定向时收到 502 错误网关?

如何在 ELB 应用程序负载均衡器上将 HTTPS 重定向到 HTTP

ELB 和 ECS 集群前的 Amazon API Gateway

在 ELB 后面可访问的 AWS EB url