Как создать самозаверяющий сертификат с OpenSSL

Я добавляю поддержку HTTPS на встроенное устройство Linux. Я попытался создать самозаверяющий сертификат с помощью этих шагов:

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

Это работает, но я получаю некоторые ошибки, например, с Google Chrome:

Это, вероятно, не тот сайт, который вы ищете!
Сертификат безопасности сайта не является доверенным!

Я что-то пропустил? Это правильный способ создания самозаверяющего сертификата?

Ответ 1

Вы можете сделать это одной командой:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Вы также можете добавить -nodes (сокращение от no DES), если вы не хотите защищать свой закрытый ключ парольной фразой. В противном случае вам будет предложено ввести пароль как минимум из 4 символов.

Параметр days (365) можно заменить любым числом, чтобы повлиять на срок годности. Затем вам будет предложено ввести что-то вроде "Название страны", но вы можете просто нажать Enter и принять значения по умолчанию.

Добавьте -subj '/CN=localhost' чтобы подавить вопросы о содержании сертификата (замените localhost на нужный домен).

Самозаверяющие сертификаты не проверяются третьими лицами, если вы ранее не импортировали их в браузеры. Если вам нужна дополнительная безопасность, вы должны использовать сертификат, подписанный центром сертификации (CA).

Ответ 2

  Я что-то пропустил? Это правильный способ создания самозаверяющего сертификата?

Легко создать самозаверяющий сертификат. Вы просто используете команду openssl req. Может быть сложно создать тот, который будет использоваться самым большим выбором клиентов, таких как браузеры и инструменты командной строки.

Это сложно, потому что браузеры имеют свои собственные требования, и они более строгие, чем IETF. Требования, используемые браузерами, задокументированы на CA/Browser Forums (см. ссылки ниже). Ограничения возникают в двух ключевых областях: (1) якоря доверия и (2) имена DNS.

Современные браузеры (например, Warez, который мы используем в 2014/2015 гг.) Хотят получить сертификат, привязанный к доверенному якору, и хотят, чтобы DNS-имена были представлены в сертификате особым образом. И браузеры активно борются с самозаверяющими серверными сертификатами.

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

Если вы не обладаете собственными полномочиями, вы должны правильно присвоить DNS-имена, чтобы сертификат имел наибольшие шансы на успех. Но я бы посоветовал вам стать вашим собственным авторитетом. Легко стать вашим собственным авторитетом, и он обойдет все вопросы доверия (кому лучше доверять, чем вам?).


Вероятно, это не тот сайт, который вы ищете!
Сертификат безопасности сайта не является доверенным!

Это связано с тем, что браузеры используют предварительно определенный список якорей доверия для проверки сертификатов сервера. Самозаверяющий сертификат не связывается с доверенным якорем.

Лучший способ избежать этого:

  1. Создайте свой собственный авторитет (то есть станьте CA)
  2. Создать запрос на подпись сертификата (CSR) для сервера
  3. Подписать CSR сервера с помощью своего ключа CA
  4. Установить сертификат сервера на сервере
  5. Установите сертификат CA на клиенте

Шаг 1 - Создать свой собственный авторитет - значит создать самозаверяющий сертификат с CA: true и правильным использованием ключа. Это означает, что субъект и эмитент - это одна и та же сущность, для CA задано значение true в базовых ограничениях (его также следует пометить как критический), использование ключа - keyCertSign и crlSign (если вы используете CRL), а также субъект Идентификатор ключа (SKI) совпадает с идентификатором ключа авторизации (AKI).

Чтобы стать собственным центром сертификации, см. *Как подписать запрос на подпись сертификата в своем центре сертификации? в Qaru. Затем импортируйте свой CA в Trust Store, используемый браузером.

Шаги 2–4 - это примерно то же, что вы делаете сейчас для общедоступного сервера, когда вы подключаетесь к службам ЦС, таким как Startcom или CAcert. Шаги 1 и 5 позволяют вам избежать сторонних полномочий и действовать как свои собственные полномочия (кому лучше доверять, чем себе?).

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

