本文记录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方式
