Netty 获取真实IP - housekeeper-software/tech GitHub Wiki
TCP服务器
初始化channel
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(ProxyProtocolChannelHandler.NAME, new ProxyProtocolChannelHandler()); //这个放在最前面
ch.pipeline().addLast(
new StreamMessageDecoder(),
new StreamMessageEncoder(),
handler.newIdleStateHandler(),
new StreamServerHandler(handler));
}
ProxyProtocolChannelHandler的实现
public class ProxyProtocolChannelHandler extends ChannelInboundHandlerAdapter {
public static final String NAME = ProxyProtocolChannelHandler.class.getSimpleName();
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
try {
ProtocolDetectionResult<HAProxyProtocolVersion> result = HAProxyMessageDecoder.detectProtocol((ByteBuf) msg);
// TODO - is it possible that this message could be split over multiple ByteBufS, and therefore this would fail?
if (result.state() == ProtocolDetectionState.DETECTED) {
// Add the actual HAProxy decoder.
// Note that the HAProxyMessageDecoder will remove itself once it has finished decoding the initial ProxyProtocol message(s).
ctx.pipeline().addAfter(NAME, null, new HAProxyMessageDecoder());
// Remove this handler, as now no longer needed.
ctx.pipeline().remove(this);
}
} catch (Exception e) {
((ByteBuf) msg).release();
}
}
super.channelRead(ctx, msg);
}
}
正常的消息handler
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if(msg instanceof HAProxyMessage){
HAProxyMessage message = (HAProxyMessage) msg;
ctx.channel().attr(ChannelUtil.CLIENT_IP).set(InetAddress.getByName(message.sourceAddress()));
message.release();
}else {
}
}
Websocket 服务器
初始化 channel
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("httpServerCodec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpHeadersHandler()); //放在 WebSocketServerProtocolHandler之前
pipeline.addLast(new WebSocketServerProtocolHandler("/"));
pipeline.addLast("httpHandler", new WebsocketServerHandler(server));
}
HttpHeadersHandler 实现
public class HttpHeadersHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
HttpHeaders headers = ((FullHttpRequest) msg).headers();
String realip = headers.get("X-Real-IP");
if (realip != null && !realip.isEmpty()) {
ctx.channel().attr(ChannelUtil.CLIENT_IP).set(InetAddress.getByName(realip));
} else {
String forwarded_for = headers.get("X-Forwarded-For");
if (forwarded_for != null && !forwarded_for.isEmpty()) {
ctx.channel().attr(ChannelUtil.CLIENT_IP).set(InetAddress.getByName(forwarded_for.split(",")[0].trim()));
}
}
ctx.channel().pipeline().remove(this);
}
ctx.fireChannelRead(msg);
}
}
这里是保存到channel属性里