案例
var koa = require('koa')
var app = new koa()
app.use(function (ctx,next) {
ctx.body = ctx.ip
})
app.listen('9090')
同時nginx設置代理:
server {
listen 8062;
server_name localhost;
proxy_set_header X-Forwarded-For "110.11.11.11,11.11.11.11";
location / {
proxy_pass http://127.0.0.1:9090;
}
}
本地訪問localhost:8062的結果:::ffff:127.0.0.1
這個結果是怎么來的呢?
koa處理ip
主要是下面的程序
// application.js
this.proxy = options.proxy || false;
this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For';
this.maxIpsCount = options.maxIpsCount || 0;
// request.js
get ip() {
if (!this[IP]) {
this[IP] = this.ips[0] || this.socket.remoteAddress || '';
}
return this[IP];
},
get ips() {
const proxy = this.app.proxy;
const val = this.get(this.app.proxyIpHeader);
let ips = proxy && val
? val.split(/\s*,\s*/)
: [];
if (this.app.maxIpsCount > 0) {
ips = ips.slice(-this.app.maxIpsCount);
}
return ips;
},
變量解釋:
proxy: default false;當proxy為false的時候, getter ips 返回一個空數組,getter ip 返回this.socket.remoteAddress;
proxyIpHeader: 自定義IpHeader,用來接收消息頭中的ip,默認"X-Forwarded-For";當proxy為true的時候 ,程序會解析消息頭 "X-Forwarded-For"中的值,假如這個值是"client, proxy1, proxy2",經過解析后 getter ips返回數組 ["client", "proxy1", "proxy2"]。getter ip 返回this.ips[0]即"client";
maxIpsCount:maxIpsCount默認值為0,不太明白這個選項的使用場景
地址前面的:::ffff是什么
:::ffff其實與ipv6有關;nodejs文檔:
如果
host
省略,如果 IPv6 可用,服務器將會接收基於未指定的 IPv6 地址 (::
) 的連接,否則接收基於未指定的 IPv4 地址 (0.0.0.0
) 的連接。
所以為了避免出現這種地址,需要監聽0.0.0.0,或者自己的局域網地址
app.listen('9090','0.0.0.0')
總結:
如果開發者認為請求來自於代理服務器的轉發,需要設定proxy:true,再設置對應的proxyIpHeader(畢竟不是都是X-Forwarded-For),然后獲取客戶端IP;
如果開發者認為中間沒有代理服務器,那么程序會直接取remoteAddress來獲取客戶端IP。
那么又有個疑問,express是如果獲取IP的呢?
如有錯誤之處,望請斧正。