快速为GRPC服务加入单向证书验证,原来是这么操作的...

2022-05-10 08:26:52 浏览数 (1)

一个上生产的 GRPC 服务肯定是少不了证书验证这个环节的。

为了安全,你可以去购买收费的证书或者免费证书也行,这里演示我们使用 OpenSSL 自生成的证书。

OpenSSL安装

如果你使用的是 Windows 系统,可以在:

http://slproweb.com/products/Win32OpenSSL.html

这个地址里面下载到对应的版本,至于怎么安装。

如果是使用的 Mac 系统一般都自带此服务。

这里建议使用 Centos 来处理,安装命令:

代码语言:javascript复制
yum install openssl openssl-devel -y

下面的内容也是在服务器 Centos7 上面操作的。

生成相关证书

不要问为什么要这样生成证书,一问就是固定搭配[坏笑]。

你只需要按照下面的步骤,一步一步的生成证书就好了。

1、生成私钥

代码语言:javascript复制
openssl genrsa -out ca.key 2048

2、生成 CSR(证书签名请求)

代码语言:javascript复制
openssl req -new -key ca.key -out ca.csr -subj "/CN=go.kun.com"

/CN 我这里随便输入一个域名 go.kun.com 反正需要改 hosts 来模拟被 DNS 解析。

3、生成自签名SSL证书

代码语言:javascript复制
openssl req -new -x509 -days 3650 -out ca.crt -key ca.key -subj "/CN=go.kun.com"

4、签发服务端证书

代码语言:javascript复制
openssl genrsa -out server.key 2048

openssl req -new -key server.key -out server.csr -subj "/CN=go.kun.com" 
-reqexts SAN 
-config <(cat /etc/pki/tls/openssl.cnf <(printf "n[SAN]nsubjectAltName=DNS:*.kun.com,DNS:*.henjinet.com"))

# 注意
openssl x509 -req -days 3650 
-in server.csr -out server.crt 
-CA ca.crt -CAkey ca.key -CAcreateserial 
-extensions SAN 
-extfile <(cat /etc/pki/tls/openssl.cnf <(printf "n[SAN]nsubjectAltName=DNS:*.kun.com,DNS:*.henjinet.com"))

可以通过下面的命令查看 csr 的信息是否有写入成功

代码语言:javascript复制
openssl req -noout -text -in ca.csr

我们需要用的文件分别是:

代码语言:javascript复制
ca.crt  ca.key  server.crt  server.key

我们把这四个文件放到工程下面的 certs 文件夹下面。

让整个服务单向验证

修改 server.go 文件里面的方法,修改如下:

代码语言:javascript复制
func main() {

 // 创建证书
 cred,err := credentials.NewServerTLSFromFile("certs/server.crt","certs/server.key")
 if err != nil {
  log.Fatalln(err)
 }

 // 创建一个GRPC服务
 srv := grpc.NewServer(grpc.Creds(cred))
 // 注册需要挂载的服务
 pbFiles.RegisterStudentServiceServer(srv, services.NewStudentService())
 // 启一个监听服务
 lis,_ := net.Listen("tcp",":8080")
 // 启动 GRPC 服务
 if err := srv.Serve(lis);err != nil{
  log.Fatalln(err)
 }
}

我们只需要使用 credentials 来创建证书配置,然后挂载 GRPC 里面即可。

修改后我们重新启动我们的 server 服务。

客户端如果不修改代码的情况下,请求就会报错了。

现在我们修改下客户端的代码:

代码语言:javascript复制
func main() {
 
 // 创建证书
 cred,err := credentials.NewClientTLSFromFile("certs/server.crt", "go.kun.com")
 if err != nil {
  log.Fatalln(err)
 }
 
 // 创建连接
 client,err := grpc.Dial(":8080",grpc.WithTransportCredentials(cred))
 if err != nil {
  log.Fatalln(err)
 }

 // 定义请求体
 req := &pbFiles.GetStudentRequest{
  SId: 3333,
 }
 // 定义返回体
 rsv := &pbFiles.GetStudentResponse{}

 // 正式请求
 err = client.Invoke(
  context.Background(),
  "/StudentService/GetStudent",
  req,
  rsv)
 if err != nil {
  log.Fatalln(err)
 }
 // 打印输出
 fmt.Println(rsv.Result)
}

这里我们是采用的单向验证,所以客户端挂载的证书也是服务端的证书。

在某些场景下这种单向证书也是有需要的,但是大多数场景下,一般都是双向验证。

因为双向验证的证书生成方式和单向验证的有一定区别,所以我们将在下一篇文章中介绍。

0 人点赞