Skip to content

Commit 9f976bd

Browse files
author
Tom
authored
Merge pull request #774 from goodhousekeeper/russian/advanced-information
Russian documentation / Advanced Subscriber information
2 parents 776cfae + d5e57ab commit 9f976bd

6 files changed

Lines changed: 250 additions & 9 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ Gemfile.lock
66
public/
77
nohup.out
88
/node_modules
9+
.idea
Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,62 @@
11
---
2+
title: Сертификаты для localhost
23
slug: certificates-for-localhost
3-
untranslated: 1
4+
top_graphic: 1
5+
date: 2017-12-21
6+
lastmod: 2017-12-21
47
---
8+
9+
{{< lastmod >}}
10+
11+
Иногда разработчикам нужен сертификат для доменного имени "localhost" - для локальной разработки, или для распространения внутри нативных приложений для взаимодействия с web-приложением. Let's Encrypt не предоставляет сертификатов для "localhost", т.к. во-первых, у этого доменного имени нет определённого владельца, и во-вторых, нет домена первого уровня - например, ".com" или ".net". Теоретически, возможно настроить доменное имя так, чтобы оно резолвилось на адрес `127.0.0.1`, и выпустить для него сертификат после прохождения проверки DNS. Тем не менее, есть более удачные решения.
12+
13+
# Для локальной разработки
14+
15+
При разработке web-приложения обычно запускают локальный web-сервер (Apache, Nginx), настроенный на `http://localhost:8000/`. Однако, браузеры по-разному обрабатывают HTTP- и HTTPS-запросы. На HTTPS-странице попытка загрузить Javascript по HTTP-протоколу будет заблокирована. Поэтому, при локальной разработке, используя HTTP, скрипты будут загружаться нормально, но после выкладки на боевые HTTPS-сервера возникнут проблемы. Чтобы избежать такой ситуации, нужно настроить доступ по HTTPS на локальном web-сервере. Но как избавиться от постоянных сообщений об ошибке сертификата, как увидеть "зелёный зам**о**к" в адресной строке?
16+
17+
Лучшим решением будет создание собственного сертификата - самоподписанного, или подписанного локальным корневым сертификатом - и добавление в доверенное хранилище операционной системы. Подробности см.ниже.
18+
19+
# Для нативных приложений, взаимодействующих с web-приложениями
20+
21+
Время от времени, разработчики вынуждены выпускать загружаемые нативные приложения, для расширения функциональности и совместного использования с web-приложениями. Например, десктоп-приложения Dropbox и Spotify умеют сканировать файлы на дисках компьютера, что невозможно для web-приложений. Общий подход в реализации таких нативных приложений состоит в запуске локального web-сервера, и обмену данными с web-приложением через XMLHTTPRequest (XHR) или WebSockets. Web-приложения, как правило, используют HTTPS, поэтому XHR- или WebSockets-запросы по небезопасному протоколу HTTP будут отклонены. Это называется "блокировка смешаного контента" (Mixed Content Blocking). Для взаимодействия с web-приложением, нативное приложение должно быть безопасным.
22+
23+
С одной стороны, современные браузеры [считают][mcb-localhost] `http://127.0.0.1:8000/` ["потенциально заслуживающим доверие"][secure-contexts] URL-ом, потому что он локальный. Отправленный на `127.0.0.1` трафик гарантированно не уйдёт за пределы компьютера, соответственно, считается безопасным для перехвата по сети. Это означает, что если web-приложение использует HTTPS, а нативное приложение запущено на `127.0.0.1`, то обе программы могут успешно взаимодействовать по XHR.
24+
С другой стороны, [для localhost это ещё не работает][let-localhost]. А WebSocket-ы игнорируют и `127.0.0.1`, и `localhost`.
25+
26+
Возможно, вы захотите обойти эти ограничения, настроив резолв произвольного доменного имени в глобальном DNS на адрес `127.0.0.1` (например, `localhost.example.com`), выпустив сертификат для этого домена, распространяя сертификат и соответствующий ему закрытый ключ внутри нативного приложения, и настроив взаимодействие по `https://localhost.example.com:8000/` вместо `http://127.0.0.1:8000/`. *Не делайте этого!* Это подвергнет пользователей риску, и сертификат может быть отозван.
27+
28+
Используя доменное имя вместо IP-адреса, вы позволяете злоумышленникам запустить атаку Man in the Middle (MitM) в процессе поиска IP-адреса по доменному имени (DNS Lookup), и внедрить ответ, который укажет на другой IP-адрес. Атакующий может притвориться нативным приложением, подделывая запросы к web-приложению, что скомпрометирует аккаунт в web-приложении.
29+
30+
Успех атаки MitM возможен потому, что вы вынуждены распространять закрытый ключ для сертификата вместе с нативным приложением. Соответственно, любой, кто скачает это приложение, получит копию ключа. Этим вы скомпрометируете закрытый ключ, и Удостоверяющий Центр (УЦ) отзовёт сертификат, как только узнает об этом. У [множества нативных приложений][mdsp1] были отозваны [сертификаты][mdsp2] по причине [распространения закрытых ключей][mdsp3].
31+
32+
К сожалению, это сужает список безопасных способов взаимодействия нативных и web-приложений. И ситуация может ещё больше усложниться в недалёком будущем, если браузеры продолжат [затруднять доступ к localhost][tighten-access].
33+
34+
Так же нужно отметить, что web-сервисы с доступом к нативному API изначально небезопасны, потому что сайты, которые вы не намеревались авторизовать, могут получить доступ к этому API. Если решите углубиться в изучение проблемы, обратите внимание на [Cross-Origin
35+
Resource Sharing][cors], использование заголовка ответа Access-Control-Allow-Origin, и надёжного HTTP-парсера. Потому как даже серверы, не прошедшие подтверждение, могут посылать предварительные запросы, эксплуатирующие уязвимости в HTTP-парсере.
36+
37+
# Создание и поверка собственных сертификатов
38+
39+
Любой может выпустить собственный сертификат без обращения к УЦ. Единственное различие будет в том, что выпущенные вами сертификаты не будут приниматься кем-либо ещё. Для локальной разработки этого достаточно.
40+
41+
Простейший способ сгенерировать закрытый ключ и самоподписанный сертификат для localhost - выполнить следующую команду из пакета openssl:
42+
43+
openssl req -x509 -out localhost.crt -keyout localhost.key \
44+
-newkey rsa:2048 -nodes -sha256 \
45+
-subj '/CN=localhost' -extensions EXT -config <( \
46+
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
47+
48+
Вы можете сконфигурировать локальный web-сервер, используя файлы localhost.crt и localhost.key, добавив localhost.crt в список доверенных корневых сертификатов.
49+
50+
Если вам требуется чуть больше реализма в сертификатах для локальной разработки, попробуйте [minica][minica] для создания собственного корневого сертификата, и выпуска конечных сертификатов, подписанных корневым. В итоге вы будете импортировать корневой сертификат вместо самоподписанных конечных сертификатов.
51+
52+
Также, вы можете использовать доменное имя с точками внутри (например, `www.localhost`), добавив в файл /etc/hosts как алиас адреса `127.0.0.1`. Этот подход чуть изменит способ обработки браузерами хранилища для cookie.
53+
54+
[mcb-localhost]: https://bugs.chromium.org/p/chromium/issues/detail?id=607878
55+
[secure-contexts]: https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy
56+
[let-localhost]: https://tools.ietf.org/html/draft-ietf-dnsop-let-localhost-be-localhost-02
57+
[mdsp1]: https://groups.google.com/d/msg/mozilla.dev.security.policy/eV89JXcsBC0/wsj5zpbbAQAJ
58+
[mdsp2]: https://groups.google.com/d/msg/mozilla.dev.security.policy/T6emeoE-lCU/-k-A2dEdAQAJ
59+
[mdsp3]: https://groups.google.com/d/msg/mozilla.dev.security.policy/pk039T_wPrI/tGnFDFTnCQAJ
60+
[tighten-access]: https://bugs.chromium.org/p/chromium/issues/detail?id=378566
61+
[minica]: https://github.com/jsha/minica
62+
[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

0 commit comments

Comments
 (0)