1.速度网络高防产品使用proxy protocol(简称PP协议)来传递用户真实IP。当前高防IP使用的为proxy_protocol 的V1版本。
2.设置proxy protocol 开启。
3.HTTP协议如何通过非网站防护 获取客户端真实IP?
以Nginx为例:
// 如果您的源服务器nginx为直接的源,不再反向代理到其他的上游,则$proxy_protocol_addr变量即为真实用户的IP。可通过修改Nginx日志格式,在access.log日志查看。也可直接打印请求头。参考下图1
server {
listen 8443 proxy_protocol("**请在您的源服务器的端口处添加 'proxy_protocol' ");
....(其他配置省略)
}
//如您的源服务器Nginx转发请求到其他上游
server {
listen 8443 proxy_protocol("请在您的源服务器的端口处添加 'proxy_protocol' ");
proxy_set_header X-PP-RealIp $proxy_protocol_addr;//您可通过该语法,将用户真实IP,定义为任意字段(本例为X-PP-RealIp),转发给上游,结果请见图2
location / {
proxy_pass http://backend.example2.com:8088;
......(省略配置)
}
}
图1
图2
4.TCP服务如何获取用户的真实IP
- 在三次握手后,数据接收阶段获取的报文中.会首先收到一个字符串,如(“PROXY TCP4 119.188.212.127 123.129.229.123 41774 8082”)。
其中以空格为分隔符,119.188.212.127 为客户端的真实IP,123.129.229.123 为高防IP,8082 为端口。 - 实现代码
php
//创建Server对象,监听 127.0.0.1:9501 端口
$server = new Swoole\Server("0.0.0.0", 8082);
//监听连接进入事件
$server->on("Connect", function ($server, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
$server->on("Receive", function ($server, $fd, $from_id, $data) {
$fd_info = $server->getClientInfo($fd);
//var_dump($fd_info);
var_dump($data);
$is_proxy = substr($data,0,5);
if($is_proxy == "PROXY"){
$proxy_arr = explode(" ",$data);
echo "真实ip:".$proxy_arr[2]."\n";
echo "高防ip:".$proxy_arr[3]."\n";
}
$server->send($fd, "Server: " . $data);
});
//监听连接关闭事件
$server->on("Close", function ($server, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$server->start();
?>
Node.js版本:
- 到Github下载对应的库 https://github.com/moznion/proxy-protocol-js ,也可以
npm proxy-protocol-js
。 - 服务器解析(高防IP使用V1版本的 代理协议)
var net = require('net');
const proxyProtocol = require('proxy-protocol-js');
const PORT = 18001;
const HOST = '0.0.0.0'
var clientHandler = function(socket){
//客户端发送数据的时候触发data事件
socket.on('data', function dataHandler(data) {//data是客户端发送给服务器的数据
var is_proxy = data.toString().substring(0,5);
if(is_proxy == "PROXY"){
const proto = proxyProtocol.V1ProxyProtocol.parse(data.toString());
console.log(proto);
}else{
console.log(socket.remoteAddress, socket.remotePort, 'send', data.toString());
}
//服务器向客户端发送消息
socket.write('server received\n');
});
//当对方的连接断开以后的事件
socket.on('close', function(){
console.log(socket.remoteAddress, socket.remotePort, 'disconnected');
})
};
//创建TCP服务器的实例
//传入的参数是:监听函数clientHandler
var app = net.createServer(clientHandler);
app.listen(PORT, HOST);
console.log('tcp server running on tcp://', HOST, ':', PORT);
- 测试结果
使用telnet 高防IP 填写的转发端口