为什么我需要证书才能作为客户端建立安全的 gRPC 连接?

为什么我需要证书才能作为客户端建立安全的 gRPC 连接?

当通过纯 TCP 使用 gRPC 时,客户端会与服务器建立一个通道,如下所示(在 ruby​​ 中):

stub = Helloworld::Greeter::Stub.new(service_url, :this_channel_is_insecure)

但是,当我在服务器上实现 TLS 并在服务器上输入我的 LetsEncrypt 证书时,客户端必须建立一个这样的安全连接(在 ruby​​ 中):

creds = GRPC::Core::Credentials.new(load_certs)  # load_certs typically loads a CA roots file
stub = Helloworld::Greeter::Stub.new(service_url, creds)

带有注释的代码取自官方 gRPC 文档。

我的问题是,为什么客户端在这里需要证书?我以为是服务器需要证书,客户端确保证书有效。当我的浏览器连接到安全网站时,它会将自己的证书带到表中吗?如果不是,那么为什么 gRPC 客户端需要证书?

从我的阅读来看,客户端知道一些受信任的机构,服务器的证书链链接到其中一个机构。上面代码中的注释指的是“CA 根文件”,它可能是链顶部的机构的证书。因此,也许 gRPC 客户端会将服务器链根部的证书与其自己的证书进行比较 - 但如果是这样,如果它得到了错误的 CA,会发生什么?

所有文档和帖子都解释了如何从 gRPC 客户端建立安全连接,都说要从本地文件读取证书,但没有一个文档和帖子说明该证书是什么,或者它来自哪里。

我错过了什么?

编辑:

我在电脑上发现一个目录,里面有一堆看似 CA 根证书的东西。/etc/ssl/certs/其中一个似乎是验证 LetsEncrypt 的机构,我在服务器上使用它,所以我尝试在客户端读取该证书,如下所示:

GRPC::Core::ChannelCredentials.new(File.read('/etc/ssl/certs/ISRG_Root_X1.pem'))

但它只导致了这个错误

握手失败,出现致命错误 SSL_ERROR_SSL:错误:1000007d:SSL 例程:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED。

答案1

gRPC 主要用于通过调用远程过程来连接服务,例如微服务。与 Web 服务器和多个浏览器客户端之间的单边信任关系相比,两个都涉及的合作伙伴必须明确地相互信任,以避免中间人攻击。gRPC 通过设计强制执行 TLS 安全连接。

如果存在不安全(没有 TLS 安全)连接(仅用于测试目的),则对于 gRPC 服务器,参数:this_port_is_insecure将传递给(GRPC::RpcServer.new).add_http2_port方法,对于每个涉及的 gRPC 客户端,参数channel_args: :this_channel_is_insecure将传递给Core::Stub.new方法。

相反,如果通过 TLS 建立安全连接,则GRPC::Core::ServerCredentials.new client_ca_pem, [{private_key: server_key_pem, cert_chain: server_cert_pem}], true必须传递给 gRPC 服务器 GRPC::Core::ChannelCredentials.new server_ca_pem, client_key_pem, client_cert_pem必须为每个客户端传递。

File.read对于所有 *_pem 变量,通过相应的 PEM 文件加载内容,由您的信任中心提供或可能是之前自行生成的:

  • server_ca_pem 是签署 server_cert_pem 的证书颁发机构
  • server_cert_pem 是服务器证书链,由客户端通过 server_ca_pem 证明
  • server_key_pem 是服务器的私钥
  • client_ca_pem 是已签署 client_cert_pem 的证书颁发机构
  • client_cert_pem 是客户端证书链,由服务器通过 client_ca_pem 证明
  • client_key_pem 是客户端的私钥

server_ca_pem并且client_ca_pem可能相同也可能不同。GRPC::Core::CallCredentials如果您需要在调用级别保护服务-客户端关系,请使用附加项。

gRPC 身份验证指南:

https://grpc.io/docs/guides/auth/

Ruby 代码示例:

https://github.com/grpc/grpc/blob/master/src/ruby/spec/channel_credentials_spec.rb

相关内容