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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10849687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:48:20  来源:igfitidea点击:

Express.js: how to get remote client address

node.jsexpressipip-address

提问by Erik

I don't completely understand how I should get a remote user IP address.

我不完全明白我应该如何获得远程用户 IP 地址。

Let's say I have a simple request route such as:

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

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

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

Is the above approach correct to get the real user IP address or is there a better way? And what about proxies?

上述方法是否正确获取真实用户IP地址或有更好的方法?那么代理呢?

回答by alessioalex

If you are running behind a proxy like NGiNX or what have you, only then you should check for 'x-forwarded-for':

如果你运行在像 NGiNX 这样的代理之后或者你有什么,那么你应该检查“x-forwarded-for”:

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

If the proxy isn't 'yours', I wouldn't trust the 'x-forwarded-for' header, because it can be spoofed.

如果代理不是“您的”,我就不会信任“x-forwarded-for”标头,因为它可以被欺骗。

回答by Haozhun

While the answer from @alessioalex works, there's another way as stated in the Express behind proxiessection of Express - guide.

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

  1. Add app.set('trust proxy', true)to your express initialization code.
  2. When you want to get the ip of the remote client, use req.ipor req.ipsin the usual way (as if there isn't a reverse proxy)
  1. 添加app.set('trust proxy', true)到您的快速初始化代码。
  2. 当你想获取远程客户端的ip时,使用req.ipreq.ips按照通常的方式(就像没有反向代理一样)

Optional reading:

可选阅读:

  • Use req.ipor req.ips. req.connection.remoteAddressdoes't work with this solution.
  • More options for 'trust proxy'are available if you need something more sophisticated than trusting everything passed through in x-forwarded-forheader (for example, when your proxy doesn't remove preexisting x-forwarded-for header from untrusted sources). See the linked guide for more details.
  • If your proxy server does not populated x-forwarded-forheader, there are two possibilities.
    1. The proxy server does not relay the information on where the request was originally. In this case, there would be no way to find out where the request was originally from. You need to modify configuration of the proxy server first.
      • For example, if you use nginx as your reverse proxy, you may need to add proxy_set_header X-Forwarded-For $remote_addr;to your configuration.
    2. The proxy server relays the information on where the request was originally from in a proprietary fashion (for example, custom http header). In such case, this answer would not work. There may be a custom way to get that information out, but you need to first understand the mechanism.
  • 使用req.ipreq.ipsreq.connection.remoteAddress不适用于此解决方案。
  • 'trust proxy'如果您需要比信任在x-forwarded-for标头中传递的所有内容更复杂的东西(例如,当您的代理没有从不受信任的来源中删除预先存在的 x-forwarded-for 标头时),则可以使用更多选项。有关更多详细信息,请参阅链接指南。
  • 如果您的代理服务器未填充x-forwarded-for标头,则有两种可能性。
    1. 代理服务器不会中继有关请求最初在哪里的信息。在这种情况下,将无法找出请求的最初来源。您需要先修改代理服务器的配置。
      • 例如,如果您使用 nginx 作为反向代理,则可能需要添加proxy_set_header X-Forwarded-For $remote_addr;到您的配置中。
    2. 代理服务器以专有方式(例如,自定义 http 标头)中继有关请求最初来自何处的信息。在这种情况下,这个答案是行不通的。可能有一种自定义方式来获取该信息,但您首先需要了解该机制。

回答by ququzone

In nginx.conffile:
proxy_set_header X-Real-IP $remote_addr;

nginx.conf文件中:
proxy_set_header X-Real-IP $remote_addr;

In node.jsserver file:
var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;

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

note that express lowercases headers

请注意,表达小写标题

回答by Edwin Dalorzo

Particularly for node, the documentation for the http server component, under event connectionsays:

特别是对于节点,http 服务器组件的文档在事件连接下说:

[Triggered] when a new TCP stream is established. [The] socket is an object of type net.Socket. Usually users will not want to access this event. In particular, the socket will not emit readable events because of how the protocol parser attaches to the socket. The socket can also be accessed at request.connection.

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

So, that means request.connectionis a socket and according to the documentation there is indeed a socket.remoteAddressattribute which according to the documentation is:

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

The string representation of the remote IP address. For example, '74.125.127.100' or '2001:4860:a005::68'.

远程 IP 地址的字符串表示形式。例如,“74.125.127.100”或“2001:4860:a005::68”。

Under express, the request object is also an instance of the Node http request object, so this approach should still work.

在express下,请求对象也是Node http请求对象的一个​​实例,所以这种方式应该还是可以的。

However, under Express.js the request already has two attributes: req.ipand req.ips

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

req.ip

Return the remote address, or when "trust proxy" is enabled - the upstream address.

req.ips

When "trust proxy"is true, parse the "X-Forwarded-For" ip address list and return an array, otherwise an empty array is returned. For example if the value were "client, proxy1, proxy2" you would receive the array ["client", "proxy1", "proxy2"] where "proxy2" is the furthest down-stream.

请求文件

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

请求文件

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

It may be worth mentioning that, according to my understanding, the Express req.ipis a better approach than req.connection.remoteAddress, since req.ipcontains the actual client ip (provided that trusted proxy is enabled in express), whereas the other may contain the proxy's IP address (if there is one).

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

That is the reason why the currently accepted answer suggests:

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

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

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

The req.headers['x-forwarded-for']will be the equivalent of express req.ip.

The req.headers['x-forwarded-for']will 相当于 express req.ip

回答by Bald

  1. Add app.set('trust proxy', true)
  2. Use req.ipor req.ipsin the usual way
  1. 添加 app.set('trust proxy', true)
  2. 使用req.ipreq.ips以通常方式

回答by learnsomemore

This is just additional information for this answer.

这只是此答案的附加信息。

If you are using nginx, you would add proxy_set_header X-Real-IP $remote_addr;to the location block for the site. /etc/nginx/sites-available/www.example.comfor example. Here is a example server block.

如果您正在使用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;
    }
}

