Netty获取真实IP
时间:2023-01-05 19:30:00
本文参考: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
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"; }