Netty OpenSsl

本文介绍了如何在Java应用中通过Nettyx集成OpenSSL进行安全通信,包括证书的生成、管理以及在客户端和服务端的配置,强调了安全实践和复用SslContext的重要性。
摘要由CSDN通过智能技术生成

概要

  网络世界 君子还是少数, 为了防范不法分子窃取我们的消息, 一般都会对消息进行加密.
当然这场景相对于Java来说还是少数, 毕竟现在大部分已经上各种云,服务和服务之间通信不需要经过公网

但如果你的通信链路可能需要经过外网, 那么极其建议你套一层安全层!!

TIPS: 鉴于网络安全手段之多, 读者需要自行辨别使用哪一种解决方案, 是黑白名单,接入认证, AES,TLS,UP, 还是CA

一般而言, 离公网越近, 防范手段越多, 离私网越近, 防范手段越少

  接下来将展示如何使用Nettyx来让你的应用提供对Openssl的支持

先引入Nettyx的依赖

确保使用最新版本nettyx,此处为了演示使用了如下版本
<dependency>
    <groupId>io.github.fbbzl</groupId>
    <artifactId>nettyx</artifactId>
    <version>2.3.3-RELEASE</version>
</dependency>

OpenSsl Scirpts

  使用OpenSsl的 懵逼点 其实是在如何生成证书上, 如果是大型企业,证书的颁发会有专门的安全部门管理, 但像一些小项目, 创业公司等可能并没有, 需要开发人员自己生成配套证书, 这一点新手可能会摸不着头脑.


正文开始

  首先确认生成证书的操作系统是否已经安装Openssl,我记得大部分Linux发行版都是自带OpenSsl的, 安装部分不做介绍, 各位大聪明自行解决,只要确保生成证书的机器上安装完Openssl工具即可

OK,我们继续往下
  Nettyx提供了一键初始化Openssl的脚本, 在源码同级src目录下存在一个support目录,其中的openssl子目录便存放了该脚本, 使用时必须去gitee和github上下载源码,而不是引入依赖这么简单, 后续会考虑提供api来调用生成
源码地址:
gitee: https://gitee.com/fbbzl/nettyx
github: https://github.com/fbbzl/nettyx
在这里插入图片描述接下来将介绍support/openssl/linux目录

  1. ./ca: 存放了生成ca证书的脚本 openssl_init_ca_root.sh, 用于生成根证书
  2. ./client: 存放了客户端的三个证书脚本 openssl_client_do_sign.sh, openssl_client_init.sh, openssl_client_pkcs8_key.sh. 分别是用来签名的脚本, 初始化客户端证书的脚本, 转pkcs8格式证书的脚本,读者可以根据自己的需求修改脚本内的一些值, 比如证书有效期
  3. ./cnf: 存放了openssl的配置文件openssl.cnf
  4. ./server: 存放了服务端的三个证书脚本 openssl_server_do_sign.sh,openssl_server_init.sh,openssl_server_pkcs8_key.sh三个证书和客户端功能一样
  5. ./openssl_auto_all.sh: 一键初始化所有证书并用root证书进行签名
  6. ./openssl_auto_client.sh: 一键初始化客户端并用root证书进行签名, 客户端用
  7. ./openssl_auto_server: 一键初始化服务端并用root证书进行签名, 服务端用
  8. ./openssl_env.sh: 脚本环境变量配置, 不用的脚本用户, 所在的环境不同, 环境变量也可能会不一样, 在读者执行脚本之前,请先设置此脚本中的值, 必须配置!!!
  9. ./openssl_init_dir.sh: 初始化openssl工作目录, 如果是第一次生成openssl证书, 需要执行此脚本

虽然我每个脚本功能都介绍了一遍, 但是实际读者只需要关心./openssl_auto_all.sh即可, 唯一要注意的是所有脚本用户必须配置./openssl_env.sh!!!因为这是脚本的执行环境配置, 所有用户都不一样, , 整个生成证书的过程中需要人机交互, 根据控制台提示输入指定信息即可,例如需要输入公司名称,组织名称, 地域信息,城市省份什么的,按照实际信息填写即可, 证书密码别输错了


假设你现在已经生成好证书了, 继续往下看

OpenSslContextFactory

  证书生成之后的使用反而是很简单的,只需要在应用中配置 根证书和自端签名后的证书, 密码即可, Nettyx提供了OpenSslContextFactory来获取一个SslContext, 尽量复用SslContext,它是Netty实现SSL的关键!!!

