Wangjili
文章58
标签12
分类9
grpc

grpc

本文记录grpc相关知识。

记录proto相关知识。

导入其它.proto文件

先记录一条命令protoc -I C:\Users\wangjili\go\pkg\mod -I ./ --go_out=./proto --govalidators_out=./protoc --go-grpc_out=./proto ./proto/*.proto

  1. -I表示导入的文件路径,可以有多个路径。
  2. --go_out表示生成xx.pb.go的路径。
  3. --govalidators_out表示生成xx.validator.pb.go文件的路径。
  4. --go-grpc_out表示生成xx_grpc.pb.go文件的路径。

使用go-proto-validators

  1. 安装:go get github.com/mwitkow/go-proto-validators;
  2. .proto文件中使用:
    import "github.com/mwitkow/go-proto-validators/validator.proto";
    message InnerMessage {
        // some_integer can only be in range (1, 100).
        int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
        // some_float can only be in range (0;1).
        double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
    }
  3. 编译
    • 先安装:go install github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
    • 编译:protoc --validators_out=./proto ./proto/*.proto,此时会报错,解决方法如下:
      https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/descriptor.proto下载protobuf文件夹,然后在项目根目录创建google文件夹,将protobuf文件夹复制到此文件中。

使用github.com/grpc-ecosystem/grpc-gateway

先记录一条命令:protoc -I C:\Users\wangjili\go\pkg\mod -I ./ --go_out=./proto --govalidators_out=./proto --go-grpc_out=./proto --grpc-gateway_out ./ ./proto/*.proto

  1. 安装:
    go get -u github.com/grpc-ecosystem/grpc-gateway
    go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway

生成秘钥

openssl genrsa -out server.key 2048
openssl ecparam -genkey -name secp384r1 -out server.key
openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650 

问题

  1. 在使用postman测试gRPChttp接口时,报错SSL Error: Unable to verify the first certificate,解决方法如下:
    解决方法。在File - Settings -> SSL certification verification 关闭。这个问题困扰了我一天。

记录gRPC加密之SSL/TLS原理

问题记录

golang 1.15+ 版本上,用gRPC通过TLS实现数据传输加密时,会报错证书的问题

rpc error: code = Unavailable desc = connection error: desc = “transport: authentication handshake failed: x509: certificate is not valid for any names, but wanted to match localhost”

造成的原因时因为我们用的证书,并没有开启SAN扩展(默认是没有开启SAN扩展)所造成的,导致客户端和服务端无法建立连接。

开始解决问题

使用开启扩展SAN的证书。
什么是SAN
SAN(Subject Alternative Name)是SSL标准x509中定义的一个扩展。使用了SAN字段的SSL证书,可以扩展此证书支持的域名,使得一个证书可以支持多个不同域名的解析。
生成CA根证书
新建 ca.conf,路径/conf/ca.conf,写入如下内容,每个字段根据个人信息填写。

[ req ]
default_bits       = 4096
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = XinJiang
localityName                = Locality Name (eg, city)
localityName_default        = Urumqi
organizationName            = Organization Name (eg, company)
organizationName_default    = Sheld
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = Ted CA Test

生成ca秘钥,得到ca.key,下面所有的命令均在项目根目录下执行,根据自己的习惯选择生成目录。

openssl genrsa -out ./conf/ca.key 4096

生成ca证书签发请求,得到ca.csr

openssl req -new -sha256 -out ./conf/ca.csr -key ./conf/ca.key --config ./conf/ca.conf

shell交互时一路回车就行,生成ca根证书,得到ca.crt

openssl x509 -req -days 3650 -in ./conf/ca.csr -signkey ./conf/ca.key -out ./conf/ca.crt

生成终端用户证书

准备配置文件,得到server.conf,我是放在/keys/server.conf, 写入如下内容

[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = XinJiang
localityName                = Locality Name (eg, city)
localityName_default        = Urumqi
organizationName            = Organization Name (eg, company)
organizationName_default    = Sheld
commonName                  = wangjili
commonName_max              = 64
commonName_default          = wangjili

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = www.wangjili.cn  # # 此处尤为重要,需要用该服务名字填写到客户端的代码中
IP      = 127.0.0.1

生成秘钥,得到server,key

openssl genrsa -out ./keys/server.key 2048

生成证书签发请求,得到server.csr

openssl req -new -sha256 -out ./keys/server.csr -key ./keys/server.key -config ./keys/server.conf

shell交互时一路回车就行,用CA证书生成终端用户证书,得到server.pem

openssl x509 -req -days 3650 -CA ./conf/ca.crt -CAkey ./conf/ca.key -CAcreateserial -in ./keys/server.csr -out ./keys/server.pem -extensions req_ext -extfile ./keys/server.conf

现在证书已经生成完毕,server.pemserver.key就是我们需要的证书和秘钥。
服务端代码:

creds, err := credentials.NewServerTLSFromFile("./keys/server.pem", "./keys/server.key")

客户端代码:

creds, err := credentials.NewClientTLSFromFile("./keys/server.pem", "www.wangjili.cn")

服务之间如何通信

向系统外部暴露采用REST,向系统内部暴露调用采用RPC方式

本文作者:Wangjili
本文链接:https://blog.wangjili.cn/2023/06/05/grpc/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可