先上代码

var http = require('http')
var server = http.createServer(function (req,res) {
console.log(req.headers['x-forwarded-for'] ); // 判断是否有反向代理
console.log(req.socket.remoteAddress ); // 判断后端的 socket 的 IP
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
res.end(ip)
})
server.listen('9098')

x-forwarded-for是什么?

X-Forwarded-For 是一个扩展header头,用来表示 HTTP 请求端真实 IP,在HTTP/1.1(RFC 2616)协议中没有定义,但是现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

由人为设置

一些代理服务器会设置一些消息头,比如nginx会在转发请求的时候可以带上这个消息头,向应用服务传递客户端的真实IP;

使用下面的配置在nginx设置反向代理转发的X-Forwarded-For:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; // 常用
proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $remote_addr" // 不常用,$http_x_forwarded_for是读取到的消息头,如果请求头没有x-Forwarded-for,这个值就是空的。

这样就能在应用服务器拿到消息头 X-Forwarded-For;

可以伪造

因为是人为设置,伪造一个假的很简单,如下:

proxy_set_header X-Forwarded-For "121.12.12.12";

所以接收到的不可信任的服务器传递回来的header,或者客户端伪造了header,其中x-forwarded-for是不能当做客户端IP的。

格式

X-Forwarded-For请求头格式非常简单,就这样:X-Forwarded-For:client, proxy1, proxy2,由[英文逗号+空格]隔开的多个部分组成,最开始的是离服务端最远的设备IP,然后是每一级代理的IP。

如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,代理服务器会把前一个网络设备的IP地址追加到X-Forwarded-For 上面,经过层层追加,服务端最终会收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

同时注意到IP3是不会追加上到这个列表上的。

实际验证:在本地电脑开启一个nodejs服务,端口为9090;开启nginx反向代理,端口为8062;

  • 通过8062访问nginx服务的时候,req.headers['x-forwarded-for']值为
192.168.1.105 //nginx通过X-Forwarded-For将客户端的地址转发了过来
  • 通过9090直接访问nodejs访问,req.headers['x-forwarded-for']值为
undefined //直接请求的时候,没有设置消息头,自然为undefined

所以:

  1. 有没有X-Forwarded-For和代理服务器的设置有关;
  2. 正确与否也和代理服务器有关;

remoteAddress

如果没有X-Forwarded-For,应用服务器可以通过与服务端建立 TCP 连接获取到。在nodejs中可以通过req.socket.remoteAddress获取到IP3;

remoteAddress有没有可能是假的呢?因为tcp链接需要三次握手,所以无法伪造这个ip。

X-Real-IP是什么

是一个自定义的消息头,目前并不属于任何标准,完全由用户控制。

结论;

没有代理:直接使用remoteAddress获取客户端IP,因为header中x-forwarded-for不可靠,可能有也可能没有,甚至可能是伪造的;

有代理的情况下,获取到的remoteAddress是代理服务器的IP,如果代理服务器是可信赖的,那么能通过x-forwarded-for来获取客户端IP。

在express,koa中都有获取ip的方法,他们是怎么封装的呢?

koa中是如何封装获取客户端IP的?

express中是如何处理IP的?

如有错误之处,望请斧正。

