Ssl

為什麼我需要證書才能作為客戶端建立安全的 gRPC 連接?

  • December 24, 2019

當在普通 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: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED。

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必須為每個客戶端傳遞。

對於所有 *_pem 變數,通過File.read從您的信任中心提供的相應 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

引用自:https://serverfault.com/questions/968343