Express.js:如何获取远程客户端地址

时间:2012-06-01 11:49:01

标签: node.js express ip ip-address

我不完全理解如何获取远程用户IP地址。

假设我有一个简单的请求路由,例如:

app.get(/, function (req, res){
   var forwardedIpsStr = req.header('x-forwarded-for');
   var IP = '';

   if (forwardedIpsStr) {
      IP = forwardedIps = forwardedIpsStr.split(',')[0];  
   }
});

上述方法是否可以获得真实的用户IP地址,还是有更好的方法? 那些代理呢?

16 个答案:

答案 0 :(得分:375)

如果您在NGiNX之类的代理服务器后面运行,或者您拥有什么,那么您应该检查x-forwarded-for':

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

如果代理人不是你的代理人,我就不会相信“x-forwarded-for'标题,因为它可以被欺骗。

答案 1 :(得分:197)

虽然@alessioalex的答案有效,但还有另一种方法,如Express - guide Express背后的部分所述。

  1. app.enable('trust proxy')添加到您的快速初始化代码中。
  2. 如果您想获取远程客户端的IP,请以通常的方式使用req.ipreq.ips(就好像没有反向代理)
  3. 如果您需要比信任x-forwarded-for标头中传递的所有内容更复杂的内容,并且您的代理不会从不受信任的来源中删除预先存在的x-forwarded-for标头,则可以使用“信任代理”的更多选项。有关详细信息,请参阅链接指南。

    注意:req.connection.remoteAddress不适用于我的解决方案。

答案 2 :(得分:50)

nginx.conf档案中:
proxy_set_header X-Real-IP $remote_addr;

node.js服务器文件中:
var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;

请注意明确的小写标题

答案 3 :(得分:27)

特别是对于节点,event connection下的http服务器组件的文档说:

  

[触发]建立新的TCP流时。 [socket]是一个类型的对象   net.Socket。通常用户不希望访问此事件。在   特别是,套接字不会因为如何发出可读事件   协议解析器附加到套接字。套接字也可以   访问 request.connection

所以,这意味着request.connection是一个套接字,根据文档,确实有一个socket.remoteAddress属性,根据文档是:

  

远程IP地址的字符串表示形式。例如,   '74 .125.127.100'或'2001:4860:a005 :: 68'。

在express下,请求对象也是Node http请求对象的一个​​实例,因此这种方法仍然有效。

但是,在Express.js下,请求已有两个属性:req.ipreq.ips

  

req.ip

     

返回远程地址,或启用“信任代理”时 - 上游地址。

     

req.ips

     

"trust proxy"true时,解析“X-Forwarded-For”ip地址列表并返回一个数组,否则为空数组为   回。例如,如果值为“client,proxy1,proxy2”,则为您   会收到数组[“client”,“proxy1”,“proxy2”]其中“proxy2”   是最下游的。

