一般我们会在搭建代理服务器来转发到具体的应用,在这些应用里,怎样读取到代理之前的客户端ip呢?下面以nignx和koa举例。
首先客户端的请求到达nginx代理服务器,我们可以通过设置headers的X-Forwarded-For来记录客户端ip,这是http的扩展头部,用来表示HTTP请求端的真实IP。
具体配置示例如下:
location / {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
}
这一HTTP头一般格式如下:
X-Forwarded-For: client1, proxy1, proxy2
其中的值通过一个 逗号+空格 把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client1被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1被添加到XFF中,之后请求被发往proxy3;通过proxy3时,proxy2被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。
$proxy_add_x_forwarded_for
the “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.
nginx会往接收到的http headers X-Forwarded-For中添加$remote_addr(此次请求的ip地址)。
所以X-Forwarded-For中最左边的ip地址便是我们想要的客户端ip。
node.js的koa框架中,使用ctx.ip来表示http请求的ip。但此时http请求是通过我们前面搭建的代理服务器转发来的,此时如果没有告诉koa,ctx.ip便显示代理服务器的ip。如果我们能告诉koa去读取headers信息中的X-Forwarded-For信息,并读取第一个ip,那便是“真正的”客户端ip了。
具体看看koa源码中怎样实现的:
module.exports = {
...
get ip() {
return this.ips[0] || this.socket.remoteAddress || '';
},
get ips() {
var proxy = this.app.proxy;
var val = this.get('X-Forwarded-For');
return proxy && val
? val.split(/\s*,\s*/)
: [];
},
...
}
从源码中可以看出,如果我们设置了app.proxy的值为true,那koa便能实现上述需求。
具体设置如下:
var Koa = require('koa');
var app = new Koa();
app.proxy = true; // 设置一些proxy header 参数会被加到信任列表中
另外在express中,可以通过下面形式设置信任proxy server信息:
app.enable('trust proxy');
这样设置之后,便可以通过如下形式来获取到所需的ip了:
app.use(function *() {
console.log(this.ip);
});
因为X-Forwarded-For可以随意更改,而且http请求到我们代理服务器时,往往会经过多层代理,如果某个代理服务器“不诚实”地修改X-Forwarded-For信息, 那么我们获取到的ip有可能并不是操作者的ip。所以获取客户端请求ip的真实性不高,只能作为参考。
感谢您的阅读!
如果看完后有任何疑问,欢迎拍砖。
欢迎转载,转载请注明出处:http://www.yangrunwei.com/a/66.html
邮箱:glowrypauky@gmail.com
QQ: 892413924