5 minutes reading time
从本篇开始,我将介绍加强 gRPC 的安全性的一系列措施。本篇介绍使用 TLS 加密 gRPC 通信的第一篇文章: gRPC 单向安全连接。
传输层安全性协议(英语:Transport Layer Security,缩写作TLS),及其前身安全套接层(Secure Sockets Layer,缩写作SSL)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。网景公司(Netscape)在1994年推出首版网页浏览器,网景导航者时,推出HTTPS协议,以SSL进行加密,这是SSL的起源。IETF将SSL进行标准化,1999年公布第一版TLS标准文件。随后又公布RFC 5246 (2008年8月)与RFC 6176(2011年3月)。在浏览器、邮箱、即时通信、VoIP、网络传真等应用程序中,广泛支持这个协议。主要的网站,如Google、Facebook等也以这个协议来创建安全连线,发送数据。目前已成为互联网上保密通信的工业标准。
SSL包含记录层(Record Layer)和传输层,记录层协议确定传输层数据的封装格式。传输层安全协议使用X.509认证,之后利用非对称加密演算来对通信方做身份认证,之后交换对称密钥作为会谈密钥(Session key)。这个会谈密钥是用来将通信两方交换的数据做加密,保证两个应用间通信的保密性和可靠性,使客户与服务器应用之间的通信不被攻击者窃听。
通过安全的连接进行传输数据非常重要,那么如何在 gRPC 中使用 TLS 保护 gRPC 通信呢? TLS 认证机制集成在了 gRPC 库中,这使得 gRPC 可以很方便使用 TLS 进行安全连接。
客户端和服务端之间的安全传输可以采用单向或双向的方式来实现。本文主要介绍 单向安全连接
。
在单向安全连接中,只有客户端会校验服务端,以确保它所接收的数据来自预期的服务器,在建立连接时,服务端会与客户端共享其公开证书,客户端会校验收到的证书。这是通过证书授权中心完成的。 证书校验完成后,客户端会使用密钥加密数据。
要启用 TLS ,需要证书和密钥(xx.key,xx.pem/xx.crt),前者是用于签名和扔着公钥,后者用于分发自签名 X.509 公钥。证书和密钥的生成这里就不过多介绍了,需要的可以自行了解。
在 gRPC 服务端启用单向安全连接的主要流程如下:
1 读取和解析公钥-私钥,创建启用 TLS 的证书 2 添加证书作为 TLS 服务凭证,为所有连接启用 TLS. 3 通过 TLS 凭证创建新的 gRPC 连接 接下来的流程跟普通的流程差不多,就不多介绍了,直接上代码:
package main
import (
"context"
"crypto/tls"
"errors"
wrapper "github.com/golang/protobuf/ptypes/wrappers"
"github.com/google/uuid"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
pb "grpc-demo/proto"
"log"
"net"
)
const (
port = ":50051"
crtFile = "./server.crt"
keyFile = "./server.key"
)
type server struct
func (ctx context.Context, in *pb.Product) (*wrapper.StringValue, error)
func (ctx context.Context, in *wrapper.StringValue) (*pb.Product, error)
func main()
为了与服务器连接,客户都需要服务端的自认证公钥。具体流程如下:
1 读取解析公开证书并启用 TLS 证书 2 以 DialOption 的形式添加传输凭证 3 通过 dial option 建立连接
具体代码如下:
package main
import (
"context"
"google.golang.org/grpc/credentials"
pb "grpc-demo/proto"
"log"
"time"
wrapper "github.com/golang/protobuf/ptypes/wrappers"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
hostname = "localhost"
crtFile = "./server.crt"
)
func main()
与原有未使用 TLS 相比,只需修改一些代码即可。
本篇文章介绍了在 gRPC 中启用 TLS 的第一篇文章-单向安全连接。主要介绍了如何在原有代码上进行修改和一些流程。