2017-05-07 319 views
1

我已经在服务器和客户端上多次更改过端口号,但服务器总是收到错误的端口号。未能完成grpc的安全握手?

当我执行客户端服务器将记录此: 2017/05/07 15:06:07 grpc: Server.Serve failed to complete security handshake from "127.0.0.1:32763": remote error: tls: bad certificate 并在客户端,我得到这个: 2017/05/07 15:06:07 Failed to dial localhost:8070: connection error: desc = "transport: x509: certificate is not valid for any names, but wanted to match localhost:8070"; please retry. rpc error: code = Internal desc = connection error: desc = "transport: x509: certificate is not valid for any names, but wanted to match localhost:8070"

我有此代码为server.go

func serve() { 
    addr := "localhost:8070" 
    crt, key := certificate.CreatePemKey() 
    certificate, err := tls.X509KeyPair(crt, key) 
    if err != nil { 
     fmt.Println(err) 
    } 

    certPool := x509.NewCertPool() 
    ca, err := ioutil.ReadFile("F:/GIAG3.crt") 
    if err != nil { 
     fmt.Println(err) 
    } 

    if ok := certPool.AppendCertsFromPEM(ca); !ok { 
     fmt.Println("unable to append certificate") 
    } 

    lis, err := net.Listen("tcp", addr) 
    if err != nil { 
     fmt.Println("could not list on %s: %s", addr, err) 
    } 

    // Create the TLS credentials 
    creds := credentials.NewTLS(&tls.Config{ 
     ClientAuth: tls.RequireAndVerifyClientCert, 
     Certificates: []tls.Certificate{certificate}, 
     ClientCAs: certPool, 
    }) 

    srv := grpc.NewServer(grpc.Creds(creds)) 
    pb.RegisterPingerServer(srv, &server{}) 

    if err := srv.Serve(lis); err != nil { 
     fmt.Println("grpc serve error: %s", err) 
    } 
} 

这是为客户端.go

func testDial2() { 
    addr := "localhost:8070" 
    crt, key := certificate.CreatePemKey() 
    certificate, err := tls.X509KeyPair(crt, key) 
    if err != nil { 
     fmt.Println(err) 
    } 

    certPool := x509.NewCertPool() 
    ca, err := ioutil.ReadFile("F:/GIAG3.crt") 
    if err != nil { 
     fmt.Println(err) 
    } 

    if ok := certPool.AppendCertsFromPEM(ca); !ok { 
     fmt.Println("unable to append certificate") 
    } 

    creds := credentials.NewTLS(&tls.Config{ 
     ServerName: addr, 
     Certificates: []tls.Certificate{certificate}, 
     RootCAs:  certPool, 
    }) 

    conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(creds)) 
    if err != nil { 
     fmt.Println(err) 
    } 

    defer conn.Close() 
    c := pb.NewPingerClient(conn) 
    r, err := c.Ping(context.Background(), &pb.Payload{Message: "Ping"}) 
    if err != nil { 
     fmt.Println(err) 
    } 
    log.Printf("%s", r.Message) 
} 

这是为CreatePemKey,它是基于这个例子https://golang.org/src/crypto/tls/generate_cert.go

func publicKey(priv interface{}) interface{} { 
    switch k := priv.(type) { 
    case *rsa.PrivateKey: 
     return &k.PublicKey 
    case *ecdsa.PrivateKey: 
     return &k.PublicKey 
    default: 
     return nil 
    } 
} 

func pemBlockForKey(priv interface{}) *pem.Block { 
    switch k := priv.(type) { 
    case *rsa.PrivateKey: 
     return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} 
    case *ecdsa.PrivateKey: 
     b, err := x509.MarshalECPrivateKey(k) 
     if err != nil { 
      fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err) 
      os.Exit(2) 
     } 
     return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} 
    default: 
     return nil 
    } 
} 

func CreatePemKey() (certpem, keypem []byte) { 
    priv, _ := rsa.GenerateKey(rand.Reader, 2048) 
    notBefore := time.Now() 
    notAfter := notBefore.AddDate(1, 0, 0) 
    serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 
    serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) 

    template := x509.Certificate{ 
     SerialNumber: serialNumber, 
     Subject: pkix.Name{ 
      Organization: []string{"Acme Co"}, 
     }, 
     NotBefore:    notBefore, 
     NotAfter:    notAfter, 
     KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 
     ExtKeyUsage:   []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 
     BasicConstraintsValid: true, 
    } 
    // template.IPAddresses = append(template.IPAddresses, net.ParseIP("localhost")) 
    template.IsCA = true 
    derbytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) 
    certpem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derbytes}) 
    keypem = pem.EncodeToMemory(pemBlockForKey(priv)) 
    return certpem, keypem 
} 

BTW的GIAG3.crt是从这里走过https://pki.goog/

请帮帮我,谢谢

回答

0

如果您的服务器证书不具有域定义并且它没有被GIAG3签名(就像你的例子),你应该在客户端配置中添加InsecureSkipVerify(这样可以跳过验证服务器名称和服务器证书),这将解决无效名称的问题。

creds := credentials.NewTLS(&tls.Config{ 
    ServerName: addr, 
    Certificates: []tls.Certificate{certificate}, 
    RootCAs:  certPool, 
    InsecureSkipVerify: true, 
}) 

但你有另外一个问题,因为客户端使用自签名证书,并要求GIAG3的认证(tls.RequireAndVerifyClientCert)签署的证书服务器,让你有一些这方面的选择,

  • 您使用由GIAG3签署的证书作为客户端。
  • 减少认证类型为tls.RequireAnyClientCert,这允许您在auth(它可能是或不是由GIAG3签名)时使用任何证书,客户端只需在连接时使用任何证书。
  • 删除证书的客户端身份验证。