ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

grpc-tts证书认证

2022-05-15 18:32:09  阅读:231  来源: 互联网

标签:TLS err pem grpc openssl server tts 认证


grpc-tts证书认证

一、前言

前面篇章的gRPC都是明文传输的,容易被篡改数据。本章将介绍如何为gRPC添加安全机制,包括TLS证书认证和Token认证。

二、TLS证书认证

什么是TLS

TLS(Transport Layer Security,安全传输层),TLS是建立在传输层TCP协议之上的协议,服务于应用层,它的前身是SSL(Secure Socket Layer,安全套接字层),它实现了将应用层的报文进行加密后再交由TCP进行传输的功能。

TLS的作用

TLS协议主要解决如下三个网络安全问题。

  • 保密(message privacy),保密通过加密encryption实现,所有信息都加密传输,第三方无法嗅探;
  • 完整性(message integrity),通过MAC校验机制,一旦被篡改,通信双方会立刻发现;
  • 认证(mutual authentication),双方认证,双方都可以配备证书,防止身份被冒充;

官方grpc-eg

源码

三、生成私钥

生成RSA私钥:openssl genrsa -out server.key 2048

生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512

生成ECC私钥:openssl ecparam -genkey -name secp384r1 -out server.key

生成ECC私钥,命令为椭圆曲线密钥参数生成及操作,本文中ECC曲线选择的是secp384r1

四、生成公钥

openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650

openssl req:生成自签名证书,-new指生成证书请求、-sha256指使用sha256加密、-key指定私钥文件、-x509指输出证书、-days 3650为有效期

此后则输入证书拥有者信息

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:XxXx
Locality Name (eg, city) []:XxXx
Organization Name (eg, company) [Internet Widgits Pty Ltd]:XX Co. Ltd
Organizational Unit Name (eg, section) []:Dev
Common Name (e.g. server FQDN or YOUR name) []:go-grpc-example
Email Address []:xxx@xxx.com

执行脚本生成:

openssl.cnf

[req]
distinguished_name = req_distinguished_name
attributes = req_attributes

[req_distinguished_name]

[req_attributes]

[test_ca]
basicConstraints        = critical,CA:TRUE
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer:always
keyUsage                = critical,keyCertSign

[test_server]
basicConstraints        = critical,CA:FALSE
subjectKeyIdentifier    = hash
keyUsage                = critical,digitalSignature,keyEncipherment,keyAgreement
subjectAltName          = @server_alt_names

[server_alt_names]
DNS.1 = *.test.example.com

[test_client]
basicConstraints        = critical,CA:FALSE
subjectKeyIdentifier    = hash
keyUsage                = critical,nonRepudiation,digitalSignature,keyEncipherment
extendedKeyUsage        = critical,clientAuth

create_tls.sh

#!/bin/bash

# Create the server CA certs.
openssl req -x509                                     \
  -newkey rsa:4096                                    \
  -nodes                                              \
  -days 3650                                          \
  -keyout ca_key.pem                                  \
  -out ca_cert.pem                                    \
  -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=test-server_ca/   \
  -config ./openssl.cnf                               \
  -extensions test_ca                                 \
  -sha256

# Create the client CA certs.
openssl req -x509                                     \
  -newkey rsa:4096                                    \
  -nodes                                              \
  -days 3650                                          \
  -keyout client_ca_key.pem                           \
  -out client_ca_cert.pem                             \
  -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=test-client_ca/   \
  -config ./openssl.cnf                               \
  -extensions test_ca                                 \
  -sha256

# Generate a server cert.
openssl genrsa -out server_key.pem 4096
openssl req -new                                    \
  -key server_key.pem                               \
  -days 3650                                        \
  -out server_csr.pem                               \
  -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=test-server1/   \
  -config ./openssl.cnf                             \
  -reqexts test_server
openssl x509 -req           \
  -in server_csr.pem        \
  -CAkey ca_key.pem         \
  -CA ca_cert.pem           \
  -days 3650                \
  -set_serial 1000          \
  -out server_cert.pem      \
  -extfile ./openssl.cnf    \
  -extensions test_server   \
  -sha256
openssl verify -verbose -CAfile ca_cert.pem  server_cert.pem

# Generate a client cert.
openssl genrsa -out client_key.pem 4096
openssl req -new                                    \
  -key client_key.pem                               \
  -days 3650                                        \
  -out client_csr.pem                               \
  -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=test-client1/   \
  -config ./openssl.cnf                             \
  -reqexts test_client
openssl x509 -req           \
  -in client_csr.pem        \
  -CAkey client_ca_key.pem  \
  -CA client_ca_cert.pem    \
  -days 3650                \
  -set_serial 1000          \
  -out client_cert.pem      \
  -extfile ./openssl.cnf    \
  -extensions test_client   \
  -sha256
openssl verify -verbose -CAfile client_ca_cert.pem  client_cert.pem

rm *_csr.pem

五、新建proto文件

主要是定义我们服务的方法以及数据格式,创建simple.proto文件。

1.定义发送消息的信息

message SimpleRequest{
    // 定义发送的参数,采用驼峰命名方式,小写加下划线,如:student_name
    string data = 1;//发送数据
}

2.定义响应信息

message SimpleResponse{
    // 定义接收的参数
    // 参数类型 参数名 标识号(不可重复)
    int32 code = 1;  //状态码
    string value = 2;//接收值
}

3.定义服务方法Route

// 定义我们的服务(可定义多个服务,每个服务可定义多个接口)
service Simple{
    rpc Route (SimpleRequest) returns (SimpleResponse){};
}

4.编译proto文件

