Pull to refresh

Comments 11

Спасибо, что не поленились собрать весь этот материал в одной статье! Это действительно многим будет полезно.

Поскольку вы упоминаете ASP.NET, то было бы неплохо для HttpClient также привести пример конфигурирования через DI, т.к. ручное создание HttpClient и HttpClientHandler там не самая лучшая практика.

Благодарю за ваш отзыв.

Мы редко пользуемся HttpClient напрямую, обычно используем Refit. Но есть статья от Microsoft на интересующую вас тему.

Всё это накладывает на разработчиков необходимость знать способы работы с сертификатами.

Знать то, конечно, желательно, но на практике до них далеко не всегда дело доходит.

Например, когда наружу идет какой-нибудь nginx и все сертификаты на нем, а от него до API слоя незащищенный http.

Да и на счет микросервисов, на мой взгляд куда как удобнее, когда вся работа с ними идет через AMQP, а не HTTP/HTTPS, так и горизонтально масштабировать сильно проще: если надо, то запустил новый инстанс сервиса и все.

Вы правы, так и делают в рабочих системах. Но подобный подход не очень хорош для обучения. Он, фактически, говорит разработчикам: "Знаете, вам не нужно беспокоиться обо всех этих сертификатах. Хостинг-провайдеры сделают всё это за вас". Цель у статьи была несколько иная - дать базовую информацию, полезную для новичков. Как я и говорил, профессионалы вряд ли найдут в ней что-то полезное.

Последнее что нужно делать - делегировать SSL/TLS терминирование managed-коду, где будут тонны аллокаций памяти и сопуствующие этому проблемы.

Автор, вы случайно не хостите ASP.NET Core в IIS?

что за проблемы у кора с иис-ом?
правда интересно, если там какие-то грабли - можно детали плз

Да, на production мы тоже используем поддержку сертификатов от провайдера, насколько мне известно. Но на компьютерах разработчиков хостим ASP.NET Core через IIS.

А поднять nginx в режиме реверс прокси - не судьба?

Вероятно, в реальных ситуациях так и делают. Но я не специалист по nginx, так что описывал те технологии, с которыми знаком.

@iakimov

Очень хорошие примеры и целостное изложение основ, спасибо!

Появились вопросы по ходу прочтения. Клиент и сервер тут похоже на одной машине, поэтому хотелось бы понимать какой именно сертификат применен для каждого процесса валидации, а какой не применен. Возможно это очевидно опытным, но у меня остались сомнения.

  1. Процесс проверки сертификата клиента сервером.

Давайте посмотрим, как заставить сервер требовать от клиента сертификат. Для этого придётся лишь немного изменить его код:

В примере, который следует за этим текстом, фигурирует certificate, как я понял это серверный для https со стороны сервера и к валидации клиента отношения не имеет. То есть его можно даже откинуть. Главное тут это присвоение:

connectionOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;

? Но как мы проверяем что клиентский сертификат верный если в коде сервера он не фигурирует? Важно ли устанавливать этот клиентский сертификат на стороне сервера?

2. Процесс проверки сертификата сервера клиентом.

Тут браузер/HttpClient клиента смотрит на серверный сертификат который пришел от сервера. Происходит не явная валидация(которую мы не прописываем руками). Для этой валидации достаточно только сертификата который пришел? или все же важно что серверный сертификат установлена на машине клиента и пришлый сравнивается с установленным? Важно ли загружать серверный сертификат на стороне клиента? Как вы писали, браузеры устанавливают базовые сертификаты при установке.

3. Можно ли описать специфику установки сертификатов если клиент и сервер разнесены по разным машинам? Есть ли тут особенности установки сертификатов в случае? Казалось что на клиент пойдет другого формата сертификат (.pfx, .cer, точно не помню что и как).

4. Как я понял единственная польза создавать самоподписные сертификаты для локальной проверки работы приложения с HTTPS перед тем как отдавать его дальше на деплой (запустилось/упало при любом https запросе). Или продемонстрировать работу HTTPS другим членам команды, для этого наверно и стоит разнести клиент и сервер при установке сертификата. Или есть другие полезные сценарии?

5. Есть примеры использования клиентских сертификатов? Привык только к проверкам серверных браузером, другое в голову не приходит.

К статье больше вопросов нет.

А вообще было бы не плохо и вторую часть написать, так как тут еще есть некоторые пробелы для полного раскрытия темы "Использование сертификатов в ASP.NET Core". Даже после прочтения, я все еще не уверенный пользователь сертификатов. Если у кого хватит сил, то могу набросить пунктов на будущее:

  • Можно ли устанавливать сертификаты на веб сервер типа IIS или nginx, в чем плюсы и минусы такого подхода? Можно ли забить на проверки сертификатов из кода ASP.NET Core или тут есть некий симбиоз между подходами? не будет ли ситуаций когда проверяются разные сертификаты из кода и на уровне веб сервера или что происходит повторная проверка сертификата? Как договариваться Dev и DevOps/админам в этих подходах?

  • Типы сертификатов. Или из кода интересуют только .pfx?

  • Установка сертификатов на разных OS. Зависит ли код от платформы?

  • Сценарии генерации прод сертификатов. Особенности для клиентских сертификатов и их распространение.

  • Если у нашего сервиса много инстансов на разных машинах, то устанавливаем на всех копию одного сертификата?