值得一提的是,根据我的理解,Express req.ip是比req.connection.remoteAddress更好的方法,因为req.ip包含实际的客户端ip(假设可信代理是在Express中启用,而另一个可能包含代理的IP地址(如果有的话)。

这就是为什么目前接受的答案表明:

  

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

req.headers['x-forwarded-for']将等同于明确req.ip

答案 4 :(得分:9)

如果您使用第三方库很好。您可以检查request-ip

您可以按以下方式使用它

import requestIp from 'request-ip';

app.use(requestIp.mw())

app.use((req, res) => {
  const ip = req.clientIp;
});

源代码很长,因此我不会在此处复制,您可以在https://github.com/pbojinov/request-ip/blob/master/src/index.js处查看

基本上,

它在请求中查找特定的标头,然后回退到某些标头 如果它们不存在,则默认设置。

用户ip由以下顺序确定:

  1. X-Client-IP
  2. X-Forwarded-For(标头可能返回以下格式的多个IP地址:“客户端IP,代理1 IP,代理2 IP”,因此我们采用第一个 一个。)
  3. CF-Connecting-IP(Cloudflare)
  4. Fastly-Client-Ip(将CDN和Firebase托管标头提供给云功能时,速度很快)
  5. True-Client-Ip(Akamai和Cloudflare)
  6. X-Real-IP(Nginx代理/ FastCGI)
  7. X-Cluster-Client-IP(Rackspace LB,Riverbed Stingray)
  8. X-ForwardedForwarded-ForForwarded(#2的变化)
  9. req.connection.remoteAddress
  10. req.socket.remoteAddress
  11. req.connection.socket.remoteAddress
  12. req.info.remoteAddress

如果找不到IP地址,它将返回null

披露:我没有与图书馆建立联系。

答案 5 :(得分:5)

  1. 添加app.set('trust proxy', true)
  2. 以通常的方式使用req.ipreq.ips

答案 6 :(得分:3)

根据Express behind proxies,如果您已正确配置req.iptrust proxy已考虑反向代理。因此,它比从网络层获得的req.connection.remoteAddress更好,而且不知道代理。

答案 7 :(得分:1)

这对我来说比其他人更好。我的网站支持CloudFlare,似乎需要cf-connecting-ip

req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress

没有对Express behind proxies进行测试,因为它没有对此cf-connecting-ip标题做任何说明。

答案 8 :(得分:1)

header对象包含您需要的所有内容,只需执行以下操作:

var ip = req.headers['x-forwarded-for'].split(',')[0];

答案 9 :(得分:1)

只需使用此快速中间件https://www.npmjs.com/package/express-ip

您可以使用

安装模块
npm i express-ip

用法

const express = require('express');
const app = express();
const expressip = require('express-ip');
app.use(expressip().getIpInfoMiddleware);

app.get('/', function (req, res) {
    console.log(req.ipInfo);
});

答案 10 :(得分:1)

我知道这个问题已经回答了,但是这就是我的工作方式。

let ip = req.connection.remoteAddress.split(`:`).pop();

答案 11 :(得分:1)

这只是this answer的附加信息。

如果您使用的是nginx,则应将proxy_set_header X-Real-IP $remote_addr;添加到站点的位置块中。例如/etc/nginx/sites-available/www.example.com。这是一个示例服务器块。

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    location / {
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_pass http://127.0.1.1:3080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

重新启动nginx后,您将可以使用node来访问express / req.headers['x-real-ip'] || req.connection.remoteAddress;应用程序路由中的IP

答案 12 :(得分:1)

具有扩展功能,nginx和x-real-ip支持

var user_ip;

    if(req.headers['cf-connecting-ip'] && req.headers['cf-connecting-ip'].split(', ').length) {
      let first = req.headers['cf-connecting-ip'].split(', ');
      user_ip = first[0];
    } else {
      let user_ip = req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
    }

答案 13 :(得分:1)

就我而言,类似于this解决方案,我最终使用了以下x-forwarded-for方法:

let ip = (req.headers['x-forwarded-for'] || '').split(',')[0];

x-forwarded-for标头将继续添加从源头到最终目标服务器的IP路由,因此,如果您需要检索源客户端的IP,则这将是第一项

答案 14 :(得分:0)

var ip = req.connection.remoteAddress;

ip = ip.split(':')[3];

答案 15 :(得分:0)

将所有@kakopappa解决方案加在一起,再加上morgan记录客户端IP地址:

morgan.token('client_ip', function getId(req) {
    return req.client_ip
});
const LOG_OUT = ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" :client_ip'
self.app.use(morgan(LOG_OUT, {
    skip: function(req, res) { // custom logging: filter status codes
        return res.statusCode < self._options.logging.statusCode;
    }
}));

// could-flare, nginx and x-real-ip support
var getIpInfoMiddleware = function(req, res, next) {
    var client_ip;
    if (req.headers['cf-connecting-ip'] && req.headers['cf-connecting-ip'].split(', ').length) {
        var first = req.headers['cf-connecting-ip'].split(', ');
        client_ip = first[0];
    } else {
        client_ip = req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
    }
    req.client_ip = client_ip;
    next();
};
self.app.use(getIpInfoMiddleware);