syntax = "proto3";// 协议为proto3

//option go_package = "path;name";
//path 表示生成的go文件的存放地址,会自动生成目录的。
//name 表示生成的go文件所属的包名

//  生成pb.go命令:  protoc -I ./ --go_out=plugins=grpc:.\07tlssecurity\proto\  .\07tlssecurity\proto\simple.proto

option go_package = "./;proto";
package proto;

// 定义我们的服务(可定义多个服务,每个服务可定义多个接口)
service Simple{
  rpc Route (SimpleRequest) returns (SimpleResponse){};
}

// 定义发送请求信息
message SimpleRequest{
  // 定义发送的参数,采用驼峰命名方式,小写加下划线,如:student_name
  // 参数类型 参数名 标识号(不可重复)
  string data = 1;
}

// 定义响应信息
message SimpleResponse{
  // 定义接收的参数
  // 参数类型 参数名 标识号(不可重复)
  int32 code = 1;
  string value = 2;
}


编译

// 指令编译方法,进入go-grpc-example项目,运行
go-grpc-example> protoc -I ./ --go_out=plugins=grpc:.\07tlssecurity\proto\  .\07tlssecurity\proto\simple.proto

image-20220508170256776

六、服务端构建TLS证书并认证

1.定义我们的服务

package main

import (
	"context"
	pb "go-grpc-example/07tlssecurity/proto"
	"log"
	"net"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

/*
@author RandySun
@create 2022-05-08-17:03
*/

// SimpleService 定义我们的服务
type SimpleService struct {
}

// Route 实现Route方法
func (s *SimpleService) Route(ctx context.Context, req *pb.SimpleRequest) (*pb.SimpleResponse, error) {
		res := pb.SimpleResponse{
		Code:  200,
		Value: "hello " + req.Data,
	}
	return &res, nil
}

const (
	// Address 监听地址
	Address string = ":8001"
	// NetWork 网络通信协议
	NetWork string = "tcp"
)

func main() {
	// 监听本地端口
	listener, err := net.Listen(NetWork, Address)
	if err != nil {
		log.Fatalf("net.Listen err: %V", err)
	}

	// 从输入证书文件和密钥文件为服务端构造TLS凭证
	creds, err := credentials.NewServerTLSFromFile("../pkg/tls/server_cert.pem", "../pkg/tls/server_key.pem")
	if err != nil {
		log.Fatalf("Failed to generate credentials %v", err)
	}

	// 创建grpc服务实例
	grpcServer := grpc.NewServer(grpc.Creds(creds))

	// 在grpc服务器注册我们的服务
	pb.RegisterSimpleServer(grpcServer, &SimpleService{})
	log.Println(Address, "net.Listing whth TLS and token...")

	//用服务器 Serve() 方法以及我们的端口信息区实现阻塞等待,直到进程被杀死或者 Stop() 被调用
	err = grpcServer.Serve(listener)

	if err != nil {
		log.Fatalf("grpcService.Serve err:%v", err)
	}
	log.Println("grpcService.Serve run success")
}

  • credentials.NewServerTLSFromFile:从输入证书文件和密钥文件为服务端构造TLS凭证
  • grpc.Creds:返回一个ServerOption,用于设置服务器连接的凭证。
go run server.go
2022/03/27 20:14:10 :8001 net.Listing...

image-20220327202923223

七、客户端配置TLS连接

package main

import (
	"context"
	pb "go-grpc-example/07tlssecurity/proto"
	"log"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

/*
@author RandySun
@create 2022-05-08-17:03
*/
// Address 连接地址
const Address string = ":8001"

var grpcClient pb.SimpleClient

func main() {
	//从输入的证书文件中为客户端构造TLS凭证
	creds, err := credentials.NewClientTLSFromFile("../pkg/tls/ca_cert.pem", "x.test.example.com")
	if err != nil {
		log.Fatalf("Failed to create TLS credentials %v", err)
	}

	// 连接服务器
	conn, err := grpc.Dial(Address, grpc.WithTransportCredentials(creds))
	if err != nil {
		log.Fatalf("net.Connect err: %v", err)
	}
	defer conn.Close()

	// 建立gRPC连接
	grpcClient = pb.NewSimpleClient(conn)
	route()
}

// route 调用服务端Route方法
func route() {
	// 创建发送结构体
	req := pb.SimpleRequest{
		Data: "grpc",
	}
	// 调用我们的服务(Route方法)
	// 同时传入了一个 context.Context ,在有需要时可以让我们改变RPC的行为,比如超时/取消一个正在运行的RPC
	res, err := grpcClient.Route(context.Background(), &req)
	if err != nil {
		log.Fatalf("Call Route err: %v", err)
	}
	// 打印返回值
	log.Println(res)
}

运行客户端

go run client.go
2022/03/27 20:20:39 服务的返回响应data: code:200 value:"hello grpc"
  • credentials.NewClientTLSFromFile:从输入的证书文件中为客户端构造TLS凭证。
  • grpc.WithTransportCredentials:配置连接级别的安全凭证(例如,TLS/SSL),返回一个DialOption,用于连接服务器。

到这里,已经完成TLS证书认证了,gRPC传输不再是明文传输。此外,添加自定义的验证方法能使gRPC相对更安全。

成功调用Server端的Route方法并获取返回的数据。

image-20220327202937888

image-20220508172034191

八、总结

本篇介绍如何为gRPC添加TLS证书认证和自定义认证,从而让gRPC更安全。

参考:gRPC官方文档中文版

标签:TLS,err,pem,grpc,openssl,server,tts,认证
来源: https://www.cnblogs.com/randysun/p/16273945.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有