grpc / grpc-go

The Go language implementation of gRPC. HTTP/2 based RPC
https://grpc.io
Apache License 2.0
20.9k stars 4.34k forks source link

Client could not sent Certificate receiving message "bad certificate" from Server #3471

Closed wusuoweiman closed 4 years ago

wusuoweiman commented 4 years ago

grpc : 1.28.0-dev go version : 1.11.2 system: linux x86_64

summary: I try to use grpc SSL/TLS to to authenticate both the server and client 。Unluckily, it doesn't work well.

I catch the packets (1) client hello seems good image (2) server hello seems good image (3) client sertificate seems wrong, the length is 0. image (4) server return "certificate" image

Reproduce:

  1. key and crt openssl genrsa -out server.key 1024 openssl rsa -in server.key -pubout -out server.pem openssl genrsa -out client.key 1024 openssl rsa -in client.key -pubout -out client.pem

openssl genrsa -out ca.key 1024 openssl req -new -key ca.key -out ca.csr openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

openssl req -new -key server.key -out server.csr openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

openssl req -new -key client.key -out client.csr openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

  1. client use the tool gnxi https://github.com/jipanyang/gnxi/blob/master/gnmi_get/gnmi_get.go https://github.com/jipanyang/gnxi/blob/master/utils/credentials/credentials.go main code: opts := credentials.ClientCredentials(targetName) conn, err := grpc.Dial(targetAddr, opts...) if err != nil { log.Exitf("Dialing to %q failed: %v", *targetAddr, err) }

func ClientCredentials(server string) []grpc.DialOption { opts := []grpc.DialOption{} if notls { opts = append(opts, grpc.WithInsecure()) } else { tlsConfig := &tls.Config{} if insecure { tlsConfig.InsecureSkipVerify = true } else { certificates, certPool := LoadCertificates() tlsConfig.ServerName = server tlsConfig.Certificates = certificates tlsConfig.RootCAs = certPool } opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) }

if authorizedUser.username != "" {
    return append(opts, grpc.WithPerRPCCredentials(&authorizedUser))
}
return opts

}

./gnmi_get -xpath_target xxx -xpath "" -target_addr -alsologtostderr -ca server.crt -cert client.crt -key client.key

  1. server https://github.com/jipanyang/sonic-telemetry-1/blob/master/telemetry/telemetry.go certificate, err = tls.LoadX509KeyPair(serverCert, serverKey) if err != nil { log.Exitf("could not load server key pair: %s", err) } tlsCfg := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, Certificates: []tls.Certificate{certificate}, } ca, err := ioutil.ReadFile(caCert) if err != nil { log.Exitf("could not read CA certificate: %s", err) } certPool := x509.NewCertPool() if ok := certPool.AppendCertsFromPEM(ca); !ok { log.Exit("failed to append CA certificate") } tlsCfg.ClientCAs = certPool opts := []grpc.ServerOption{grpc.Creds(credentials.NewTLS(tlsCfg))} cfg := &gnmi.Config{} cfg.Port = int64(port) s, err := gnmi.NewServer(cfg, opts) if err != nil { log.Errorf("Failed to create gNMI server: %v", err) return } telemetry -logtostderr --port 8080 -v=2 --server_crt server.crt --server_key server.key --ca_crt client.crt
easwars commented 4 years ago

I'm not sure if this is really a gRPC issue. Could you please verify that your cert configuration is valid, by spinning up a regular server process with the server certs, and have the client do a regular net.Dial and then wrap the resulting net.Conn in a tls.Conn, or directly do a tls.Dial and pass in the tls.Config.

stale[bot] commented 4 years ago

This issue is labeled as requiring an update from the reporter, and no update has been received after 7 days. If no update is provided in the next 7 days, this issue will be automatically closed.