实践使用nodejs获取用户真实IP?的更多相关文章

  1. PHP获取用户真实 IP , 淘宝IP接口获得ip地理位置(转)

    <?php /** * 获取用户真实 IP */ function getIP() { static $realip; if (isset($_SERVER)){ if (isset($_SER ...

  2. java 获取用户真实ip

    /** * 获取用户真实ip * @param request * @return */ public static String getIpAddr(HttpServletRequest reque ...

  3. 多层代理获取用户真实IP

    1. 几个概念remote_addr:如果中间没有代理,这个就是客户端的真实IP,如果有代理,这就是上层代理的IP.X-Forwarded-For:一个HTTP扩展头,格式为 X-Forwarded- ...

  4. Java中使用HttpRequest获取用户真实IP地址端口

    import javax.servlet.http.HttpServletRequest; /** * 自定义访问对象工具类 * * 获取对象的IP地址等信息 * @author X-rapido * ...

  5. 在有nginx做反向代理时候,如何获取用户真实Ip信息

    在获取用户的Ip地址时,不一定可以获取到用户真实的地址信息,这要看代理服务器的类型,代理服务器有普通匿名代理服务器,高匿代理服务器,像这种情况很难获取到用户真实的Ip地址 假如用户没有使用匿名代理服务 ...

  6. 获取用户真实IP:(模拟:客户端--F5--nginx--tomcat 后端获取用户真实IP)

    模拟:客户端--F5--nginx--tomcat 后端获取用户真实IP 192.168.109.137 :nginx01(充当第一层代理==F5)192.168.109.138 :nginx02(二 ...

  7. 如何根据HttpServletRequets获取用户真实IP地址

    最近的一个项目的某个功能获取用户的ip地址,添加用户的系统使用记录. 我发现当我直接使用getRemoteAddr()方法从HttpServletRequet中获取用户的ip时,获取到的是服务器的ip ...

  8. nginx反向代理获取用户真实ip

    nginx做反向代理时,默认的配置后端获取到的ip都是来自于nginx,如何转发用户的真实ip到后端程序呢?如是是java后端,用request.getRemoteAddr();获取到的是nginx的 ...

  9. CDN下nginx获取用户真实IP地址

    随着nginx的迅速崛起,越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速,但是随之也遇到一个问题:nginx如何获取用户 ...

随机推荐

  1. .Net Core踩坑记:读取txt中文乱码

    迁移.net framework的项目,有块读取txt中文转码的问题,普通的不能再普通的代码,想都没想直接copy过去,也没测,结果今天就被坑了.Core是3.1版本,这是原来的代码: string ...

  2. JS中函数执行顺序的问题?

    作者:知乎用户链接:https://www.zhihu.com/question/23564807/answer/82996422来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  3. gerapy 爬虫web调度可视化工具(基于scrapyd)

    web 基于scrapyd 提供主机管理功能 基于scrapyd管理已安装服务的主机. 进入具体主机管理页面,会自动加载所有已知爬虫任务: 可直接可以调度.运行.查看日志. 提供项目管理功能 将已知项 ...

  4. django python mange.py runserver 源码

    django python mange.py runserver 源码 入 口 mange.py文件 execute_from_command_line函数 输入参数为['manage.py', 'r ...

  5. IIS 发布页面后或者vs平台运行后显示“未能加载文件或程序集“WebApi”或它的某一个依赖项。试图加载格式不正确的程序。”

    一般情况下出现这样的问题是因为.dll文件不存在或者路径不正确. 但今天我遇到的情况都不在这两个内. 我确定.dll文件是存在的,路径也是正确的. 但是程序死活都是“未能加载文件或程序集“xxx”或它 ...

  6. RocketMQ入门到入土(二)事务消息&顺序消息

    接上一篇:RocketMQ入门到入土(一)新手也能看懂的原理和实战! 一.事务消息的由来 1.案例 引用官方的购物案例: 小明购买一个100元的东西,账户扣款100元的同时需要保证在下游的积分系统给小 ...

  7. HTTP 协议详解(二)

    前面一篇已经说过了 HTTP 的基本特性,HTTP 的发展史,前情回顾.这一篇就更详细的 HTTP 协议使用过程一些参数配置,缓存,Cookie设置相关的细节做一些梳理. 数据类型与编码 在 TCP/ ...

  8. 收藏python开发各种资源官方文档

    http://json.cn/ https://cn.bing.com/ https://processon.com/ https://docs.djangoproject.com/en/1.11/r ...

  9. Spring Security(三) —— 核心配置解读

    摘要: 原创出处 https://www.cnkirito.moe/spring-security-3/ 「老徐」欢迎转载,保留摘要,谢谢! 3 核心配置解读 上一篇文章<Spring Secu ...

  10. Python3笔记011 - 3.2 选择语句

    第3章 流程控制语句 3.2 选择语句 1.if语句 if 表达式: 语句块 执行的流程是:当表达式的布尔值为真时,执行语句块,为假时,离开if语句,程序往下执行. 2.if...else语句 if ...