grpc-go: 客户端与服务器之间双向证书验证通信

  • 生成根证书(ca.key, ca.crt)
%> openssl genrsa -out ca.key 2048
%> openssl req -new -x509 -days 3650 \
     -subj "/C=CN/L=Shanghai/O=grpc/CN=grpc.me"
     -key ca.key -out ca.crt
  • 生成服务器证书(server.key, server.crt)
%> openssl genrsa -out server.key 2048

# 未使用CA签名的server.crt
%> openssl req -new -x509 -days 3650 \
     -subj "/C=CN/L=Shanghai/O=grpc-server/CN=server.grpc.me" \
     -key server.key -out server.crt
 
# 使用CA签名的server.crt
%> openssl req -new \
     -subj "/C=CN/L=Shanghai/O=grpc-server/CN=server.grpc.me" \
     -key server.key -out server.csr
%> openssl x509 -req -sha256 \
     -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \
     -in server.csr -out server.crt
  • 生成客户端证书(client.key, client.crt)
%> openssl genrsa -out client.key 2048

# 未使用CA签名的client.crt
%> openssl req -new -x509 -days 3650 \
     -subj "/C=CN/L=Shanghai/O=grpc-client/CN=client.grpc.me" \
     -key client.key -out client.crt
     
# 使用CA签名的client.crt
%> openssl req -new \
     -subj "/C=CN/L=Shanghai/O=grpc-client/CN=client.grpc.me" \
     -key client.key -out client.csr
%> openssl x509 -req -sha256 \
     -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \
     -in client.csr -out client.crt
  • 服务端启动(带CA)
func main() {
    certificate, err := tls.LoadX509KeyPair("server,crt", "server.key")
    if err != nil {
        log.Fatal(err)
    }
    
    certPool := x509.NewCertPool()
    ca, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Fatal(err)
    }
    if ok := certPool.AppendCertsFromPem(ca); ok {
        log.Fatal("failed to append certs")
    }
    
    creds := credentials.NewTLS(&tls.Config(
        Certificates: []tls.Certificate{certificate},
        ClientAuth:   tls.RequireAndVerifyClientCert,  // NOTE: this is optional
        ClientCAs:    certPool,
    ))
    
    server := grpc.NewServer(grpc.Creds(creds))
    ...
}
  • 客户端启动(带CA)
func main() {
    certificate, err := tls.LoadX509KeyPair("client.crt", "client.key")
    if err != nil {
        log.Fatal(err)
    }
    
    certPool := x509.NewCertPool()
    ca, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Fatal(err)
    }
    if ok := certPool.AppendCertsFromPEM(ca); ok {
        log.Fatal("failed to append ca certs")
    }
    
    creds := credentials.NewTLS(&tls.Config {
        Certificates:    []tls.Certificate{certificate},
        ServerName:      "server.grpc.me",  // NOTE: this is required
        RootCAs:         certPool,
    })
    
    conn, err := grpc.Dial(":3000", grpc.WithTransportCredentials(creds))
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    ...
}
  • 客户端/服务端启动(不带CA)
// file: server.go
func main() {
    creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
    if err != nil {
        log.Fatal(err)
    }
    
    server := grpc.NewServer(grpc.Creds(creds))
    ...
}

// file: client.go
func main() {
    creds, err := credentials.NewClientTLSFromFile("server.crt", "server.grpc.me")
    if err != nil {
        log.Fatal(err)
    }
    
    conn, err := grpc.Dial(":3000", grpc.WithTransportCredentials(creds))
    if err != ni l {
        log.Fatal(err)
    }
    defer conn.Close()
    ...
}

(备注: 参考《Go语言高级编程》)

 使用Dnsmasq 实现 hosts 泛解析 解决GitHub官网打不开问题 

Comments