Проблема браузеров (и других подобных пользовательских агентов), не доверяющих самозаверяющим сертификатам, станет большой проблемой в Интернете вещей (IoT). Например, что произойдет, когда вы подключитесь к своему термостату или холодильнику, чтобы запрограммировать его? Ответ - ничего хорошего в том, что касается взаимодействия с пользователем.

Рабочая группа W3C WebAppSec начинает изучать эту проблему. См., Например, Предложение: пометка HTTP как незащищенного.


Как создать самозаверяющий сертификат с OpenSSL

Приведенные ниже команды и файл конфигурации создают самозаверяющий сертификат (он также показывает, как создать запрос на подпись). Они отличаются от других ответов в одном отношении: имена DNS, используемые для самозаверяющего сертификата, указаны в дополнительном имени субъекта (SAN), а не в общем имени (CN).

Имена DNS помещаются в SAN через файл конфигурации со строкой subjectAltName = @alternate_names (нет способа сделать это через командную строку). Затем в файле конфигурации есть раздел alternate_names (вы должны настроить его на свой вкус):

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# IP.1        = 127.0.0.1
# IP.2        = ::1

Важно указывать DNS-имя в SAN, а не в CN, потому что и IETF, и форумы CA/Browser определяют практику. Они также указывают, что DNS-имена в CN устарели (но не запрещены). Если вы поместите DNS-имя в CN, оно должно быть включено в SAN в соответствии с политиками CA/B. Таким образом, вы не можете избежать использования альтернативного имени субъекта.

Если вы не введете DNS-имена в SAN, сертификат не будет проверен в браузере и других пользовательских агентах, которые следуют рекомендациям CA/Browser Forum.

Связано: браузеры следуют политикам CA/Browser Forum; а не политики IETF. Это одна из причин, по которой сертификат, созданный с помощью OpenSSL (который обычно следует IETF), иногда не проходит проверку в браузере (браузеры следуют CA/B). Это разные стандарты, разные правила выдачи и разные требования к валидации.


Создайте самозаверяющий сертификат (обратите внимание на добавление опции -x509):

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

Создать запрос на подпись (обратите внимание на отсутствие опции -x509):

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

Распечатать самозаверяющий сертификат:

openssl x509 -in example-com.cert.pem -text -noout

Распечатайте запрос на подпись:

openssl req -in example-com.req.pem -text -noout

Файл конфигурации (передается с помощью опции -config)

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because it presented to the user. The server DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = [email protected]

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier    = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

Для Chrome может потребоваться следующее. В противном случае Chrome может жаловаться, что общее имя неверно (ERR_CERT_COMMON_NAME_INVALID). Я не уверен, какова связь между IP-адресом в SAN и CN в этом случае.

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

Существуют и другие правила обработки имен DNS в сертификатах X.509/PKIX. Обратитесь к этим документам за правилами:

RFC 6797 и RFC 7469 перечислены, потому что они более строгие, чем другие документы RFC и CA/B. RFC 6797 и 7469 также не разрешают использование IP-адреса.

Ответ 3

Вот варианты, описанные в ответе @diegows, более подробно описанные в документации:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX
req

Утилита запроса сертификата PKCS # 10 и создания сертификата.

-x509

эта опция выводит самозаверяющий сертификат вместо запроса сертификата. Обычно это используется для создания тестового сертификата или самозаверяющего корневого центра сертификации.

-newkey arg

эта опция создает новый запрос сертификата и новый закрытый ключ. Аргумент принимает одну из нескольких форм. rsa: nbits, где nbits - количество бит, генерирует ключ RSA размером nbit.

-keyout filename

это дает имя файла для записи недавно созданного закрытого ключа.

-out filename

Это указывает имя выходного файла для записи или стандартный вывод по умолчанию.

-days n

