锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Netty获取真实IP

时间:2023-01-05 19:30:00 2e302电容柜用

本文参考:https://www.jianshu.com/p/cc8d592582c9 感谢分享

Netty获取真实IP

netty想要获得客户端请求的IP有两种方法:

一、通过ChannelHandlerContext

String ip=connContext.getClientIP().replace("/","").split(":")[0]; 

如果使用代理,此时获得IP代理服务器IP

二、通过nginx获取真实IP

nginx对TCP协议代理需要引入stream并修改模块nginx配置:

stream{     upstream tcpstream{         server  10.1.11.67:10001 weight=1;     }     server{         listen 80;         proxy_connect_timeout 20s;         proxy_timeout 1m;         # 开启代理         proxy_protocol on;         proxy_pass tcpstream;     }    error_log logs/error.log; } 

proxy protocol是HAProxy的作者Willy Tarreau2010年开发设计Internet协议,通过tcp添加一个小的头部信息,方便客户端信息(协议栈、源IP、目的IP、源端口、目的端口等。),在复杂的网络条件下,需要获得用户的真实性IP非常有用。本质上,代理在三次握手后,将一个携带原始连接四元组信息的数据包插入连接中。

  • 目前 proxy protocol有两个版本,v1仅支持human-readable报头格式(ASCIII码),v2需同时支持human-readable与二进制格式兼容v1格式
  • proxy protocol接收端必须完整有效地接收 proxy protocol 连接数据可以在头部开始处理。因此,服务器的同一监控端口没有兼容带proxy protocol连接和不带包proxy protocol包的连接。如果服务器收到的第一个数据包不符合proxy protocol服务器将直接终止连接格式。
    在这里插入图片描述
    三次握手成功后获得byte数据转化为16进制:
50524f58592054435034203132372e302e302e31203132372e302e302e312036303634322038300d0a 

分析结果如下:

PROXY TCP4 127.0.0.1 127.0.0.1 60642 80  注意结果为PROXY TCP4 127.0.0.1 127.0.0.1 60642 80\r\n 所以上面会换行 

解析代码

以上分析只有一层代理,如果两层代理获得的数据是什么?

50524f585920544350342031302e312e31312e36362031302e312e31312e36382035333732382038300d0a50524f585920544350342031302e312e352e32372031302e312e31312e36362036353431312038300d0a 

分析结果如下:

获取到数据PROXY TCP4 10.1.11.66 10.1.11.68 53728 80  PROXY TCP4 10.1.5.27 10.1.11.66 65411 80  

解析代码

public class MessageDecoder extends ByteToMessageDecoder {   protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception {   log.info("收到数据:{}",ctx.channel().id(),ByteBufUtil.hexDump(buffer));   if(buffer.readableBytes() < ProtocolDataHead.LENGTH){    return;   }    //protocol head         ProtocolDataHead header = ProtocolDataHead.fromData(ByteBufUtil.getBytes(buffer,0,ProtocolDataHead.LENGTH));         if(header.getStartMark().equals(ProtocolDataHead.STARTMARK)){          ///公司业务代码,不展示         } else if(header.getStartMark().equals(NginxIPConst.NGINX_IP_TWO)){          if(buffer.readableBytes()0){     byte[] nginxIP=new byte[readData.indexOf(NginxIPConst.NGINX_IP_END)/2 2];     buffer.readBytes(nginxIP);     NginxUtils.checkHead(ctx.channel().id().toString(),nginxIP);     return;    }else{     buffer.clear();    }   }else{    log.info("收到数据错误:{}",ByteBufUtil.hexDump(buffer));    buffer.clear();    return;   }  } }  
public class NginxUtils {     private static ConcurrentHashMap ipMap=new ConcurrentHashMap<>(1000);      public static void checkHead(String channelId,byte[] bytes){         String nginxIP=new String(bytes, Charset.forName("UTF-8"));         log.info("获取数据{}",nginxIP);         String[] strs=nginxIP.split(" ");         if(strs.length>2){             ipMap.put(channelId,strs[2]);         }     }      public static String getIp(String channelId){         return ipMap.get(channelId);     }      public static String removeIp(String channelId){         return ipMap.remove(channelId);     } } 
public class NginxIPConst {      //nginx透传ip最小长度     public static final int NGINX_IP_LENGTH = 41;      //nginx透传ip前两位数据     public static final String NGINX_IP_TWO = "PR";      //nginx结尾符     public static final String NGINX_IP_END = "0d0a"; } 
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章