grpc使用ssl(tls) 通过openssl指定多个域名和IP

原文地址: http://www.ltang.me/2018/11/27/grpc-tls-openssl/

最近在使用grpc做项目,信息安全的同事提出要求,需要将来往报文加密,避免抓包。阅读grpc的文档,发现它已经支持ssl(tls),因此直接选这种认证和加密方式。

服务端和客户端代码参考grpc-java项目中的demo,摘取关键代码如下:

服务端

 private SslContextBuilder getSslContextBuilder() {
        InputStream cacert = ZooPorterRpcServer.class.getClassLoader().getResourceAsStream("ssl/server.crt");
        InputStream privkey = ZooPorterRpcServer.class.getClassLoader().getResourceAsStream("ssl/server.pem");
        SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(cacert, privkey);
        return GrpcSslContexts.configure(sslContextBuilder, SslProvider.OPENSSL);
    }
 
    private void start() throws IOException {
        port = settings.getInt("server.port");
        server = NettyServerBuilder.forPort(port).addService(BeanUtil.me().getBean(ElasticsearchServiceGrpcImpl.class))
                .sslContext(getSslContextBuilder().build())
                .build()
                .start();
      
        logger.info("Server started, listening on " + port);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                ZooPorterRpcServer.this.stop();
                logger.error("*** server shut down");
            }
        });
    }

客户端

    protected final ManagedChannel channel;
 
    private static SslContext buildSslContext() throws SSLException {
        SslContextBuilder builder = GrpcSslContexts.forClient();
        builder.trustManager(ZooPorterClient.class.getClassLoader().getResourceAsStream("ssl/ca.crt"));
        return builder.build();
    }
 
    public ZooPorterClient() throws SSLException {
 
        channel = NettyChannelBuilder.forAddress(Settings.HOST, Settings.PORT)
                .negotiationType(NegotiationType.TLS)
                .sslContext(buildSslContext())
                .build();
    }

密钥和证书

上述代码中,ca.cert和server.pem/server.cert是通过openssl生成的密钥和证书,生成的脚本可以直接参考项目中的readme文档。

值得注意的是,按照readme中的脚本,只能生成一个指定了域名的证书(localhost),假使我们想通过多个域名甚至多个IP来访问服务(后端做负载均衡和服务发现),这样生成的证书就不合用了,访问时会抛异常。因此修改了脚本,下面脚本仅做记录使用。

openssl genrsa -passout pass:1111 -des3 -out ca.key 1024
openssl req -passin pass:1111 -new -x509 -days 7300 -key ca.key -out ca.crt -subj "/C=CN/ST=GuangDong/CN=www.ido.com" -extensions SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:www.ido.com,IP:127.0.0.1,IP:180.137.128.151"))
openssl genrsa -passout pass:1111 -des3 -out server.key 1024
openssl req -passin pass:1111 -new -key server.key -out server.csr -subj "/C=CN/ST=GuangDong/CN=www.ido.com" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:www.ido.com,IP:127.0.0.1,IP:180.137.128.151"))
# 以下这句是grpc官方例子中生成crt文件的命令,但发现这种方式无法指定ip和多域名,因此弃用
# openssl x509 -req -passin pass:1111 -days 7300 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt 
openssl ca -passin pass:1111 -days 7300 -in server.csr -keyfile ca.key -cert ca.crt -extensions SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:www.ido.com,IP:127.0.0.1,IP:180.137.128.151"))
openssl rsa -passin pass:1111 -in server.key -out server.key
openssl pkcs8 -topk8 -nocrypt -in server.key -out server.pem

这样生成的证书,经过测试,可以部署在多个IP(这里是127.0.0.1和180.137.128.151)服务器上,正常访问。

其他

然而,这需要先知道有哪些IP即将部署服务啊!!假如以后部署服务的服务器越来越多,难道要重新生成证书并且更新服务和客户端吗?

得考虑下,这个ip能否是*号,或者其他任何方法,使得服务端增加节点,不影响 客户端正常调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值