когда используется опция -x509, это указывает количество дней для сертификации сертификата. По умолчанию 30 дней.

-nodes

если указана эта опция, то при создании закрытого ключа он не будет зашифрован.

Документация на самом деле более подробная, чем выше; Я просто резюмировал это здесь.

Ответ 4

Начиная с 2019 года, следующая команда удовлетворяет все ваши потребности, включая SAN:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -extensions san -config \
  <(echo "[req]"; 
    echo distinguished_name=req; 
    echo "[san]"; 
    echo subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1
    ) \
  -subj /CN=example.com

В OpenSSL ≥ 1.1.1 это можно сократить до:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -subj /CN=example.com \
  -addext subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1

Он создает сертификат, который

  • действителен для доменов example.com и example.net (SAN),
  • также действителен для IP-адреса 10.0.0.1 (SAN),
  • относительно сильный (по состоянию на 2019 г.) и
  • действителен в течение 3650 дней (~ 10 лет).

Он создает следующие файлы:

  • Закрытый ключ: example.key
  • Сертификат: example.crt

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

Замечание № 1: параметры шифрования

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

В будущем вы можете захотеть использовать более чем 4096 битов для ключа RSA и алгоритм хеширования, более сильный, чем sha256, но по состоянию на 2019 г. это нормальные значения. Они достаточно сильны, хотя поддерживаются всеми современными браузерами.

Замечание № 2: параметр "-nodes"

Теоретически вы можете не указывать параметр -nodes (что означает "без шифрования DES"), в этом случае example.key будет зашифрован паролем. Однако это почти никогда не полезно для установки на сервере, поскольку вам придется либо хранить пароль на сервере, либо вводить его вручную при каждой перезагрузке.

Замечание № 3: MinGW

В Windows в MinGW bash, вы должны поставить перед командой префикс MSYS_NO_PATHCONV=1:

MSYS_NO_PATHCONV=1 openssl ...

В качестве альтернативы, запустите команду в простой командной строке Windows cmd.exe.

Замечание № 4: см. также

Ответ 5

Я не могу комментировать, поэтому я поставлю это как отдельный ответ. Я нашел несколько вопросов с принятым однострочным ответом:

  • Однострочник содержит ключевую фразу в ключе.
  • Однострочник использует SHA-1, который во многих браузерах выдает предупреждения в консоли.

Вот упрощенная версия, которая удаляет ключевую фразу, повышает безопасность для подавления предупреждений и включает предложение в комментариях для передачи в -subj для удаления полного списка вопросов:

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Замените localhost на любой домен, который вам требуется. Вам нужно будет выполнить первые две команды одну за другой, так как OpenSSL предложит ввести ключевую фразу.

Чтобы объединить их в файл .pem:

cat server.crt server.key > cert.pem

Ответ 6

Современные браузеры теперь вызывают ошибку безопасности для хорошо сформированных самозаверяющих сертификатов, если они не имеют SAN (Subject Alternate Name). OpenSSL не предоставляет способ командной строки, чтобы указать это, поэтому многие обучающие программы и закладки разработчиков неожиданно устарели.

Самый быстрый способ запустить снова - это короткий автономный файл conf:

  1. Создайте конфигурационный файл OpenSSL (пример: req.cnf)

    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
    
  2. Создайте сертификат, ссылающийся на этот файл конфигурации

    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
    

Пример конфигурации из https://support.citrix.com/article/CTX135602

Ответ 7

Я бы порекомендовал добавить параметр -sha256, чтобы использовать алгоритм хеширования SHA-2, поскольку основные браузеры рассматривают возможность отображения "сертификатов SHA-1" как небезопасных.

Та же самая командная строка из принятого ответа - @diegows с добавленным -sha256

openssl req -x509 -sha256 -newkey rsa: 2048 -keyout key.pem -out cert.pem -days XXX

Больше информации в блоге безопасности Google.