Спасибо за отзыв!

Вот что я могу сказать по поводу ваших вопросов.

Вопрос 1. Вы правы, на стороне сервера важной является строчка

connectionOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;\

Сам код сервера ничего о клиентском сертификате ничего не знает. Чтобы проверка клиентского сертификата на стороне сервера прошла, необходимо сделать следующее. Либо вы добавляете сам клиентский сертификат в хранилище доверенных сертификатов (Trusted Root Certification Authorities) на сервере. Либо, если ваш клиентский сертификат не является самоподписанным, а подписан другим сертификатом, то в это хранилище на сервере можно поместить тот сертификат, которым вы подписывали клиентский сертификат (или вообще любой сертификат вверх по цепочке подписывания). В этом случае сам клиентский сертификат на сервере не нужен.

Вопрос 2. Собственно, ответ такой же. На стороне клиента должен присутствовать либо сам серверный сертификат, либо один из его цепочки подписывающих сертификатов.

Вопрос 3. Действительно, некоторая специфика есть.

  1. Если вы устанавливаете серверный сертификат на клиента, то вам не нужно иметь в нём закрытый ключ. Поэтому можно выбрать любой формат, который содержит только публичный ключ. По крайней мере, я так полагаю. Но обычно распространяют не сами клиентские или серверные сертификаты, а подписывающие их сертификаты. Это намного удобнее.

  2. Кроме того, когда вы разнесли клиент и сервер по разным машинам, вы уже не можете обращаться с клиента на сервер по имени localhost. Поэтому в генерируемых для этой задачи сертификатах поля subject и DNS Name должны содежать правильные значения (т. е. сетевое имя машины-сервера).

  3. Ну и всё то, что написано выше про установку сертификатов в доверенное хранилище, тоже имеет место.

Вопрос 4. Насколько мне известно, самоподписанные сертификаты действительно используются только для тестирования. Но в принципе это нормальные сертификаты. Если вы решите проблему их установки на нужные машины и своевременного обновления, то можно их использовать. Хотя зачем это нужно, если есть более удобные и надёжные средства, не понятно.

Тут в голову пришло, что такая штука, как Fiddler, использует вроде бы самоподписанный сертификат для перехвата SSL-трафика (т. е. фактически для реализации атаки "человек посередине", описанной в статье). Но это, конечно, экзотический сценарий.

Вопрос 5. Честно говоря, сам я не сталкивался с системами, использующими клиентские сертификаты. Только познакомился с этим в том курсе Pluralsight, о котором говорится в статье. Скорее всего, это какие-то приложения, обладающие повышенными требованиями к безопасности. Ну вот, например, такой вариант. Вы хотите, чтобы ваш клиент работал исключительно на подконтрольных вам устройствах. Вы боитесь, что если клиент станут использовать все, кто хочет, с любой машины, безопасность вашей системы пострадает. Поэтому вы ставите клиентские сертификаты на все компьютеры ваших сотрудников и заставляете систему проверять их. В результате клиент не сможет соединиться с сервером ни с одной машины, на которой нет правильного клиентского сертификата.

Спасибо вам за предложения по расширению статьи. Могу сказать по ним следующее:

Да, с сертификатами можно работать на уровне Web-сервера (IIS, nginx), а не приложения. Обычно так и делают в промышленных системах. В результате проверкой сертификата занимается Web-сервер, а не ваше приложения. Это позволяет сделать код вашего приложения проще, а обработку запросов - быстрее. Кроме того, ответственность за правильную проверку сертификатов переносится на разработчиков Web-сервера, которые, хочется надеяться, обладают соответствующей квалификацией.

Возможным недостатком такого подхода может являться необходимость проверять в приложении некоторые поля сертификата, а затем использовать значения этих полей в коде приложения. Хотя, я уверен, вполне можно настроить Web-сервер так, чтобы он передавал сертификат вашему приложению, а не терминировал SSL на своём уровне. С другой стороны, если вашему приложению всё равно придётся проверять сертификат, зачем это делать на стороне Web-сервера...

Если у вашего сервера много экземпляров, то да, на всех них нужно установить серверный сертификат. Я думаю, что он должен быть один и тот же для всех экземпляров. Не знаю, как поведут себя клиенты, если в ответ на разные запросы к одному и тому же серверу будут приходить разные, хотя и валидные, сертификаты. С другой стороны, происходит же что-то подобное в момент, когда мы заменяем сертификат сервера из-за окончания его срока службы.

Sign up to leave a comment.

Articles