Назад | Перейти на главную страницу

зачем мне нужен сертификат для установления безопасного соединения gRPC в качестве клиента?

При использовании gRPC поверх обычного TCP клиент устанавливает канал с сервером следующим образом (в 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, говорят о чтении сертификата из локального файла, но ни один из них не говорит, что это за сертификат или откуда он.

Что мне не хватает?

РЕДАКТИРОВАТЬ:

Я обнаружил на своем компьютере каталог с кучей корневых сертификатов ЦС. /etc/ssl/certs/ Один из них, похоже, является органом, проверяющим LetsEncrypt, который я использую на сервере, поэтому я попытался прочитать этот сертификат в клиенте следующим образом:

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

но это привело только к этой ошибке

Не удалось выполнить рукопожатие с фатальной ошибкой SSL_ERROR_SSL: error: 1000007d: SSL-процедуры: OPENSSL_internal: CERTIFICATE_VERIFY_FAILED.

gRPC в первую очередь предназначен для подключения служб путем вызова удаленных процедур, например для микросервисов. В отличие от односторонних доверительных отношений между веб-сервером и несколькими клиентами браузера, обе вовлеченные партнеры должны явно доверять друг другу, чтобы избежать атак «злоумышленник в середине». 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