大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说获取请求来源 IP 地址[亲测有效],希望您对编程的造诣更进一步.
IP 追溯主要用于获取请求的真实 IP ,由于现有服务是基于 Nginx 实现负载均衡的,因此获取请求真实 IP 存在一定难度。在 Matrix 现有实现中,IP 追溯由 getIp
函数完成,其具体代码如下。
/** * 获得请求发送方的 ip * @param {Context} ctx * @return {string} */
export function getIp(ctx) {
const xRealIp = ctx.get('X-Real-Ip');
const { ip } = ctx;
const { remoteAddress } = ctx.req.connection;
return xRealIp || ip || remoteAddress;
}
在对代码进行更为详细的讨论之前,我们需要分析几种常用获取请求 IP 来源的方式:
req.socket.remoteAddress
X-Forwarded-For
X-Real-IP
req.socket.remoteAddress
在 Node.js 官方文档 net_socket_remoteaddress 中,我们得知可通过 req.socket.remtoeAddress
获取 Socket 连接的源 IP 地址信息。
socket.remoteAddress
Added in: v0.5.10
- String
The string representation of the remote IP address. For example,
'74.125.127.100'
or'2001:4860:a005::68'
. Value may beundefined
if the socket is destroyed (for example, if the client disconnected).
根据官方文档 http_request_socket 的描述,req.connection
和 req.socket
是等价的,我们也可以通过 req.connection.remoteAddress
获取 Socket 连接的源 IP 信息。这种获取请求 IP 来源的方式,适用于客户端直连服务端的场景。
![获取请求来源 IP 地址[亲测有效]插图1 获取请求来源 IP 地址[亲测有效]](https://daima100.com/wp-content/themes/justnews/themer/assets/images/lazy.png)
但由于现有 Matrix 服务使用了 Nginx 作为服务集群的负载均衡,故通过 req.socket.connection
获取得到的是 Nginx 的 IP 地址,并不是请求的真实 IP 地址。
X-Forwarded-For
根据 RFC 7239 规范,HTTP 代理(如 Nginx、Apache 等)会改写 HTTP 请求头部,添加 X-Forwarded-For
字段,用于追踪请求的来源,该字段的格式如下:
X-Forwarded-For: client, proxy1, proxy2
下面对 X-Forwarded-For
字段的处理过程,进行详细阐述:
- 客户端(如浏览器)在发送 HTTP 请求时,默认是不带
X-Forwarded-For
字段。 - 当请求到达第一个 HTTP 代理服务器时,代理服务器根据 RFC 7239 规范,为请求头部添加
X-Forwared-For
字段,并且将值设置为客户端的 IP 地址。 - 若后面存在多个 HTTP 代理(即请求在后续会依次被多个 HTTP 代理处理),则每个代理都会在
X-Forwarded-For
字段值中追加上一代理的 IP 地址。 - 在业务服务器中,我们可通过
X-Forwarded-For
值的最左边的 IP 地址获取客户端的 IP 地址。
![获取请求来源 IP 地址[亲测有效]插图3 获取请求来源 IP 地址[亲测有效]](https://daima100.com/wp-content/themes/justnews/themer/assets/images/lazy.png)
但遗憾的是,X-Forwarded-For
是可伪造的:如果客户端在发起 HTTP 请求时,设置了伪造的 X-Forwarded-For
字段,由于后续的每层代理只会追加此字段而不会覆盖,故业务服务器最终获取的客户端 IP 地址可能是客户端伪造的地址。
通常,我们需要进行额外的配置,才能使得 Nginx 支持 X-Forwarded-For
。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Real-IP
HTTP 代理服务器可在请求头部中设置 X-Real-IP
请求源信息,但这并不是 RFC 规范中的内容。
![获取请求来源 IP 地址[亲测有效]插图5 获取请求来源 IP 地址[亲测有效]](https://daima100.com/wp-content/themes/justnews/themer/assets/images/lazy.png)
X-Real-IP
是客户端不可伪造的,但仅能描述最近一个代理的真实 IP ,如果有多层代理,其仍旧不可作为客户端请求的真实 IP 。在现实生活中,多层代理其实是比较少见的,常见的是单层代理,因此在通常情况下,使用 X-Real-IP
是足以完成任务的,且相对于 X-Forwarded-For
有更好的安全性。
我们可通过以下设置,使得 Nginx 支持 X-Real-IP
字段的自动设置。
proxy_set_header X-Real-IP $remote_addr;
几种方式的对比
以下是我对几种获取客户端真实 IP 的方式的总结,分析了各方式的局限和应用场景。
req.socket.remoteAddress | X-Forwarded-For | X-Real-IP | |
---|---|---|---|
是否可伪造 | 否 | 是 | 否 |
有效性 | 仅在客户端直连服务端时 | 仅在未伪造时 | 仅在客户端未经过多级代理时 |
参考资料
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13701.html