以下将展示如何初始化一个OpenSslContextFactory

    @Configuration
    public class SslConfiguration {
       // 这里只是简单展示如何配置, 其实不建议将配置放入java代码, 如何将ssl的配置放入yml,properties配置文件, 相信各位大聪明知道如何解决, 在此不做讲解
        @Bean
        public OpenSslContextFactory sslContextFactory() {
            OpenSslConfig openSslConfig = new OpenSslConfig();
            // 必填 根证书
            openSslConfig.setRoot();	
			// 必填 自端证书, 如果是客户端则配置客户端证书路径, 如果是服务端则配置服务端证书路径
            openSslConfig.setCert();
            // 必填 jks file就是带pkcs8的文件
            openSslConfig.setKey();
            // 非必填 pkcs8文件的密码, 如果没有则不用配置
            openSslConfig.setKeyPass();

            return new OpenSslContextFactory(openSslConfig);
        }
    }

  在完成了OpenSslContextFactory的构建之后, 离成功只差一步了, 接下来通过下图中的API获取SslContext, 客户端和服务端依然是不一样的

首先看下客户端的Channel初始化器如何使用

@Slf4j
@RequiredArgsConstructor
public class TestChannelInitializer<C extends Channel> extends ChannelInitializer<C> {

		// 通过构造参数传入sslFactory即可, 不要把ChannelInitializer变成bean, 如果ChannelInitializer的初始化有重复代码
		// 可以尝试使用Factory模式, 比如建一个ChannelInitializerFactory组件等等
		private final OpenSslContextFactory sslFactory;

    @Override
    protected void initChannel(C channel) throws SSLException {
        // 建议使用 spring的配置bean来配置openssl的证书的目录, 这里为了演示, 直接new
        // 客户端和服务端不同的是, 客户端可能会有多个, 如果多个客户端使用同一份客户端签名证书, 这虽然降低了证书管理和应用部署的难度, 但是安全系数降低了,一个被破解就全部都破解, 但是如果多个客户端生成自己各自的签名证书, 安全度提升但是管理和部署的难度又会提升, 怎么说呢, 没有银弹, 还请各位自行斟酌

        // 尽量复用SslContext实例, 此处获取的是客户端的sslcontext
        SslContext clientSslContext = sslFactory.getClientSslContext();
        SslHandler clientSslHandler = clientSslContext.newHandler(channel.alloc());
        
        channel.pipeline().addLast(
                // 如果程序 既要接收ssl又要接收非ssl, 可以使用OptionalSslHandler
                clientSslHandler
                , new StartEndFlagFrameCodec(320, true, wrappedBuffer(new byte[]{(byte) 0x7e}))
                , new EscapeCodec(EscapeMap.mapHex("7e", "7d5e"))
                , new UserCodec()
                , new LoggerHandler(log, INFO));
    }
}

接下来是服务端的Channel初始化器, 和客户顿的ssl就只是证书的目录不一样, 其他几乎一样

@Slf4j
public class TestChannelInitializer<C extends Channel> extends ChannelInitializer<C> {

    @Override
    protected void initChannel(C channel) throws SSLException {
        // 建议使用 spring的配置bean, 这里为了演示, 直接new
        OpenSslConfig serverSslConfig = new OpenSslConfig();
        serverSslConfig.setCert("/usr/local/yourapp/ssl/server/xxx.cer");
        serverSslConfig.setKey("/usr/local/yourapp/ssl/server/xxx.key");
        serverSslConfig.setKeyPass("a$5sdf2@##$");
        serverSslConfig.setRoot("/usr/local/yourapp/ssl/root/yyy.cer");

        // 尽量复用SslContext实例, 此处获取的是客户端的sslcontext
        SslContext serverSslContext = new OpenSslContextFactory(serverSslConfig).getServerSslContext();
        SslHandler serverSslHandler       = serverSslContext.newHandler(channel.alloc());

        channel.pipeline().addLast(
                // 如果应用既要接收ssl又要接收非ssl, 可以使用OptionalSslHandler,它会自动判断是否是sslmessage的                
                serverSslHandler
                , new StartEndFlagFrameCodec(320, true, wrappedBuffer(new byte[]{(byte) 0x7e}))
                , new EscapeCodec(EscapeMap.mapHex("7e", "7d5e"))
                , new UserCodec()
                , new LoggerHandler(log, INFO));
    }
}

至此我们完成了 客户端 和 服务端 的Ssl配置, 此时应用就具备ssl通信的能力了

  • 54
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值