当前位置:首页 > 网赚资讯 > 正文内容

Java,Netty,实现HTTP代理服务器,IP安全过滤,代码案例分享

夜猫(夜猫子)4个月前 (01-21)网赚资讯37

介绍说明

普通代理(Http)

Http,RFC 7230中描述为普通代理,其代理扮演的是“中间人”角色,对于连接到它的客户端来说,它是服务端,对于要连接的服务端来说,它是客户端,代理服务器负责在两端之间来回传送HTTP报文。

隧道代理(Https)

Https,代理服务器是一个web服务器,影响了客户端和服务器的TLS加密连接的。此时主要使用RFC中定义的通过 Web 代理服务器用隧道方式传输基于 TCP 的协议的隧道代理方式,它的主要流程为:

1、浏览器首先发送Http Connect请求给代理服务器,发送目标主机信息。

2、代理服务器建立和目标主机的tcp链接,并向浏览器回应Connection Established应答。

3、浏览器将请求发送给代理服务器,代理服务器透传给目标主机。

4、目标主机将响应回给代理服务器,代理服务器将响应回给浏览器。

Netty实现

Netty高性能网络框架,支持OIO(阻塞式传输)/NIO(非阻塞式传输)等能力,同时屏蔽了网络底层现,使开发人员专注于应用逻辑开发。

Netty框架中大量运用了直接内存用来提高效率,编写代码时要注意及时释放资源,避免内存泄漏问题。

代码分享

