无法在grpc上完成安全握手?

时间:2017-05-07 07:42:02

标签: go grpc handshake

我已经多次更改了服务器和客户端上的端口号,但服务器总是收到错误的端口号。

当我执行客户端时,服务器将记录此信息: 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)
    }
}

这是针对client.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/

请帮助我,谢谢

1 个答案:

答案 0 :(得分:0)

如果您在journalctl -u docker中找到了此日志:

mai 29 10:33:04 ca275nt dockerd[1523]: time="2019-05-29T10:33:04.454362399-03:00" level=warning msg="grpc: Server.Serve failed to complete security handshake from \"192.168.0.45:58392\": remote error: tls: bad certificate" module=grpc    

这可能与另一个群集集群节点主机发出的docker swarm请求试图使用无效令牌连接到docker swarm主节点有关。

您可以使用以下方法发现无效的群集节点主机名:

nslookup 192.168.0.45                                                                                                                                          
45.0.168.192.in-addr.arpa       name = hostabc.domain.com.
45.0.168.192.in-addr.arpa       name = hostabc.

Authoritative answers can be found from:

通过在报告的主机上运行docker swarm leave,解决此问题。

我知道这与主要问题无关,但是我在搜索: docker "grpc: Server.Serve failed to complete security handshake from",这是第一个问题。那么我认为将疑难解答放在这里很有用,以节省其他时间。