After restarting nginx, you will be able to access the ip in your node/expressapplication routes with req.headers['x-real-ip'] || req.connection.remoteAddress;

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

回答by Oyetoke Tobi

I wrote a package for that purpose. You can use it as express middleware. My package is published here: https://www.npmjs.com/package/express-ip

我为此编写了一个包。您可以将其用作快速中间件。我的包在这里发布:https: //www.npmjs.com/package/express-ip

You can install the module using

您可以使用安装模块

npm i express-ip

Usage

用法

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

回答by abbr

According to Express behind proxies, req.iphas taken into account reverse proxy if you have configured trust proxyproperly. Therefore it's better than req.connection.remoteAddresswhich is obtained from network layer and unaware of proxy.

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

回答by Lorem Ipsum

I know this question has been answered, but here's how I got mine to work.

我知道这个问题已经得到回答,但这是我如何让我的工作。

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

回答by Hongbo Miao

If you are fine using 3rd-party library. You can check request-ip.

如果您可以使用 3rd-party 库。您可以检查request-ip

You can use it is by

你可以使用它

import requestIp from 'request-ip';

app.use(requestIp.mw())

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

The source code is quite long, so I won't copy here, you can check at https://github.com/pbojinov/request-ip/blob/master/src/index.js

源码比较长,这里就不复制了,大家可以查看https://github.com/pbojinov/request-ip/blob/master/src/index.js

Basically,

基本上,

It looks for specific headers in the request and falls back to some defaults if they do not exist.

The user ip is determined by the following order:

  1. X-Client-IP
  2. X-Forwarded-For(Header may return multiple IP addresses in the format: "client IP, proxy 1 IP, proxy 2 IP", so we take the the first one.)
  3. CF-Connecting-IP(Cloudflare)
  4. Fastly-Client-Ip(Fastly CDN and Firebase hosting header when forwared to a cloud function)
  5. True-Client-Ip(Akamai and Cloudflare)
  6. X-Real-IP(Nginx proxy/FastCGI)
  7. X-Cluster-Client-IP(Rackspace LB, Riverbed Stingray)
  8. X-Forwarded, Forwarded-Forand Forwarded(Variations of #2)
  9. req.connection.remoteAddress
  10. req.socket.remoteAddress
  11. req.connection.socket.remoteAddress
  12. req.info.remoteAddress

If an IP address cannot be found, it will return null.

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

用户ip由以下顺序确定:

  1. X-Client-IP
  2. X-Forwarded-For(Header可能会返回多个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-Forwarded,Forwarded-ForForwarded(#2 的变体)
  9. req.connection.remoteAddress
  10. req.socket.remoteAddress
  11. req.connection.socket.remoteAddress
  12. req.info.remoteAddress

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

Disclose: I am not associated with the library.

披露:我与图书馆无关。