0
2
nginx 1.6.2, самоподписанные сертификаты сервера и клиента, openssl проверку проходят:
$ openssl verify -CAfile server/server.crt client01.crt
client01.crt: C = RU, ST = Moscow, L = Moscow, O = Companyname, OU = User, CN = etc, emailAddress = support@site.com
error 18 at 0 depth lookup:self signed certificate
OK
А при запросе nginx отвечает ошибкой 400 The SSL certificate error
В логах сервера:
2016/04/22 11:16:20 [info] 1465#0: *35 client SSL certificate verify error: (18:self signed certificate) wh
ile reading client request headers, client: 192.168.2.11, server: _, request: "GET /test HTTP/1.1", host: "
192.168.2.6"
2016/04/22 11:16:20 [debug] 1465#0: *35 http finalize request: 495, "/test?" a:1, c:1
2016/04/22 11:16:20 [debug] 1465#0: *35 event timer del: 8: 1461313040230
2016/04/22 11:16:20 [debug] 1465#0: *35 http special response: 495, "/test?"
2016/04/22 11:16:20 [debug] 1465#0: *35 http set discard body
2016/04/22 11:16:20 [debug] 1465#0: *35 echo header filter, uri "/test?"
2016/04/22 11:16:20 [debug] 1465#0: *35 xslt filter header
2016/04/22 11:16:20 [debug] 1465#0: *35 posix_memalign: 0000000001F02580:4096 @16
2016/04/22 11:16:20 [debug] 1465#0: *35 HTTP/1.1 400 Bad Request
Настройки nginx:
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.nopass.key;
ssl_client_certificate /etc/nginx/ssl/ca.crt;
ssl_verify_client on;
location {
proxy_pass http://192.168.2.6:9080;
}
}
Я правильно понимаю, что серверу не нравится то, что сертификат самоподписанный? Как разрешить?
Модуль ngx_http_ssl_module
обеспечивает работу
по протоколу HTTPS.
По умолчанию этот модуль не собирается, его сборку необходимо
разрешить с помощью конфигурационного параметра
--with-http_ssl_module
.
Для сборки и работы этого модуля нужна библиотека
OpenSSL.
Пример конфигурации
Для уменьшения загрузки процессора рекомендуется
-
установить число
рабочих процессов
равным числу процессоров, -
разрешить
keep-alive
соединения, - включить разделяемый кэш сессий,
- выключить встроенный кэш сессий
-
и, возможно, увеличить время жизни сессии
(по умолчанию 5 минут):
worker_processes auto; http { ... server { listen 443 ssl; keepalive_timeout 70; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5; ssl_certificate /usr/local/nginx/conf/cert.pem; ssl_certificate_key /usr/local/nginx/conf/cert.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ... }
Директивы
Синтаксис: |
ssl
|
---|---|
Умолчание: |
ssl off; |
Контекст: |
http , server
|
Эта директива устарела в версии 1.15.0.
Вместо неё следует
использовать параметр ssl
директивы listen.
Синтаксис: |
ssl_buffer_size
|
---|---|
Умолчание: |
ssl_buffer_size 16k; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.5.9.
Задаёт размер буфера, используемого при отправке данных.
По умолчанию размер буфера равен 16k, что соответствует минимальным
накладным расходам при передаче больших ответов.
С целью минимизации времени получения начала ответа (Time To First Byte)
может быть полезно использовать меньшие значения,
например:
ssl_buffer_size 4k;
Синтаксис: |
ssl_certificate
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Указывает файл
с сертификатом в формате PEM
для данного виртуального сервера.
Если вместе с основным сертификатом нужно указать промежуточные,
то они должны находиться в этом же файле в следующем порядке: сначала
основной сертификат, а затем промежуточные.
В этом же файле может находиться секретный ключ в формате PEM.
Начиная с версии 1.11.0
эта директива может быть указана несколько раз
для загрузки сертификатов разных типов, например RSA и ECDSA:
server { listen 443 ssl; server_name example.com; ssl_certificate example.com.rsa.crt; ssl_certificate_key example.com.rsa.key; ssl_certificate example.com.ecdsa.crt; ssl_certificate_key example.com.ecdsa.key; ... }
Возможность задавать отдельные
цепочки
сертификатов
для разных сертификатов есть только в OpenSSL 1.0.2 и выше.
Для более старых версий следует указывать только одну цепочку сертификатов.
Начиная с версии 1.15.9 в имени файла можно использовать переменные
при использовании OpenSSL 1.0.2 и выше:
ssl_certificate $ssl_server_name.crt; ssl_certificate_key $ssl_server_name.key;
Однако нужно учитывать, что при использовании переменных
сертификат загружается при каждой операции SSL handshake,
что может отрицательно влиять на производительность.
Вместо файла
можно указать значение
data
:$переменная
(1.15.10),
при котором сертификат загружается из переменной
без использования промежуточных файлов.
При этом следует учитывать, что ненадлежащее использование
подобного синтаксиса может быть небезопасно,
например данные секретного ключа могут попасть в
лог ошибок.
Нужно иметь в виду, что из-за ограничения протокола HTTPS
для максимальной совместимости виртуальные серверы должны слушать на
разных
IP-адресах.
Синтаксис: |
ssl_certificate_key
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Указывает файл
с секретным ключом в формате PEM
для данного виртуального сервера.
Вместо файла
можно указать значение
engine
:имя
:id
(1.7.9),
которое загружает ключ с указанным id
из OpenSSL engine с заданным именем
.
Вместо файла
можно указать значение
data
:$переменная
(1.15.10),
при котором секретный ключ загружается из переменной
без использования промежуточных файлов.
При этом следует учитывать, что ненадлежащее использование
подобного синтаксиса может быть небезопасно,
например данные секретного ключа могут попасть в
лог ошибок.
Начиная с версии 1.15.9 в имени файла можно использовать переменные
при использовании OpenSSL 1.0.2 и выше.
Синтаксис: |
ssl_ciphers
|
---|---|
Умолчание: |
ssl_ciphers HIGH:!aNULL:!MD5; |
Контекст: |
http , server
|
Описывает разрешённые шифры.
Шифры задаются в формате, поддерживаемом библиотекой
OpenSSL, например:
ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
Полный список можно посмотреть с помощью команды
“openssl ciphers
”.
В предыдущих версиях nginx по умолчанию использовались
другие
шифры.
Синтаксис: |
ssl_client_certificate
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Указывает файл
с доверенными сертификатами CA в формате
PEM, которые используются для
проверки клиентских сертификатов и
ответов OCSP, если включён ssl_stapling.
Список сертификатов будет отправляться клиентам.
Если это нежелательно, можно воспользоваться директивой
ssl_trusted_certificate.
Синтаксис: |
ssl_conf_command
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.19.4.
Задаёт произвольные конфигурационные
команды
OpenSSL.
Директива поддерживается при использовании OpenSSL 1.0.2 и выше.
На одном уровне может быть указано
несколько директив ssl_conf_command
:
ssl_conf_command Options PrioritizeChaCha; ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;
Директивы наследуются с предыдущего уровня конфигурации при условии, что
на данном уровне не описаны свои директивы ssl_conf_command
.
Следует учитывать, что изменение настроек OpenSSL напрямую
может привести к неожиданному поведению.
Синтаксис: |
ssl_crl
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 0.8.7.
Указывает файл
с отозванными сертификатами (CRL)
в формате PEM, используемыми для
проверки клиентских сертификатов.
Синтаксис: |
ssl_dhparam
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 0.7.2.
Указывает файл
с параметрами для DHE-шифров.
По умолчанию параметры не заданы,
и соответственно DHE-шифры не будут использоваться.
До версии 1.11.0 по умолчанию использовались встроенные параметры.
Синтаксис: |
ssl_early_data
|
---|---|
Умолчание: |
ssl_early_data off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.15.3.
Разрешает или запрещает TLS 1.3
early data.
Запросы, отправленные внутри early data, могут быть подвержены
атакам повторного воспроизведения (replay).
Для защиты от подобных атак на уровне приложения
необходимо использовать
переменную $ssl_early_data.
proxy_set_header Early-Data $ssl_early_data;
Директива поддерживается при использовании OpenSSL 1.1.1 и выше (1.15.4) или
BoringSSL.
Синтаксис: |
ssl_ecdh_curve
|
---|---|
Умолчание: |
ssl_ecdh_curve auto; |
Контекст: |
http , server
|
Эта директива появилась в версиях 1.1.0 и 1.0.6.
Задаёт кривую для ECDHE-шифров.
При использовании OpenSSL 1.0.2 и выше
можно указывать несколько кривых (1.11.0), например:
ssl_ecdh_curve prime256v1:secp384r1;
Специальное значение auto
(1.11.0) соответствует
встроенному в библиотеку OpenSSL списку кривых для OpenSSL 1.0.2 и выше,
или prime256v1
для более старых версий.
До версии 1.11.0
по умолчанию использовалась криваяprime256v1
.
При использовании OpenSSL 1.0.2 и выше
директива задаёт список кривых, поддерживаемых сервером.
Поэтому для работы ECDSA-сертификатов
важно, чтобы список включал кривые, используемые в сертификатах.
Синтаксис: |
ssl_ocsp
|
---|---|
Умолчание: |
ssl_ocsp off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.19.0.
Включает проверку OCSP для цепочки клиентских сертификатов.
Параметр leaf
включает проверку только клиентского сертификата.
Для работы проверки OCSP
необходимо дополнительно установить значение директивы
ssl_verify_client в
on
или optional
.
Для преобразования имени хоста OCSP responder’а в адрес необходимо
дополнительно задать директиву
resolver.
Пример:
ssl_verify_client on; ssl_ocsp on; resolver 192.0.2.1;
Синтаксис: |
ssl_ocsp_cache
|
---|---|
Умолчание: |
ssl_ocsp_cache off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.19.0.
Задаёт имя
и размер
кэша,
который хранит статус клиентских сертификатов для проверки OCSP-ответов.
Кэш разделяется между всеми рабочими процессами.
Кэш с одинаковым названием может использоваться в нескольких
виртуальных серверах.
Параметр off
запрещает использование кэша.
Синтаксис: |
ssl_ocsp_responder
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.19.0.
Переопределяет URL OCSP responder’а, указанный в расширении сертификата
“Authority
Information Access”
для проверки клиентских сертификатов.
Поддерживаются только “http://
” OCSP responder’ы:
ssl_ocsp_responder http://ocsp.example.com/;
Синтаксис: |
ssl_password_file
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.7.3.
Задаёт файл
с паролями от
секретных ключей,
где каждый пароль указан на отдельной строке.
Пароли применяются по очереди в момент загрузки ключа.
Пример:
http { ssl_password_file /etc/keys/global.pass; ... server { server_name www1.example.com; ssl_certificate_key /etc/keys/first.key; } server { server_name www2.example.com; # вместо файла можно указать именованный канал ssl_password_file /etc/keys/fifo; ssl_certificate_key /etc/keys/second.key; } }
Синтаксис: |
ssl_prefer_server_ciphers
|
---|---|
Умолчание: |
ssl_prefer_server_ciphers off; |
Контекст: |
http , server
|
Указывает, чтобы при использовании протоколов SSLv3 и TLS
серверные шифры были более приоритетны, чем клиентские.
Синтаксис: |
ssl_protocols
|
---|---|
Умолчание: |
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; |
Контекст: |
http , server
|
Разрешает указанные протоколы.
Параметры
TLSv1.1
иTLSv1.2
(1.1.13, 1.0.12) работают только при использовании OpenSSL 1.0.1 и выше.
Параметр
TLSv1.3
(1.13.0) работает только
при использовании OpenSSL 1.1.1 и выше.
Параметр
TLSv1.3
используется по умолчанию
начиная с 1.23.4.
Синтаксис: |
ssl_reject_handshake
|
---|---|
Умолчание: |
ssl_reject_handshake off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.19.4.
Если разрешено, то операции SSL handshake в
блоке server будут отклонены.
Например в этой конфигурации отклоняются все операции SSL handshake с
именем сервера, отличным от example.com
:
server { listen 443 ssl default_server; ssl_reject_handshake on; } server { listen 443 ssl; server_name example.com; ssl_certificate example.com.crt; ssl_certificate_key example.com.key; }
Синтаксис: |
ssl_session_cache
|
---|---|
Умолчание: |
ssl_session_cache none; |
Контекст: |
http , server
|
Задаёт тип и размеры кэшей для хранения параметров сессий.
Тип кэша может быть следующим:
off
-
жёсткое запрещение использования кэша сессий:
nginx явно сообщает клиенту, что сессии не могут использоваться повторно. none
-
мягкое запрещение использования кэша сессий:
nginx сообщает клиенту, что сессии могут использоваться повторно, но
на самом деле не хранит параметры сессии в кэше. builtin
-
встроенный в OpenSSL кэш, используется в рамках только одного рабочего процесса.
Размер кэша задаётся в сессиях.
Если размер не задан, то он равен 20480 сессиям.
Использование встроенного кэша может вести к фрагментации памяти. shared
-
кэш, разделяемый между всеми рабочими процессами.
Размер кэша задаётся в байтах, в 1 мегабайт может поместиться
около 4000 сессий.
У каждого разделяемого кэша должно быть произвольное название.
Кэш с одинаковым названием может использоваться в нескольких
виртуальных серверах.
Также он используется для автоматического создания, хранения и
периодического обновления ключей TLS session tickets (1.23.2),
если они не указаны явно
с помощью директивы ssl_session_ticket_key.
Можно использовать одновременно оба типа кэша, например:
ssl_session_cache builtin:1000 shared:SSL:10m;
однако использование только разделяемого кэша без встроенного должно
быть более эффективным.
Синтаксис: |
ssl_session_ticket_key
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.5.7.
Задаёт файл
с секретным ключом, применяемым при шифровании и
расшифровании TLS session tickets.
Директива необходима, если один и тот же ключ нужно использовать
на нескольких серверах.
По умолчанию используется случайно сгенерированный ключ.
Если указано несколько ключей, то только первый ключ
используется для шифрования TLS session tickets.
Это позволяет настроить ротацию ключей, например:
ssl_session_ticket_key current.key; ssl_session_ticket_key previous.key;
Файл
должен содержать 80 или 48 байт случайных данных
и может быть создан следующей командой:
openssl rand 80 > ticket.key
В зависимости от размера файла для шифрования будет использоваться либо
AES256 (для 80-байтных ключей, 1.11.8), либо AES128 (для 48-байтных ключей).
Синтаксис: |
ssl_session_tickets
|
---|---|
Умолчание: |
ssl_session_tickets on; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.5.9.
Разрешает или запрещает возобновление сессий при помощи
TLS session tickets.
Синтаксис: |
ssl_session_timeout
|
---|---|
Умолчание: |
ssl_session_timeout 5m; |
Контекст: |
http , server
|
Задаёт время, в течение которого клиент может повторно
использовать параметры сессии.
Синтаксис: |
ssl_stapling
|
---|---|
Умолчание: |
ssl_stapling off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.3.7.
Разрешает или запрещает
прикрепление
OCSP-ответов сервером.
Пример:
ssl_stapling on; resolver 192.0.2.1;
Для работы OCSP stapling’а должен быть известен сертификат издателя
сертификата сервера.
Если в заданном директивой ssl_certificate
файле не содержится промежуточных сертификатов,
то сертификат издателя сертификата сервера следует поместить в файл,
заданный директивой ssl_trusted_certificate.
Для преобразования имени хоста OCSP responder’а в адрес необходимо
дополнительно задать директиву
resolver.
Синтаксис: |
ssl_stapling_file
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.3.7.
Если задано, то вместо опроса OCSP responder’а,
указанного в сертификате сервера,
ответ берётся из указанного файла
.
Ответ должен быть в формате DER и может быть сгенерирован командой
“openssl ocsp
”.
Синтаксис: |
ssl_stapling_responder
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.3.7.
Переопределяет URL OCSP responder’а, указанный в расширении сертификата
“Authority
Information Access”.
Поддерживаются только “http://
” OCSP responder’ы:
ssl_stapling_responder http://ocsp.example.com/;
Синтаксис: |
ssl_stapling_verify
|
---|---|
Умолчание: |
ssl_stapling_verify off; |
Контекст: |
http , server
|
Эта директива появилась в версии 1.3.7.
Разрешает или запрещает проверку сервером ответов OCSP.
Для работоспособности проверки сертификат издателя сертификата сервера,
корневой сертификат и все промежуточные сертификаты должны быть указаны
как доверенные с помощью директивы
ssl_trusted_certificate.
Синтаксис: |
ssl_trusted_certificate
|
---|---|
Умолчание: |
— |
Контекст: |
http , server
|
Эта директива появилась в версии 1.3.7.
Задаёт файл
с доверенными сертификатами CA в формате PEM,
которые используются для проверки
клиентских сертификатов и ответов OCSP,
если включён ssl_stapling.
В отличие от ssl_client_certificate, список этих сертификатов
не будет отправляться клиентам.
Синтаксис: |
ssl_verify_client
|
---|---|
Умолчание: |
ssl_verify_client off; |
Контекст: |
http , server
|
Разрешает проверку клиентских сертификатов.
Результат проверки доступен через переменную
$ssl_client_verify.
Параметр optional
(0.8.7+) запрашивает клиентский
сертификат, и если сертификат был предоставлен, проверяет его.
Параметр optional_no_ca
(1.3.8, 1.2.5)
запрашивает сертификат
клиента, но не требует, чтобы он был подписан доверенным сертификатом CA.
Это предназначено для случаев, когда фактическая проверка сертификата
осуществляется внешним по отношению к nginx’у сервисом.
Содержимое сертификата доступно через переменную
$ssl_client_cert.
Синтаксис: |
ssl_verify_depth
|
---|---|
Умолчание: |
ssl_verify_depth 1; |
Контекст: |
http , server
|
Устанавливает глубину проверки в цепочке клиентских сертификатов.
Обработка ошибок
Модуль ngx_http_ssl_module
поддерживает несколько
нестандартных кодов ошибок, которые можно использовать для
перенаправления с помощью директивы
error_page:
- 495
- при проверке клиентского сертификата произошла ошибка;
- 496
- клиент не предоставил требуемый сертификат;
- 497
- обычный запрос был послан на порт HTTPS.
Перенаправление делается после того, как запрос полностью разобран
и доступны такие переменные, как $request_uri
,
$uri
, $args
и другие переменные.
Встроенные переменные
Модуль ngx_http_ssl_module
поддерживает
встроенные переменные:
$ssl_alpn_protocol
-
возвращает протокол, выбранный при помощи ALPN во время операции SSL handshake,
либо пустую строку (1.21.4); $ssl_cipher
- возвращает название используемого шифра для установленного SSL-соединения;
$ssl_ciphers
-
возвращает список шифров, поддерживаемых клиентом (1.11.7).
Известные шифры указаны по имени, неизвестные указаны в шестнадцатеричном виде,
например:AES128-SHA:AES256-SHA:0x00ff
Переменная полностью поддерживается при использовании OpenSSL версии 1.0.2
и выше.
При использовании более старых версий переменная доступна
только для новых сессий и может содержать только известные шифры. $ssl_client_escaped_cert
-
возвращает клиентский сертификат в формате PEM
(закодирован в формате urlencode) для установленного SSL-соединения (1.13.5); $ssl_client_cert
-
возвращает клиентский сертификат
для установленного SSL-соединения в формате PEM
перед каждой строкой которого, кроме первой, вставляется символ табуляции;
предназначена для использования в директиве
proxy_set_header;Переменная устарела, вместо неё следует использовать
переменную$ssl_client_escaped_cert
. $ssl_client_fingerprint
-
возвращает SHA1-отпечаток клиентского сертификата
для установленного SSL-соединения (1.7.1); $ssl_client_i_dn
-
возвращает строку “issuer DN” клиентского сертификата
для установленного SSL-соединения согласно
RFC 2253 (1.11.6); $ssl_client_i_dn_legacy
-
возвращает строку “issuer DN” клиентского сертификата
для установленного SSL-соединения;До версии 1.11.6 переменная называлась
$ssl_client_s_dn
. $ssl_client_raw_cert
-
возвращает клиентский сертификат
для установленного SSL-соединения в формате PEM; $ssl_client_s_dn
-
возвращает строку “subject DN” клиентского сертификата
для установленного SSL-соединения согласно
RFC 2253 (1.11.6); $ssl_client_s_dn_legacy
-
возвращает строку “subject DN” клиентского сертификата
для установленного SSL-соединения;До версии 1.11.6 переменная называлась
$ssl_client_s_dn
. $ssl_client_serial
-
возвращает серийный номер клиентского сертификата
для установленного SSL-соединения; $ssl_client_v_end
- возвращает дату окончания срока действия клиентского сертификата (1.11.7);
$ssl_client_v_remain
-
возвращает число дней,
оставшихся до истечения срока действия клиентского сертификата (1.11.7); $ssl_client_v_start
- возвращает дату начала срока действия клиентского сертификата (1.11.7);
$ssl_client_verify
-
возвращает результат проверки клиентского сертификата:
“SUCCESS
”, “FAILED:
reason
”
и, если сертификат не был предоставлен, “NONE
”;До версии 1.11.7 результат “
FAILED
”
не содержал строкуreason
. $ssl_curve
-
возвращает согласованную кривую, использованную для
обмена ключами во время операции SSL handshake (1.21.5).
Известные кривые указаны по имени, неизвестные указаны в шестнадцатеричном виде,
например:prime256v1
Переменная поддерживается при использовании OpenSSL версии 3.0 и выше.
При использовании более старых версий значением переменной будет пустая строка. $ssl_curves
-
возвращает список кривых, поддерживаемых клиентом (1.11.7).
Известные кривые указаны по имени, неизвестные указаны в шестнадцатеричном виде,
например:0x001d:prime256v1:secp521r1:secp384r1
Переменная поддерживается при использовании OpenSSL версии 1.0.2 и выше.
При использовании более старых версий значением переменной будет пустая строка.Переменная доступна только для новых сессий.
$ssl_early_data
-
возвращает “
1
”, если
используется TLS 1.3 early data
и операция handshake не завершена, иначе “” (1.15.3). $ssl_protocol
- возвращает протокол установленного SSL-соединения;
$ssl_server_name
-
возвращает имя сервера, запрошенное через
SNI
(1.7.0); $ssl_session_id
- возвращает идентификатор сессии установленного SSL-соединения;
$ssl_session_reused
-
возвращает “
r
”, если сессия была использована повторно,
иначе “.
” (1.5.11).
I have to add ssl (https) for a website, I was given a SSL.CSR and a SSL.KEY file. I ‘dos2unix’ed them (because they have trailing ^M) and copied them to the server(CSR -> mywebsite.crt, KEY -> mywebsite.key). I did the following modification to nginx.conf:
@@ -60,8 +60,13 @@
}
server {
- listen 80;
+ listen 443;
server_name ...;
+ ssl on;
+ ssl_certificate mywebsite.crt;
+ ssl_certificate_key mywebsite.key;
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_timeout 10m;
# Set the max size for file uploads to 500Mb
client_max_body_size 500M;
Error happens when I restart nginx:
nginx: [emerg] PEM_read_bio_X509_AUX("/etc/nginx/mywebsite.crt") failed (SSL: error:0906D06C:PEM routines:PEM_read_bio:no start line:Expecting: TRUSTED CERTIFICATE)
I figure it’s because the first line of mywebsite.crt file contains ‘REQUEST’, so I remove ‘REQUEST’ from the first and last of the lines, and restart nginx again, and hit another error:
nginx: [emerg] PEM_read_bio_X509_AUX("/etc/nginx/mywebsite.crt") failed (SSL: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:Field=algorithm, Type=X509_ALGOR error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:Field=signature, Type=X509_CINF error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:Field=cert_info, Type=X509 error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib)
Any idea?
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с Nginx. В этом процессе я столкнулся с несколькими проблемами, которые я опишу ниже, может кому то это поможет избежать подобных проблем.
И так первым делом я заказал новый сертификат у провайдера. Мне пообещали что он будет выпущен в течение 3 дней – 7 дней. Но прошло 7 дней а сертификата все нет и нет и каких либо сообщений об ошибках я то же ни получал. Я начал выяснять в чем может быть проблема. Обращение в тех. поддержку провайдера не помогло. Пришлось потратить несколько дней на поиск проблемы. Оказалось что если в доменной зоне существует хотя бы одна DNS запись типа CAA то сертификат может выдать только тот провайдер который прописан в этой записи. Я совсем забыл что год назад я создал эту запись для другого провайдера. В итоге создал новую запись CAA для нового провайдера, и сертификат пришел в течение дня по электронной почте.
Далее все просто, первым делом создадим текстовый файл your_domain.crt, который будет объединять три сертификата (сам SSL-сертификат, корневой и промежуточный сертификаты) в один файл. Поочередно скопируем и вставим в созданный документ каждый сертификат из электронного письма. После вставки всех сертификатов файл должен иметь вид:
-----BEGIN CERTIFICATE-----
#Ваш сертификат#
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
#Промежуточный сертификат#
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
#Корневой сертификат#
-----END CERTIFICATE-----
Далее создадим файл your_domain.key и скопируйте в него содержание приватного ключа сертификата так же из этого электронного письма.
В процессе этих действий я не заметил как совершил ошибку в одном из этих файлов, поэтому когда позже я попытался использовать эти сертификаты у меня ничего не получилось. В логе Ngnix я нашел следующую ошибку:
nginx: [emerg] SSL_CTX_use_PrivateKey_file(“/etc/ssl/your_domain.key”) failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)
Основная причина этого сообщения об ошибке заключается в том, что закрытый ключ и сертификат не совпадают при попытке включить SSL в nginx. Чтобы проверить закрытый и открытый ключи, nginx сравнивает modulus каждого из них. Если они не совпадают, вы получите эту ошибку.
Получить modulus закрытого ключа (передав его через md5sum) можно следующей командой:
$ sudo openssl rsa -modulus -in /etc/ssl/your_domain.key -noout | md5sum
d41d8cd54f00b204e9800978ecf8427e -
И сравнить его с modulus из сертификата:
$ sudo openssl x509 -modulus -in /etc/ssl/your_domain.crt -noout | md5sum
f3a2f9186fcdcdf0d2235236f2ee9a26 -
Как видите, в моем случае дайджесты оказались разные. Получается как будто сертификат сгенерированный из другого ключа. Но также, эта ошибка возможна из-за неверного порядка следования сертификатов в файле crt, так как modulus будет рассчитываться из первого сертификата, найденного в файле.
После этого я еще раз все проверил, нашел ошибку в сертификате и после того как поправил ее все заработало.
Далее приведу минимальные настройки Nginx для установки сертификата:
server {
listen 443 ssl;
server_name your_domain.com;
ssl_certificate /etc/ssl/your_domain.crt;
ssl_certificate_key /etc/ssl/your_domain.key;
}
Я это обычно не использую более расширенные настройки SSL, но если вы хотите дополнительно оптимизировать работу Nginx HTTPS-сервера, можно внести следующие настройки. SSL-операции задействуют дополнительные ресурсы сервера. Чтобы снизить количество операций, можно повторно использовать параметры SSL-сессий. Они хранятся в кеше SSL-сессий. Можно задать тип кеша (в примере это shared-кеш, разделяемый между всеми рабочими процессами) и его размер в байтах (в 1 Мб кеша помещается около 4000 сессий) с помощью директивы ssl_session_cache. Также можно увеличить таймаут кеша (время, в течение которого клиент повторно использует параметры сессии) директивой ssl_session_timeout: по умолчанию он равен 5 минутам. Можно настроить время работы одного keepalive-соединения с помощью директивы keepalive_timeout.
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
keepalive_timeout 70;
Можно дополнительно указать протоколы SSL, которые поддерживает сервер:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Чтобы при использовании протоколов SSLv3 и TLS серверные шифры были более приоритетны, чем клиентские, можно добавить следующую строку:
ssl_prefer_server_ciphers on;
Чтобы уменьшить время загрузки страниц у пользователей сайта, нужно разрешить серверу прикреплять OCSP-ответы для валидации сертификата. При этом необходимо указать путь к файлу корневого сертификата и DNS-сервер. Для этого создайте файл ca.crt и скопируйте в него содержимое корневого сертификата. Загрузите этот файл на сервер в директорию, где хранятся ранее созданные файлы. В нашем примере это /etc/ssl/. Затем добавьте в конфигурационном файле в секции server{} строки:
ssl_stapling on;
ssl_trusted_certificate /etc/ssl/ca.crt;
resolver 8.8.8.8;
Ну и в конце правок конечно же не забываем перезагрузить сервер Nginx:
$ sudo /etc/init.d/nginx restart
Была ли вам полезна эта статья?
SSL certificate renewals can be messy.
The PEM files won’t work, Nginx cannot find the cert, and the green light won’t turn on no matter what you do.
You are not alone.
Hundreds of Nginx owners face SSL certificate renewal issues everyday, and here at Bobcares, our Support Engineers help them fix it in a jiffy.
We provide 100% transparent end-customer support to web hosts, digital marketers and VPS hosting providers. Their customers raise tech support requests in their help desk, and our experts resolve it for them.
A lot of these customers use Nginx as their web server, and SSL cert renewal is a common issue we troubleshoot.
Today we’ll look at the top 5 issues reported by Nginx users, and how we resolve them:
1. Let’s Encrypt renewal command breaks
Many Nginx server owners these days use Let’s Encrypt as their certificate provider.
LetsEncrypt provides a way to renew SSL certificates using various command line tools, such as CertBot
.
We’ve seen these reasons for CertBot based renewal to fail:
– Wrong WebRoot specified in renew command
CertBot uses a command line options called “WebRoot” to know where it should store the new certificates.
In newly migrated websites, or those that were updated recently, we’ve seen this setting to be wrong, causing the renewal to fail.
We adjust the CertBot settings to match the current website configuration to fix this error.
– “.well-known” folder deleted or wrong permissions set
CertBot uses a folder called “.well-known” in the website document root to check the authenticity of a request.
In many websites we’ve seen this folder with wrong permissions or missing altogether (possibly due to a security cleanup or a migration error). Restoring this folder quickly resolve this issue.
– HTTP authorization set for .well-known folder
Some sites setup an additional layer of security by protecting “.well-known” folder with .htaccess authentication.
This will break the command line based renewal process. So, in these sites, we disable HTTP authentication until the renewal is complete.
Of course, there are other errors as well related to CertBot based renewal.
That is because the renewal process goes through a complex sequence of steps, which includes auto-generating a CSR, contacting the LE servers using ACME protocol, passing the auth test using .well-known folder, setting up the certificates in the right folder, and successfully restarting the Nginx servers.
If any step in this sequence fails for some reason, the renewal fails.
So, there isn’t a real one-size-fit-all-solution. Instead, our Support Engineers gather evidence from the LetsEncrypt log file (/var/log/letsencrypt/letsencrypt.log), and systematically rule out each possibility to zero in on the root cause.
2. Old SSL shows up even after an update
Sure, SSL renewals can be tricky, but the most confusing of all is when after a successful renewal, the browser still shows the old expired SSL.
You’d think Nginx is doing that out of spite. But no, there are perfectly logical reasons for that.
Here are a few common causes:
– Cert uploaded to the wrong location
We’ve seen many cases where customers use old or incompatible renewal steps to upload new certificates.
It usually happens after a recent app upgrade, site migration or server upgrade.
In these cases the new certificates get stored in a folder that’s not Nginx’s certificate path.
To resolve this error, we look at the Nginx configuration files for the cert path, and then check if the new files are uploaded to this location.
– New certificate not uploaded in gateway server
In some web configurations, the Nginx server sits behind a load-balancer or a caching server.
So, it is not enough to upload the new certificate in the Nginx server. It should be uploaded to the front end servers as well.
Many site owners miss this step, leading to renewal errors.
– Nginx reload failed
There are times when Nginx won’t completely restart. The old process still keeps serving the old certificate from memory.
If we suspect a runaway Nginx process, we force kill it, and restart the service to fix this issue.
3. Intermediate certificates are built wrong or are corrupted
A pet peeve of Nginx users is Nginx’s inability to recognize intermediate certificates (aka cert bundles, aka certificate chain).
Instead, users are required to put their site certificate and all intermediate certificates into one file in the right order, and then point it to the “ssl_certificate” configuration option.
Yeah, it sounds complicated, and it sure is complicated for someone not used to tinkering with server backend.
That is why many webmasters see the error “Site Not Trusted” even after an apparently successful upgrade.
Almost all of these errors are caused by incorrect copy-paste of certificate data into the files. Some characters would be missing, or the certs will be pasted one on top of another.
All that cause cause the cert file to be corrupted, and connecting browsers will be unable to complete a successful verification.
We fix this by programmatically merging the Site Cert and Chain Cert so that there are not manual errors.
4. Forbidden errors while running cert renew
These days one cannot be too paranoid.
That is why some server administration panels like Plesk provide a way to block all access to hidden directories (ones that start with a period [ . ] ).
It is a measure to protect sensitive information some apps store in hidden directories.
Unfortunately, automatic cert installers such as Let’s Encrypt’s CertBot use hidden folders (/path/to/docroot/.well-known) for user validation.
Such validation measures will fail if hidden folder protection is enabled.
So, when we see a “403 Forbidden” error message in the cert renewal log files, we look for such security restrictions, and remove it until the new certificate is installed.
5. Nginx crashes (does not start) after certificate renewal
The most urgent issues often relate to crashed Nginx servers after a failed upgrade.
Some auto-installers are capable of changing configuration entries, but if the installer fails for some reason, it will break the Nginx configuration file.
In such cases, we restore the Nginx configuration file from backup to quickly get the site back online.
If a backup isn’t available, we get the site online by resetting the SSL configuration section that most automated tools target.
Once the site is back online, we make the changes manually to bring the new certificate online.
Conclusion
Certificate renewals can be a hassle. Today we’ve seen the top 5 issues that are reported by Nginx users while renewing SSL, and how our Support Engineers fix them.
PREVENT YOUR SERVER FROM CRASHING!
Never again lose customers to poor server speed! Let us help you.
Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.
SEE SERVER ADMIN PLANS
var google_conversion_label = «owonCMyG5nEQ0aD71QM»;