<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.70</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15to18</artifactId> <version>1.70</version> </dependency> <!-- netty-all --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.60.Final</version> </dependency>package com.what21.netty03.demo01; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.net.InetSocketAddress; public class HttpServer { private String serverName; private String bindHost; private int bindPort; public HttpServer(String serverName, String bindHost, int bindPort) { this.serverName = serverName; this.bindHost = bindHost; this.bindPort = bindPort; } public void start() throws Exception { // 用于Acceptor的主"线程池" EventLoopGroup bossEventGroup = new NioEventLoopGroup(); // 初始化==>用于I/O工作的从"线程池" EventLoopGroup workerEventGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); // group方法设置主从线程池 serverBootstrap.group(bossEventGroup, workerEventGroup); // 指定通道channel类型,服务端为:NioServerSocketChannel serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024); serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true); serverBootstrap.handler(new LoggingHandler(LogLevel.INFO)); serverBootstrap.childHandler(new HttpServerInitializer()); ChannelFuture bindFuture = null; if ("0.0.0.0".equalsIgnoreCase(this.bindHost)) { bindFuture = serverBootstrap.bind(this.bindPort).sync(); } else { InetSocketAddress bindAddress = new InetSocketAddress(this.bindHost, this.bindPort); bindFuture = serverBootstrap.bind(bindAddress).sync(); } Channel parentChannel = bindFuture.channel(); bindFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { if (channelFuture.isSuccess()) { System.out.println(HttpServer.this.serverName + ",绑定监听成功," + channelFuture.channel().localAddress()); } else { System.err.println(HttpServer.this.serverName + ",绑定监听失败!" + channelFuture.cause()); } } }); ChannelFuture closeFuture = bindFuture.channel().closeFuture().sync(); closeFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { if (channelFuture.isSuccess()) { System.out.println(HttpServer.this.serverName + ",停止监听成功," + channelFuture.channel().localAddress()); } else { System.err.println(HttpServer.this.serverName + ",停止监听失败!" + channelFuture.cause()); } } }); } catch (Exception e) { e.printStackTrace(); } finally { // 优雅退出,释放"线程池" if (bossEventGroup != null) { bossEventGroup.shutdownGracefully(); } if (workerEventGroup != null) { workerEventGroup.shutdownGracefully(); } } } public static void main(String[] args) { try { new HttpServer("HTTP代理服务器", "0.0.0.0", 8888).start(); } catch (Exception e) { e.printStackTrace(); } } }package com.what21.netty03.demo01; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.ipfilter.IpFilterRule; import io.netty.handler.ipfilter.IpFilterRuleType; import io.netty.handler.ipfilter.IpSubnetFilterRule; import io.netty.handler.ipfilter.RuleBasedIpFilter; import java.net.InetSocketAddress; public class HttpServerInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel ch) throws Exception { IpSubnetFilterRule rule1 = new IpSubnetFilterRule("192.168.119.1", 24, IpFilterRuleType.ACCEPT); IpSubnetFilterRule rule2 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.REJECT); IpFilterRule rejectAll = new IpFilterRule() { @Override public boolean matches(InetSocketAddress remoteAddress) { return true; } @Override public IpFilterRuleType ruleType() { return IpFilterRuleType.REJECT; } }; RuleBasedIpFilter filter = new RuleBasedIpFilter(rule1, rejectAll); ch.pipeline().addLast("ipFilter", filter); ch.pipeline().addLast("httpServerCodec", new HttpServerCodec()); ch.pipeline().addLast("httpObjectAggregator", new HttpObjectAggregator(65536)); ch.pipeline().addLast("httpProxyServerHandler", new HttpProxyServerHandler()); } }package com.what21.netty03.demo01; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.handler.codec.http.*; public class HttpProxyServerHandler extends ChannelInboundHandlerAdapter { private ChannelFuture cf; private String host; private int port; @Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { if (msg instanceof FullHttpRequest) { FullHttpRequest request = (FullHttpRequest) msg; String host = request.headers().get("Host"); String[] temp = host.split(":"); int port = 80; if (temp.length > 1) { port = Integer.parseInt(temp[1]); } else { if (request.uri().indexOf("https") == 0) { port = 443; } } this.host = temp[0]; this.port = port; String authorization = request.headers().get("Authorization"); System.out.println("http basic认证信息:" + authorization); if ("CONNECT".equalsIgnoreCase(request.method().name())) { // HTTPS建立代理握手 HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); ctx.writeAndFlush(response); ctx.pipeline().remove("httpServerCodec"); ctx.pipeline().remove("httpObjectAggregator"); return; } //连接***目标服务器 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(ctx.channel().eventLoop()) // 注册线程池 .channel(ctx.channel().getClass()) // 使用NioSocketChannel来作为连接用的channel类 .handler(new HttpProxyInitializer(ctx.channel())); ChannelFuture cf = bootstrap.connect(temp[0], port); cf.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { future.channel().writeAndFlush(msg); } else { ctx.channel().close(); } } }); //ChannelFuture cf = bootstrap.connect(temp[0], port).sync(); //cf.channel().writeAndFlush(request); } else { // https 只转发数据,不做处理 if (cf == null) { //连接***目标服务器 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(ctx.channel().eventLoop()) // 复用客户端连接线程池 .channel(ctx.channel().getClass()) // 使用NioSocketChannel来作为连接用的channel类 .handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx0, Object msg) throws Exception { ctx.channel().writeAndFlush(msg); } }); } }); cf = bootstrap.connect(host, port); cf.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { future.channel().writeAndFlush(msg); } else { ctx.channel().close(); } } }); } else { cf.channel().writeAndFlush(msg); } } } }package com.what21.netty03.demo01; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpObjectAggregator; public class HttpProxyInitializer extends ChannelInitializer { private Channel clientChannel; public HttpProxyInitializer(Channel clientChannel) { this.clientChannel = clientChannel; } @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new HttpClientCodec()); ch.pipeline().addLast(new HttpObjectAggregator(512 * 1024)); ch.pipeline().addLast(new HttpProxyClientHandler(clientChannel)); } }package com.what21.netty03.demo01; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.FullHttpResponse; public class HttpProxyClientHandler extends ChannelInboundHandlerAdapter { private Channel clientChannel; public HttpProxyClientHandler(Channel clientChannel) { this.clientChannel = clientChannel; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse response = (FullHttpResponse) msg; //修改http响应体返回***客户端 response.headers().add("response", "from proxy"); clientChannel.writeAndFlush(msg); } }

扫码打开(YM云库)小程序
夜猫博客首页已更新,请及时查看哦!
项目更新推送Q群(值得关注)

夜猫博客项目分享群(扫码加入)

分享给朋友:

相关文章

如何通过知识付费的大趋势赚钱 三个方面低成本挖掘高财富

如何通过知识付费的大趋势赚钱 三个方面低成本挖掘高财富

如何通过知识付费的大趋势赚钱 三个方面低成本挖掘高财富 查看地址:https://www.fenxiangbacy.com/post-2648.html...

分享最新的27个懒人快速赚钱项目 让你睡着也能赚钱

分享最新的27个懒人快速赚钱项目 让你睡着也能赚钱

分享最新的27个懒人快速赚钱项目 让你睡着也能赚钱 查看地址:https://www.fenxiangbacy.com/post-2646.html...

公众号运营技巧:4种提价值方法打造独具一格的公众号

公众号运营技巧:4种提价值方法打造独具一格的公众号

人们会被事物的表象所吸引,倾向于解决表象问题而忽略本质问题。 拿时下最让我们运营人虐心的公众号运营来说,大伙儿投入都很大,但这一两年来,很显然,大部分的公众号阅读率不升反降:标题党、追热点、捧热...

自媒体100w阅读量爆文写作技巧总结 标题+文案如何优化

自媒体100w阅读量爆文写作技巧总结 标题+文案如何优化

作为自媒体人,相信每个人都有个10W+爆文的梦想,但是能做到的人***。 实际上文章能成为爆文并不是靠运气,决定文章能否成为爆文的***个要素就是标题,其二是内容。标题是文章的眼睛,标题质量的高低直...

靠抖音一天赚了100多万佣金,她到底做了什么?

靠抖音一天赚了100多万佣金,她到底做了什么?

当天,还有人在朋友圈高呼“后生可畏”——“今天全抖音的带货达人都被一个大一新生按在地上摩擦……互联网原住民真可怕,也是一个里程碑,一天100万的佣金,视频电商才刚刚开始”。...

网红经济该何去何从?定向引流的网赚营销技巧

网红经济该何去何从?定向引流的网赚营销技巧

网红经济,依托网红,通过社交网赚媒体上聚集人气,拉拢粉丝,再依托日渐庞大的粉丝群体进行定向精准营销,进而将粉丝转化为销售额或者其他价值的新经济模式。 2018年,粉丝规模在10万人以上的网络红人...