本文记录grpc
相关知识。
记录proto
相关知识。
导入其它.proto
文件
先记录一条命令protoc -I C:\Users\wangjili\go\pkg\mod -I ./ --go_out=./proto --govalidators_out=./protoc --go-grpc_out=./proto ./proto/*.proto
。
-I
表示导入的文件路径,可以有多个路径。--go_out
表示生成xx.pb.go
的路径。--govalidators_out
表示生成xx.validator.pb.go
文件的路径。--go-grpc_out
表示生成xx_grpc.pb.go
文件的路径。
使用go-proto-validators
- 安装:
go get github.com/mwitkow/go-proto-validators
; - 在
.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}]; }
- 编译
- 先安装:
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
。
- 安装:
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
问题
- 在使用
postman
测试gRPC
的http
接口时,报错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.pem
和server.key
就是我们需要的证书和秘钥。
服务端代码:
creds, err := credentials.NewServerTLSFromFile("./keys/server.pem", "./keys/server.key")
客户端代码:
creds, err := credentials.NewClientTLSFromFile("./keys/server.pem", "www.wangjili.cn")
服务之间如何通信
向系统外部暴露采用REST,向系统内部暴露调用采用RPC方式