分享
  1. 首页
  2. 文章

Go 1.15 以上版本的 GRPC 通信,使用自签CA、Server、Client证书和双向认证

custer · · 1434 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

第1步:生成 CA 根证书

👍 openssl genrsa -out ca.key 2048

Generating RSA private key, 2048 bit long modulus (2 primes)
.............+++++
..................................................................................................................+++++
e is 65537 (0x010001)

👍 openssl req -new -x509 -days 3650 -key ca.key -out ca.pem

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:shanghai
Locality Name (eg, city) []:shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:custer
Organizational Unit Name (eg, section) []:custer
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

第2步:用 openssl 生成 ca 和双方 SAN 证书。

准备默认 OpenSSL 配置文件于当前目录

linux系统在 : /etc/pki/tls/openssl.cnf

Mac系统在: /System/Library/OpenSSL/openssl.cnf

1:cp 目录到项目目录进行修改设置

cp /System/Library/OpenSSL/openssl.cnf /learn-gin/06.gin-grpc/keys

2:找到 [ CA_default ],打开 copy_extensions = copy

3:找到[ req ],打开 req_extensions = v3_req # The extensions to add to a certificate request

4:找到[ v3_req ],添加 subjectAltName = @alt_names

5:添加新的标签 [ alt_names ] , 和标签字段

[ alt_names ]
DNS.1 = localhost
DNS.2 = *.custer.fun

这里填入需要加入到 Subject Alternative Names 段落中的域名名称,可以写入多个。

第3步:生成服务端证书

👍 openssl genpkey -algorithm RSA -out server.key

........................................................................................+++++
.......................................+++++

👍 openssl req -new -nodes -key server.key -out server.csr -days 3650 -subj "/C=cn/OU=custer/O=custer/CN=localhost" -config ./openssl.cnf -extensions v3_req

Ignoring -days; not generating a certificate

👍 openssl x509 -req -days 3650 -in server.csr -out server.pem -CA ca.pem -CAkey ca.key -CAcreateserial -extfile ./openssl.cnf -extensions v3_req

Signature ok
subject=C = cn, OU = custer, O = custer, CN = localhost
Getting CA Private Key

server.csr是上面生成的证书请求文件。ca.pem/ca.key是CA证书文件和key,用来对server.csr进行签名认证。这两个文件在之前生成的。

第4步:生成客户端证书

👍 openssl genpkey -algorithm RSA -out client.key

........+++++
...........+++++

👍 openssl req -new -nodes -key client.key -out client.csr -days 3650 -subj "/C=cn/OU=custer/O=custer/CN=localhost" -config ./openssl.cnf -extensions v3_req

Ignoring -days; not generating a certificate

👍 openssl x509 -req -days 3650 -in client.csr -out client.pem -CA ca.pem -CAkey ca.key -CAcreateserial -extfile ./openssl.cnf -extensions v3_req

Signature ok
subject=C = cn, OU = custer, O = custer, CN = localhost
Getting CA Private Key

现在 Go 1.15 以上版本的 GRPC 通信,这样就完成了使用自签CA、Server、Client证书和双向认证

服务端代码

func main() {
 cert, _ := tls.LoadX509KeyPair("cert/server.pem", "cert/server.key")
 certPool := x509.NewCertPool()
 ca, _ := ioutil.ReadFile("cert/ca.pem")
 certPool.AppendCertsFromPEM(ca)
 creds := credentials.NewTLS(&tls.Config{
 Certificates: []tls.Certificate{cert},
 ClientAuth: tls.RequireAndVerifyClientCert,
 ClientCAs: certPool,
 })
 rpcServer := grpc.NewServer(grpc.Creds(creds))
 services.RegisterProdServiceServer(rpcServer, new(services.ProdService))
 listen, _ := net.Listen("tcp", ":8081")
 rpcServer.Serve(listen)
}

客户端代码

func main() {
 cert, _ := tls.LoadX509KeyPair("cert/client.pem", "cert/client.key")
 certPool := x509.NewCertPool()
 ca, _ := ioutil.ReadFile("cert/ca.pem")
 certPool.AppendCertsFromPEM(ca)
 creds := credentials.NewTLS(&tls.Config{
 Certificates: []tls.Certificate{cert},
 ServerName: "localhost",
 RootCAs: certPool,
 })
 conn, err := grpc.Dial(":8081", grpc.WithTransportCredentials(creds))
 if err != nil {
 log.Fatal(err)
 }
 defer conn.Close()
 prodClient := services.NewProdServiceClient(conn)
 prodRes, err := prodClient.GetProdStock(context.Background(), &services.ProdRequest{ProdId: 12})
 if err != nil {
 log.Fatal(err)
 }
 log.Info(prodRes.ProdStock)
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1434 次点击 ∙ 1 赞
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