Обновление май 2018. Как отмечалось в комментариях многих, использование SHA-2 не добавляет никакой защиты к самозаверяющему сертификату. Но я все же рекомендую использовать его как хорошую привычку не использовать устаревшие/небезопасные криптографические хеш-функции. Полное объяснение доступно в разделе Почему для сертификатов выше сертификата конечного объекта можно использовать SHA-1? ,

Ответ 8

Этот сценарий я использую на локальных ящиках для установки SAN (subjectAltName) в самозаверяющих сертификатах.

Этот сценарий берет имя домена (example.com) и создает SAN для *.example.com и example.com в одном сертификате. Разделы ниже комментируются. Назовите сценарий (например, generate-ssl.sh) и дайте ему права на выполнение. Файлы будут записаны в тот же каталог, что и скрипт.

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

#!/usr/bin/env bash

# Set the TLD domain we want to use
BASE_DOMAIN="example.com"

# Days for the cert to live
DAYS=1095

# A blank passphrase
PASSPHRASE=""

# Generated configuration file
CONFIG_FILE="config.txt"

cat > $CONFIG_FILE <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = CA
ST = BC
L = Vancouver
O = Example Corp
OU = Testing Domain
emailAddress = [email protected]$BASE_DOMAIN
CN = $BASE_DOMAIN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.$BASE_DOMAIN
DNS.2 = $BASE_DOMAIN
EOF

# The file name can be anything
FILE_NAME="$BASE_DOMAIN"

# Remove previous keys
echo "Removing existing certs like $FILE_NAME.*"
chmod 770 $FILE_NAME.*
rm $FILE_NAME.*

echo "Generating certs for $BASE_DOMAIN"

# Generate our Private Key, CSR and Certificate
# Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout "$FILE_NAME.key" -days $DAYS -out "$FILE_NAME.crt" -passin pass:$PASSPHRASE -config "$CONFIG_FILE"

# OPTIONAL - write an info to see the details of the generated crt
openssl x509 -noout -fingerprint -text < "$FILE_NAME.crt" > "$FILE_NAME.info"

# Protect the key
chmod 400 "$FILE_NAME.key"

Этот сценарий также записывает информационный файл, чтобы вы могли проверить новый сертификат и убедиться, что SAN настроен правильно.

                ...
                28:dd:b8:1e:34:b5:b1:44:1a:60:6d:e3:3c:5a:c4:
                da:3d
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            DNS:*.example.com, DNS:example.com
Signature Algorithm: sha256WithRSAEncryption
     3b:35:5a:d6:9e:92:4f:fc:f4:f4:87:78:cd:c7:8d:cd:8c:cc:
     ...

Если вы используете Apache, вы можете сослаться на вышеуказанный сертификат в файле конфигурации следующим образом:

<VirtualHost _default_:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/htdocs

    SSLEngine on
    SSLCertificateFile path/to/your/example.com.crt
    SSLCertificateKeyFile path/to/your/example.com.key
</VirtualHost>

Не забудьте перезапустить сервер Apache (или Nginx, или IIS), чтобы новый сертификат вступил в силу.

Ответ 9

2017 однострочный:

openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.pem \
-new \
-out server.pem \
-subj /CN=localhost \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
-sha256 \
-days 3650

Это также работает в Chrome 57, так как он предоставляет SAN, не имея другого файла конфигурации. Это было взято из ответа здесь.

Это создает один файл .pem, который содержит как закрытый ключ, так и сертификат. Вы можете переместить их в отдельные файлы .pem, если это необходимо.

Ответ 10

У вас правильная общая процедура. Синтаксис команды приведен ниже.

openssl req -new -key {private key file} -out {output file}

Тем не менее, предупреждения отображаются, потому что браузер не смог проверить идентификацию путем проверки сертификата с помощью известного центра сертификации (CA).

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

  1. Создать личный ключ
  2. Используйте этот закрытый ключ для создания файла CSR
  3. Отправить CSR в CA (Verisign или другие и т.д.)
  4. Установите полученный сертификат от CA на веб-сервере
  5. Добавить другие сертификаты в цепочку аутентификации в зависимости от типа сертификата

