Начиная с Chrome 58, он больше не принимает самозаверяющие сертификаты, которые полагаются на Common Name
: https://productforums.google.com/forum/#!topic/chrome/zVo3M8CgKzQ;context-place=topicsearchin/chrome/category$ 3ACanary% 7Csort: актуальность% 7Cspell: false
Вместо этого требуется использовать Subject Alt Name
. Ранее я следовал этому руководству по созданию самозаверяющего сертификата: https://devcenter.heroku.com/articles/ssl-certificate-self который отлично работал, потому что мне требовался server.crt
и server.key
файлы для того, что я делаю. Теперь мне нужно создать новые сертификаты, включающие SAN
однако все мои попытки сделать это не сработали с Chrome 58.
Вот что я сделал:
Я выполнил шаги из вышеупомянутой статьи Heroku, чтобы сгенерировать ключ. Затем я написал новый файл конфигурации OpenSSL:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = san
extensions = san
[ req_distinguished_name ]
countryName = US
stateOrProvinceName = Massachusetts
localityName = Boston
organizationName = MyCompany
[ san ]
subjectAltName = DNS:dev.mycompany.com
Затем сгенерировал server.crt
с помощью следующей команды:
openssl req \
-new \
-key server.key \
-out server.csr \
-config config.cnf \
-sha256 \
-days 3650
У меня Mac, поэтому я открыл server.crt
файл с Keychain, добавил его в мои системные сертификаты. Затем я установил его на Always Trust
.
За исключением файла конфигурации для установки значения SAN, это были те же шаги, которые я использовал в предыдущих версиях Chrome для создания самозаверяющего сертификата и доверия к нему.
Однако после этого я все еще получаю ERR_CERT_COMMON_NAME_INVALID
в Chrome 58.
Мое решение:
openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.key \
-new \
-out server.crt \
-subj /CN=dev.mycompany.com \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
<(printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')) \
-sha256 \
-days 3650
Статус: работает у меня
В Windows сохраните этот сценарий в папке SSL как makeCERT.bat. Он создаст эти файлы: example.cnf, example.crt, example.key
@echo off
REM IN YOUR SSL FOLDER, SAVE THIS FILE AS: makeCERT.bat
REM AT COMMAND LINE IN YOUR SSL FOLDER, RUN: makecert
REM IT WILL CREATE THESE FILES: example.cnf, example.crt, example.key
REM IMPORT THE .crt FILE INTO CHROME Trusted Root Certification Authorities
REM REMEMBER TO RESTART APACHE OR NGINX AFTER YOU CONFIGURE FOR THESE FILES
REM PLEASE UPDATE THE FOLLOWING VARIABLES FOR YOUR NEEDS.
SET HOSTNAME=example
SET DOT=com
SET COUNTRY=US
SET STATE=KS
SET CITY=Olathe
SET ORGANIZATION=IT
SET ORGANIZATION_UNIT=IT Department
SET EMAIL=webmaster@%HOSTNAME%.%DOT%
(
echo [req]
echo default_bits = 2048
echo prompt = no
echo default_md = sha256
echo x509_extensions = v3_req
echo distinguished_name = dn
echo:
echo [dn]
echo C = %COUNTRY%
echo ST = %STATE%
echo L = %CITY%
echo O = %ORGANIZATION%
echo OU = %ORGANIZATION_UNIT%
echo emailAddress = %EMAIL%
echo CN = %HOSTNAME%.%DOT%
echo:
echo [v3_req]
echo subjectAltName = @alt_names
echo:
echo [alt_names]
echo DNS.1 = *.%HOSTNAME%.%DOT%
echo DNS.2 = %HOSTNAME%.%DOT%
)>%HOSTNAME%.cnf
openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout %HOSTNAME%.key -days 3560 -out %HOSTNAME%.crt -config %HOSTNAME%.cnf
Вот решение, которое мне подходит:
Создать ключ CA и сертификат
# openssl genrsa -out server_rootCA.key 2048
# openssl req -x509 -new -nodes -key server_rootCA.key -sha256 -days 3650 -out server_rootCA.pem
Создайте server_rootCA.csr.cnf
# server_rootCA.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=DE
ST=Berlin
L=NeuKoelln
O=Weisestrasse
OU=local_RootCA
emailAddress=ikke@server.berlin
CN = server.berlin
Создайте файл конфигурации v3.ext
# v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = server.berlin
Создать ключ сервера
# openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server_rootCA.csr.cnf )
Создать сертификат сервера
# openssl x509 -req -in server.csr -CA server_rootCA.pem -CAkey server_rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile v3.ext
Добавить сертификат и ключ в файл сайта Apache2, раздел HTTPS (порт 443)
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
Скопируйте server_rootCA.pem с сервера на свой компьютер ..
# scp you@server.berlin:~/server_rootCA.pem .
.. и добавьте его в браузер Chromium
Chromium -> Setting -> (Advanced) Manage Certificates -> Import -> 'server_rootCA.pem'
ВЫ ВСЕ СДЕЛАНО!
P.S. Вместо создания функциональной пары сертификатов CA и сервера (согласно приведенным выше инструкциям) вы можете просто отключить заголовки HSTS в конфигурации вашего HTTP-сервера. Это предотвратит использование Chromium HTTPS и позволит пользователям нажимать «Дополнительно → перейти к your.url (небезопасно)» без необходимости получать и устанавливать собственный сертификат CA (server_rootCA.pem). Другими словами, отключение HSTS позволит публично просматривать ваш сайт через HTTP и / или небезопасное соединение HTTPS (будьте осторожны!).
Для Apache2 добавьте следующее в файл сайта, раздел HTTP (порт 80)
Header unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=0;includeSubDomains"
Протестировано на Debian / Apache2.4 + Debian / Chromium 59
https://ram.k0a1a.net/self-signed_https_cert_after_chrome_58
Есть несколько отличных ответов, которые дают примеры того, как заставить это работать, но ни один из них не объясняет, где что-то пошло не так в вашей попытке. OpenSSL иногда может быть довольно неинтуитивным, поэтому стоит пройтись по нему.
Во-первых, в стороне, OpenSSL по умолчанию игнорирует любые значения отличительных имен, которые вы указываете в config. Если вы хотите их использовать, вы должны добавить prompt = no
в вашу конфигурацию. Кроме того, написанная команда генерирует только сертификат. запрос не сертификат, поэтому -days
команда ничего не делает.
Если вы сгенерируете запрос на сертификат, используя эту команду, которую вы дали, и проверите результат, присутствует альтернативное имя субъекта:
$ openssl req -new -key server.key -out server.csr -config config.cnf -sha256
$ openssl req -text -noout -in server.csr
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
...
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:dev.mycompany.com
Signature Algorithm: sha256WithRSAEncryption
...
Но затем, если вы сгенерируете сертификат с помощью команды в ссылке heroku и проверите результат, альтернативное имя субъекта отсутствует:
$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
$ openssl x509 -text -noout -in server.crt
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
89:fd:75:26:43:08:04:61
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = Massachusetts, L = Boston, O = MyCompany
Validity
Not Before: Jan 21 04:27:21 2018 GMT
Not After : Jan 21 04:27:21 2019 GMT
Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
...
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
...
Причина в том, что по умолчанию OpenSSL не копирует расширения из запроса в сертификат. Обычно сертификат создается / подписывается ЦС на основе запроса от клиента, и некоторые расширения могут предоставить сертификату большую мощность, чем предполагал ЦС, если они будут слепо доверять расширениям, определенным в запросе.
Есть способы указать OpenSSL скопировать расширения, но IMHO это больше, чем просто предоставление расширений в файле конфигурации при создании сертификата.
Если вы попытаетесь использовать существующий файл конфигурации, это не сработает, потому что раздел верхнего уровня отмечен [req]
поэтому эти настройки применяются только к команде req, а не к команде x509. Маркер раздела верхнего уровня не обязательно, поэтому вы можете просто удалить эту первую строку, и тогда она будет работать как для запросов, так и для сертификатов.
$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt -extfile config.cnf
В качестве альтернативы вы можете использовать -x509
аргумент к req
для создания самозаверяющего сертификата с помощью одной команды вместо создания сначала запроса, а затем сертификата. В этом случае нет необходимости снимать [req]
строка раздела, поскольку этот раздел читается и используется командой req.
$ openssl req -x509 -sha256 -days 365 -key server.key -out server.crt -config config.cnf
Напомним, вот модифицированный файл конфигурации, используемый в приведенных выше командах:
default_bits = 2048
distinguished_name = dn
x509_extensions = san
req_extensions = san
extensions = san
prompt = no
[ dn ]
countryName = US
stateOrProvinceName = Massachusetts
localityName = Boston
organizationName = MyCompany
[ san ]
subjectAltName = DNS:dev.mycompany.com
Мое решение - оставить главное openssl.cnf
как есть и просто в конце добавить новый раздел вроде [ cert_www.example.com ]
где www.example.com - это веб-сайт, для которого я хочу создать сертификат, и в нем укажите subjectAltName
Мне бы понадобилось (и все остальное). Конечно, раздел можно называть как угодно.
После этого я могу запустить openssl req
как и раньше, просто добавив -extensions cert_www.example.com
чтобы его содержание было подобрано, и я добавляю -subj
чтобы добавить непосредственно всю информацию DN.
Не забудьте проверить содержимое сертификата после его создания и перед его использованием с помощью openssl x509 -text
Как сценарий оболочки, который должен работать на разных платформах с bash. Предполагает HOSTNAME
env для оболочки или укажите имя хоста по вашему выбору, например self_signed_cert.sh test
set -e
if [ -z "$1" ]; then
hostname="$HOSTNAME"
else
hostname="$1"
fi
local_openssl_config="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = san_self_signed
[ req_distinguished_name ]
CN=$hostname
[ san_self_signed ]
subjectAltName = DNS:$hostname, DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign
extendedKeyUsage = serverAuth, clientAuth, timeStamping
"
openssl req \
-newkey rsa:2048 -nodes \
-keyout "$hostname.key.pem" \
-x509 -sha256 -days 3650 \
-config <(echo "$local_openssl_config") \
-out "$hostname.cert.pem"
openssl x509 -noout -text -in "$hostname.cert.pem"
Вышеупомянутое более или менее вводит минимальную информацию о конфигурационном файле, необходимую openssl.
Примечание, включены дополнительные DNS:localhost
в качестве SAN, чтобы упростить тестирование через localhost. Удалите этот лишний бит из сценария, если он вам не нужен.
bcardarella ответ отличный (не могу комментировать / голосовать за недостаточную репутацию). Однако в ответе используется существующее расположение файла конфигурации openssl, которое зависит от платформы ... следовательно:
Работает для меня
Очевидно, что нужно просто найти файл конфигурации openssl для вашей собственной платформы и указать его правильное местоположение.
Чтобы проверить, импортируйте test.cert.pem
в авторитеты хрома в chrome://settings/certificates
, и:
openssl s_server -key test.key.pem -cert test.cert.pem -accept 20443 -www &
openssl_pid=$!
google-chrome https://localhost:20443
И после тестирования
kill $openssl_pid