Open isayme opened 6 years ago
参考: https://nodejs.org/api/net.html#net_socket_remoteaddress
指 socket 连接的源IP信息, 适用于客户端 直连 服务端的场景.
通常 Server 端不会直接与 Client 端通信, 而是通过 Nginx 等代理接受客户端请求, 这时候 remoteAddress 是代理服务的地址, 无法描述客户端IP.
remoteAddress
由此引入了HTTP 扩展协议头: X-Forwarded-For , 格式是:
X-Forwarded-For
X-Forwarded-For: client, proxy1, proxy2
获取的时候取 X-Forwarded-For 的第一个 IP 地址即可. 但需要注意的是: X-Forwarded-For 可伪造!
通常 Nginx 作为 proxy 时的配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
代理程序设置请求源的 IP 信息, 目前并不是 RFC 标准.
X-Real-IP 不可伪造, 但仅能描述最近一个代理的真实IP, 如果有多级代理, 仍旧不可作为真实客户端的 IP.
X-Real-IP
proxy_set_header X-Real-IP $remote_addr;
默认是返回的是 req.connection.remoteAddress; 当设置 app.set('trust proxy', true) 时, 返回的是 X-Forwarded-For 中的第一个 IP;
req.connection.remoteAddress
app.set('trust proxy', true)
注: 如果 X-Forwarded-For 第一个被伪造且不是一个正常IP, req.ip 不会做任何处理. proxy-addr
注: 如果 X-Forwarded-For 第一个被伪造且不是一个正常IP, req.ip 不会做任何处理.
req.ip
req.ip 背后用的即是 proxy-addr, 不单独讨论.
proxy-addr
综合了多种 Header 建立了 IP 获取的优先顺序, 同时如果有伪造的异常数据会进行过滤.
https://github.com/pbojinov/request-ip#how-it-works
使用 request-ip 库:
request-ip
const express = require('express') const requestIP = require('request-ip') const app = express() app.set('trust proxy', false) // default is false app.use(requestIP.mw({ attributeName: 'clientIP' })
推荐 Nginx 配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr;
https://stackoverflow.com/a/19524949/1918831
req.socket.remoteAddress
req.connection.socket.remoteAddress
req.info.remoteAddress
req
http.IncomingMessage
req.connection
req.socket
req.connection.socket
req.info
获取 IP 的几种来源
req.connection.remoteAddress
参考: https://nodejs.org/api/net.html#net_socket_remoteaddress
指 socket 连接的源IP信息, 适用于客户端 直连 服务端的场景.
X-Forwarded-For (RFC 7239)
通常 Server 端不会直接与 Client 端通信, 而是通过 Nginx 等代理接受客户端请求, 这时候
remoteAddress
是代理服务的地址, 无法描述客户端IP.由此引入了HTTP 扩展协议头:
X-Forwarded-For
, 格式是:获取的时候取
X-Forwarded-For
的第一个 IP 地址即可. 但需要注意的是:X-Forwarded-For
可伪造!通常 Nginx 作为 proxy 时的配置:
X-Real-IP
代理程序设置请求源的 IP 信息, 目前并不是 RFC 标准.
X-Real-IP
不可伪造, 但仅能描述最近一个代理的真实IP, 如果有多级代理, 仍旧不可作为真实客户端的 IP.通常 Nginx 作为 proxy 时的配置:
对比
Express 中获取 IP 方式及建议
req.ip (readonly)
默认是返回的是
req.connection.remoteAddress
; 当设置app.set('trust proxy', true)
时, 返回的是X-Forwarded-For
中的第一个 IP;req.ip
背后用的即是proxy-addr
, 不单独讨论.request-ip
综合了多种 Header 建立了 IP 获取的优先顺序, 同时如果有伪造的异常数据会进行过滤.
https://github.com/pbojinov/request-ip#how-it-works
推荐 Express 做法
使用
request-ip
库:推荐 Nginx 配置:
引申阅读
req 上的各种 remoteAddress 异同
https://stackoverflow.com/a/19524949/1918831
req.connection.remoteAddress
req.socket.remoteAddress
req.connection.socket.remoteAddress
req.info.remoteAddress
req
是http.IncomingMessage
的实例req.connection
===req.socket
: https://nodejs.org/api/http.html#http_request_socket (lib/_http_incoming.js)req.connection.socket
: https only & node <= 0.11.2 有效req.info
: for hapi 框架, https://hapijs.com/api#-requestinfo参考资料