У меня есть более подробная информация об этом в посте " Защита соединения: создание сертификата безопасности с OpenSSL".

Ответ 11

Один лайнер FTW. Мне нравится быть простым. Почему бы не использовать одну команду, которая содержит ВСЕ необходимые аргументы? Вот как мне это нравится - это создает сертификат x509 и его ключ PEM:

openssl req -x509 \
 -nodes -days 365 -newkey rsa:4096 \
 -keyout self.key.pem \
 -out self-x509.crt \
 -subj "/C=US/ST=WA/L=Seattle/CN=example.com/[email protected]"

Эта единственная команда содержит все ответы, которые вы обычно предоставляете для деталей сертификата. Таким образом, вы можете установить параметры и запустить команду, получить выходные данные, а затем пойти на кофе.

>> Подробнее здесь <<

Ответ 12

Однострочная версия 2017:

CentOS:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

Ubuntu:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "/CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

Редактировать: добавлен добавленный слеш к опции 'subj' для Ubuntu.

Ответ 13

Генерировать ключи

Я использую /etc/mysql для хранения сертификатов, потому что /etc/apparmor.d/usr.sbin.mysqld содержит /etc/mysql/*.pem r.

sudo su -
cd /etc/mysql
openssl genrsa -out ca-key.pem 2048;
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem;
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem;
openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;

Добавить конфигурацию

/etc/mysql/my.cnf

[client]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/client-cert.pem
ssl-key=/etc/mysql/client-key.pem

[mysqld]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

На моей установке сервер Ubuntu вошел в систему: /var/log/mysql/error.log

Последующие заметки:

  • SSL error: Unable to get certificate from '...'

    MySQL может быть отказано в доступе на чтение к вашему файлу сертификата, если он не находится в конфигурации apparmors. Как упоминалось в предыдущих шагах ^, сохраните все наши сертификаты в .pem файлов .pem каталоге /etc/mysql/ который по умолчанию утвержден apparmor (или измените ваш apparmor/SELinux, чтобы разрешить доступ к ним, где бы вы их не хранили).

  • SSL error: Unable to get private key

    Ваша версия сервера MySQL может не поддерживать формат rsa:2048 по умолчанию

    Преобразовать сгенерированный rsa:2048 в обычный rsa с:

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • Проверьте, поддерживает ли локальный сервер SSL:

    mysql -u root -p
    mysql> show variables like "%ssl%";
    +---------------+----------------------------+
    | Variable_name | Value                      |
    +---------------+----------------------------+
    | have_openssl  | YES                        |
    | have_ssl      | YES                        |
    | ssl_ca        | /etc/mysql/ca-cert.pem     |
    | ssl_capath    |                            |
    | ssl_cert      | /etc/mysql/server-cert.pem |
    | ssl_cipher    |                            |
    | ssl_key       | /etc/mysql/server-key.pem  |
    +---------------+----------------------------+
    
  • Проверка соединения с базой данных зашифрована SSL:

    Проверка соединения

    При входе в экземпляр MySQL вы можете выполнить запрос:

    show status like 'Ssl_cipher';
    

    Если ваше соединение не зашифровано, результат будет пустым:

    mysql> show status like 'Ssl_cipher';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | Ssl_cipher    |       |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    В противном случае он будет показывать строку ненулевой длины для используемого шифра:

    mysql> show status like 'Ssl_cipher';
    +---------------+--------------------+
    | Variable_name | Value              |
    +---------------+--------------------+
    | Ssl_cipher    | DHE-RSA-AES256-SHA |
    +---------------+--------------------+
    1 row in set (0.00 sec)
    
  • Требовать ssl для определенного подключения пользователя ('require ssl'):

    • SSL

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

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      REQUIRE SSL;
    

    Для подключения клиент должен указать параметр --ssl-ca для проверки подлинности сертификата сервера и может дополнительно указать параметры --ssl-key и --ssl-cert. Если не указана ни опция --ssl-ca, ни опция --ssl-capath, клиент не аутентифицирует сертификат сервера.


Альтернативная ссылка: подробное руководство по безопасным PHP-соединениям с MySQL по SSL.

Ответ 14

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

Основная причина, по которой человек не хочет получать подписанный сертификат от центра сертификации, - это стоимость - Symantec взимает от 995 до 1999 долларов в год за сертификаты - только за сертификат, предназначенный для внутренней сети, Symantec взимает 399 долларов в год. Эту стоимость легко оправдать, если вы обрабатываете платежи по кредитным картам или работаете в центре прибыли высокодоходной компании. Это больше, чем многие могут себе позволить для личного проекта, который каждый создает в Интернете, или для некоммерческой организации, работающей с минимальным бюджетом, или если кто-то работает в центре затрат организации - центры затрат всегда пытаются сделать больше менее.

Альтернативой является использование certbot (см. О certbot). Certbot - это простой в использовании автоматический клиент, который получает и развертывает сертификаты SSL/TLS для вашего веб-сервера.

Если вы настроили certbot, вы можете разрешить ему создавать и поддерживать для вас сертификат, выданный центром сертификации Lets Encrypt.

Я сделал это на выходных для своей организации. Я установил необходимые пакеты для certbot на своем сервере (Ubuntu 16.04), а затем выполнил команду, необходимую для настройки и включения certbot. Вероятно, для certbot нужен плагин DNS - в настоящее время мы используем DigitalOcean, хотя, возможно, скоро перейдем на другой сервис.

Обратите внимание, что некоторые инструкции были не совсем верными и заняли время, чтобы разобраться с Google. В первый раз это заняло довольно много времени, но теперь я думаю, что смогу сделать это за считанные минуты.

Что касается DigitalOcean, я столкнулся с трудностями, когда мне предложили ввести путь к INI файлу учетных данных DigitalOcean. Сценарий имеет в виду страницу " Приложения и API" и вкладку "Токены/ключи" на этой странице. Вам необходимо иметь или сгенерировать персональный токен доступа (чтение и запись) для API DigitalOcean - это шестнадцатеричная строка из 65 символов. Затем эту строку необходимо поместить в файл на веб-сервере, с которого вы запускаете certbot. Этот файл может содержать комментарий в качестве первой строки (комментарии начинаются С#). Вторая строка:

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

Как только я понял, как настроить токен чтения + записи для API DigitalOcean, было довольно просто использовать certbot для установки сертификата с подстановочными знаками. Обратите внимание, что не нужно настраивать подстановочный сертификат, вместо этого можно указать каждый домен и поддомен, к которому требуется применить сертификат. Это был подстановочный сертификат, который требовал INI файл учетных данных, содержащий личный токен доступа от DigitalOcean.

Обратите внимание, что сертификаты открытых ключей (также известные как сертификаты идентификации или сертификаты SSL) истекают и требуют обновления. Таким образом, вам необходимо будет обновлять свой сертификат на периодической (повторяющейся) основе. Документация certbot покрывает продление сертификатов.

Мой план состоит в том, чтобы написать сценарий для использования команды openssl, чтобы получить дату истечения срока действия моего сертификата и инициировать продление по истечении 30 дней или менее до его истечения. Затем я добавлю этот скрипт в cron и буду запускать его один раз в день.

Вот команда, чтобы прочитать дату истечения срока действия вашего сертификата:

[email protected]:~# /usr/bin/openssl x509 -enddate -noout -in path-to-certificate-pem-file
notAfter=May 25 19:24:12 2019 GMT

Ответ 15

Сценарии самоподписанного сертификата и цепочки сертификатов для RSA и ECDSA с использованием OpenSSL доступны здесь.