VPN 在Android中的通信四 (netty TLS绑定)

        对于VPN应用来说,为了提升安全性,对消息加密是常规操作。

        众所周之,Netty是高性能的Java NIO网络通信框架,因而用Netty来写VPN通信是再正常不过了。网上关于为Netty生成、以及使用SSL/TLS证书的文章有很多,但由于各种原因,生成的证书要么是Netty中无法读取和使用,要么是代码不全或不具体导致根本配不通SSL/TLS加密。(通常TLS有两种 普通TLS 和国密TLS,本章主要讲述普通TLS)

一、通过openSSL 生成证书

        OpenSSL是一个开放源代码的软件库,应用程序可以使用这个包来进行安全通信,它包括代码、脚本、配置和过程的集合。其主要库是以 C 语言所写成,实现了基本的加密功能,实现了 SSL 与 TLS 协议。OpenSSL整个软件包大概可以分成三个主要功能部分:SSL协议库、应用程序、密码算法库。

        如果自己电脑已经安装了openSSL并配置相应的环境变量,可以直接使用命令生成证书。

命令如下:

         创建私钥证书 openssl genrsa -des3 -out netty/netty-key.pem 1024

        创建证书请求 openssl req -new -out netty/netty-req.csr -key netty/netty-key.pem   

        生成公钥证书    openssl x509 -req -inca/ca-req.csr -out netty/netty-cert.crt -signkey netty/netty-key.pem -days 3650

二、netty 绑定TLS证书

1、创建一个sslContext 来绑定证书

 if (sslContext != null) {
            return;
        }
        if (BuildConfig.GMSSL_ENABLE) {
//这是国密的TLS证书 本章暂时忽略
            try {
                sslContext = (SslContext) GmUtils.getInstance().createNettySslContext(clientCry, clientKey, caCrt, signGm, signGmKey);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
        InputStream clientCryInput = new ByteArrayInputStream(clientCry.getBytes());
        InputStream clientKeyInput = new ByteArrayInputStream(clientKey.getBytes());
        InputStream caCrtInput = new ByteArrayInputStream(caCrt.getBytes());
        try {
            this.sslContext = SslContextBuilder
                    .forClient()
                    .keyManager(clientCryInput, clientKeyInput)
                    .trustManager(caCrtInput)
                    .build();
        } catch (SSLException e) {
            e.printStackTrace();
            Logger.p("fail to create ssl", e);
        }

2、在netty中绑定 sslContext,创建一个SslHandler 来处理sslContext 如下:

public class SslHandler extends ChannelInitializer<SocketChannel> {
    private SslContext sslContext;
    private ConcurrentLinkedQueue<ByteBuffer> readQueue;
    private ConcurrentLinkedQueue<Object> writeQueue;

    public SdpNettyHandler(SslContext sslContext, ConcurrentLinkedQueue<ByteBuffer> readQueue,ConcurrentLinkedQueue<Object> writeQueue) {
        this.sslContext = sslContext;
        this.writeQueue = writeQueue;
        this.readQueue = readQueue;
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        if (this.sslContext != null) {
//绑定sslContext
            ch.pipeline().addLast(this.sslContext.newHandler(ch.alloc()));
        }
        ch.pipeline().addLast(new TcpFrameEncoder());
        ch.pipeline().addLast(new HeartHandler(readQueue,writeQueue));
        ch.pipeline().addLast(new EchoClientHandlerV2(this.readQueue));
        ch.pipeline().addLast(new EchoClientHandler(this.readQueue));

        ch.pipeline().addLast(new DatagramDnsResponseDecoder());
    }
}

3、在创建netty 连接绑定SslHandler

      bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                    .resolver(MyAddressResolverGroup.getInstance(hostMap))
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
                    .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(5000, 5000, 80000))
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new SslHandler(sslContext, readQueue, writeQueue));
            channelFuture = bootstrap.connect(host, port).sync();

到此netty 绑定证书完毕

上一遍章 VPN 在Android中的通信三 (netty DNS 域名自解析)

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尚思app

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值