В наше время использование HTTPS становится обязательным для всех сайтов и веб-приложений. Но в процессе разработки возникает проблема корректного тестирования. Естественно, Let’s Encrypt и другие CA не выдают сертификаты для localhost.

Традиционно есть два решения.

  1. Самоподписанные сертификаты, сгенерированные через openssl или др. Вот самый простой способ сгенерировать приватный ключ и самоподписанный сертификат для localhost:

    openssl req -x509 -out localhost.crt -keyout localhost.key   -newkey rsa:2048 -nodes -sha256   -subj '/CN=localhost' -extensions EXT -config <(    printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

    Но такой сертификат вызовет ошибки доверия в браузерах, потому что в доверенном хранилище отсутствует соответствующий центр сертификации.
  2. Трюк с регистрацией нового домена типа localhost.example.com, который локально ресолвится в 127.0.0.1 (в /etc/hosts), с получением обычного сертификата для данного домена. Но такая махинация сомнительна с точки зрения безопасности — по крайней мере, для публичных сервисов подобный ресолвинг делать крайне не рекомендуется из-за возможной MiTM-атаки со сменой на враждебный IP-адрес. Если ограничиться только локальной машиной, то может это и подходящий вариант, хотя тоже возникают некоторые сомнения. К тому же, такой сертификат могут отозвать. В любом случае, есть вариант проще и безопаснее (см. ниже).

Речь идёт о mkcert — простой утилите для генерации локально-доверенных сертификатов с собственным центром сертификации. Она работает под всеми ОС и не требует какой-то конфигурации.

Версия для Linux


Сначала нужно установить certutil.

sudo apt install libnss3-tools
    -или-
sudo yum install nss-tools
    -или-
sudo pacman -S nss

затем

brew install mkcert

или собрать из исходников:

go get -u github.com/FiloSottile/mkcert
$(go env GOPATH)/bin/mkcert

Версия для macOS


brew install mkcert
brew install nss # if you use Firefox

Версия для Windows


Под Windows можно скачать собранные бинарники либо воспользоваться одним из пакетных менеджеров: Chocolatey или Scoop.

choco install mkcert
    -или-
scoop install mkcert

Наличие локального центра сертификации — самое важное принципиальное отличие mkcert от openssl и самоподписанных сертификатов, потому что при запуске такого CA локально не возникает никаких ошибок доверия.

В принципе, запустить и настроить собственный CA можно и другими средствами, но это требует нетривиальных знаний и навыков. Здесь всё делает само собой, без всяких дополнительных ключей и настроек. Просто устанавливаем программу — и она автоматически создаёт локальный центр сертификации и прописывает его в доверенное хранилище системы и доверенное хранилище Firefox.

$ mkcert -install
Created a new local CA at "/Users/filippo/Library/Application Support/mkcert" 
The local CA is now installed in the system trust store! ?
The local CA is now installed in the Firefox trust store (requires restart)!

Комментарии (29)


  1. saipr
    09.01.2019 10:44
    +4

    Но такой сертификат вызовет ошибки доверия в браузерах, потому что в доверенном хранилище отсутствует соответствующий центр сертификации.

    А что мешает поставить этот сертификат в доверенное хранилище?


    запустить и настроить собственный CA можно и другими средствами, но это требует нетривиальных знаний и навыков.

    Попробуйте воспользоваться этим УЦ.


  1. mwambanatanga
    09.01.2019 11:10

    Зарегистрировать бесплатный домен в .ml, .tk, .ga (этого добра не перечесть) и получить на него бесплатный же сертификат от LE. А дальше всё, как в пункте 2.

    А если компания параноидально следит за безопасностью и на все компьютеры уже установлен «свой» корневой сертификат для прослушки трафика, то достаточно им подписать и далее всё, как в пункте 1.


    1. xPomaHx
      11.01.2019 08:51

      Для удобной разработки все равно придется купить впс с внешним ип.


  1. herrjemand
    09.01.2019 11:43
    +1

    А зачем? Localhost и так считается SecureContext.


  1. tendium
    09.01.2019 13:50

    Есть вот такая утилитка, github.com/cloudflare/cfssl — несколько менее популярная, чем mkcert, но имхо, более удобная и более гибкая.


  1. amarao
    09.01.2019 15:23

    При этом есть риск начать доверять кому угодно, подписанным этим CA. Достаточно, чтобы приватный ключ CA утёк. Это куда более вероятно в dev-среде, чем кажется. Среда dev, а машины-то (разработчиков) вполне себе продакшен.


    1. sigprof
      10.01.2019 18:11

      Можно уничтожать приватный ключ CA сразу после подписывания сертификата сервера; в этом случае сертификат сервера можно будет продолжать использовать до истечения его срока действия, но сформировать другой сертификат сервера будет уже нельзя без создания нового сертификата CA и добавления его в хранилище доверенных сертификатов.


      Теоретически можно реализовать и вариант с возможностью последующего создания сертификатов только для имён из определённого домена, если сгенерировать промежуточный CA с нужными Name Constraints — в этом случае утечка приватного ключа такого промежуточного CA не даст злоумышленнику возможности создать доверенные сертификаты для произвольного домена.


  1. 96467840
    09.01.2019 17:05

    где-то на сайте по asp.net видел инструкцию как сделать валидный серт для локалхоста. к сожалению, сейчас быстро найти не смог

    вот нашел тут metanit.com/sharp/aspnet5/18.6.php


    1. brain_tyrin
      10.01.2019 18:11

      Ну это способ, требующий студии, на самом деле можно просто
      dotnet dev-certs https --trust
      www.hanselman.com/blog/DevelopingLocallyWithASPNETCoreUnderHTTPSSSLAndSelfSignedCerts.aspx
      Говорят, не работает на линуксе, но там и галку в студии поставить не получится :)


  1. kelevra
    09.01.2019 17:59

    Первый тост — за localhost! Админы локалхостов ликуют!


  1. springimport
    09.01.2019 19:22
    +1

    В хроме переиграли в безопасность и решили чтобы .localhost всегда смотрел на 127.0.0.1.
    У меня была ситуация когда потребовалось чтобы site.localhost смотрел на соседний в сети комп, но какого было удивление когда я не смог это сделать через hosts.
    Т.е. сначала мы забираем у разрабов .dev, и оставляем:

    .test
    .example
    .invalid
    .localhost

    А потом внезапно ограничиваем .localhost. И что теперь использовать, myproject.invalid? А разрабов гугла это не парит.


    1. Meklon
      09.01.2019 20:15

      А в чем суть проблемы? Я в локальных использую example.lan, example.local


      1. gecube
        09.01.2019 20:40
        +1

        Завтра заберут и .lan., и .local.
        Не говоря уже о том, что придется поддерживать две структуры доменов (начиная с TLD) для dev- и prod- окружений, что реально может бомбануть


      1. springimport
        10.01.2019 17:21

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


      1. sigprof
        10.01.2019 19:17

        Домен .local на самом деле довольно давно занят — он используется в Multicast DNS (RFC 6762). В Windows из коробки клиент Multicast DNS отсутствует, а вот в Mac OS X и многих дистрибутивах Linux он есть, и в этом случае при попытке использования имён из домена .local для своих собственных целей могут возникать проблемы.


        Домены верхнего уровня .lan, .corp, .home сейчас свободны и теоретически могли бы быть кем-то зарегистрированы, как и .dev, однако вероятность этого довольно мала, поскольку такие имена слишком часто используются в локальных сетях. В феврале 2018 года ICANN отклонила заявки на регистрацию доменов .corp, .home и .mail как раз из-за возможных проблем безопасности по причине конфликтов имён.


        1. Meklon
          10.01.2019 23:05
          +1

          Я в своей сети сейчас использую .lan
          Вообще, мне кажется, что должны быть зарезервированы ключевые домены, как те же приватные диапазоны IP


    1. sigprof
      10.01.2019 18:47

      .invalid для этой цели тоже использовать нельзя — в RFC 6761 написано, что запросы имён из .invalid могут обрабатываться специальным образом и в приложениях, и в библиотеке резолвера (как и .localhost). Так что, если действовать строго по букве RFC, остаётся использовать либо оставшиеся зарезервированные домены .test или .example, либо субдомен в официально зарегистрированном домене (типа .dev.contoso.com; разумеется, показывать такой субдомен всему миру в глобальном DNS совсем не обязательно).


      1. springimport
        10.01.2019 18:51

        Если .example еще кое-как можно принять, то .test для разработки вообще не в кассу. Было 4 несчастных домена из которых по сути остаются вообще 2. Глупая ситуация, как по мне. Для разрабов надо было оставлять .dev и не выпендриваться. Это мое мнение.
        Отдельный домен для каждого проекта не очень, тем более что хочется 2 уровня, а не десяток.


  1. firedragon
    09.01.2019 20:19

    У разработчиков NET и Windows нет такой проблемы. Из коробки можно поднять центр сертификации для домена. Дальше выпускайте сертификаты сколько вашей душе угодно. 2016 server c ролями DC DNS DHCP CA занимает около 900 мб. оперативной памяти.
    Рекомендую.


    1. gecube
      09.01.2019 20:41
      +1

      900мб? Srsly? А чего сразу не 2 или 4 ГиБ?
      Линукс, уверен, с аналогичным функционалом и в 200-500МиБ впишется


    1. bluetooth
      09.01.2019 21:35
      -1

      Зачем поднимать домен? Все решается гораздо легче. Правим руками файл hosts, прописываем какой душе угодно домен на 127.0.0.1 и ставим самоподписанный сертификат. И все.


  1. bluetooth
    09.01.2019 21:34
    -1

    Подправить hosts руками и использовать самоподписанный сертификат на любой домен. И делов то…


    1. 9660
      10.01.2019 05:39

      Подправить hosts руками и использовать самоподписанный сертификат на любой домен. И делов то…

      А бровзер на это говорит что сертификату самоподписанному он не доверяет.


      1. bluetooth
        10.01.2019 15:33

        Сделать доверенный самоподписанный сертификат тоже не такая уж и большая проблема.


        1. 9660
          10.01.2019 15:46

          Расскажите как не включая СА в список доверенных сделать

          доверенный самоподписанный сертификат

          Очень интересно. Без подначки пишу.


  1. artemlight
    10.01.2019 02:48
    +3

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


  1. RuK
    10.01.2019 07:16

    Пока самый полезный пост в новом году (и не менее полезные комменты)


  1. Your_Jesus
    10.01.2019 18:11

    Спасибо


  1. denvist
    10.01.2019 18:11
    +1

    Для «разработки» есть довольно удобные инструменты, так как в этом случае нужен не только https, а как минимум среда исполнения и управления. Для себя нашел весьма удобное решение — typecode/hotel.

    Из коробки:

    • Локальные домены — project.localhost;
    • HTTPS — project.localhost;
    • Поддомены — http://*.project.localhost;
    • Работает на macOS, Linux и Windows, так как это node.js;
    • Поддержка бэкенда — Node, Ruby, PHP, Go, Python ...
    • Автостарт сервисов при обращении к ним;
    • Режим прокси;
    • и прочее...