2017-05-07 328 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簽名)時使用任何證書,客戶端只需在連接時使用任何證書。
  • 刪除證書的客戶端身份驗證。