Проблема в том, что openssl -verify
это не работает.
Как упоминал Прияди , openssl -verify
останавливается на первом самоподписанном сертификате, поэтому вы на самом деле не проверяете цепочку, так как часто промежуточный сертификат самозаверяющий.
Я предполагаю, что вы хотите быть на 101% уверены, что файлы сертификатов верны, прежде чем пытаться установить их в продуктивной веб-службе. Этот рецепт выполняет именно эту предполетную проверку.
Обратите внимание, что ответ Питера правильный , однако вывод openssl -verify
не указывает на то, что после этого все действительно работает. Да, могут возникнуть некоторые проблемы, но не все.
Вот сценарий, который проверяет цепочку сертификатов перед ее установкой в Apache. Возможно, это можно улучшить с помощью более мистической магии OpenSSL, но я не гуру OpenSSL и следующие работы:
#!/bin/bash
# This Works is placed under the terms of the Copyright Less License,
# see file COPYRIGHT.CLL. USE AT OWN RISK, ABSOLUTELY NO WARRANTY.
#
# COPYRIGHT.CLL can be found at http://permalink.de/tino/cll
# (CLL is CC0 as long as not covered by any Copyright)
OOPS() { echo "OOPS: $*" >&2; exit 23; }
PID=
kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; }
trap 'kick' 0
serve()
{
kick
PID=
openssl s_server -key "$KEY" -cert "$CRT" "$@" -www &
PID=$!
sleep .5 # give it time to startup
}
check()
{
while read -r line
do
case "$line" in
'Verify return code: 0 (ok)') return 0;;
'Verify return code: '*) return 1;;
# *) echo "::: $line :::";;
esac
done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/)
OOPS "Something failed, verification output not found!"
return 2
}
ARG="${1%.}"
KEY="$ARG.key"
CRT="$ARG.crt"
BND="$ARG.bundle"
for a in "$KEY" "$CRT" "$BND"
do
[ -s "$a" ] || OOPS "missing $a"
done
serve
check && echo "!!! =========> CA-Bundle is not needed! <========"
echo
serve -CAfile "$BND"
check
ret=$?
kick
echo
case $ret in
0) echo "EVERYTHING OK"
echo "SSLCertificateKeyFile $KEY"
echo "SSLCertificateFile $CRT"
echo "SSLCACertificateFile $BND"
;;
*) echo "!!! =========> something is wrong, verification failed! <======== ($ret)";;
esac
exit $ret
Обратите внимание, что вывод после EVERYTHING OK
- это настройка Apache, потому что люди, использующие NginX
или haproxy
обычно могут читать и понимать это в совершенстве;)
Существует GitHub Gist, в котором могут быть некоторые обновления
Предпосылки для этого скрипта:
- У вас есть данные доверенного корневого центра сертификации,
/etc/ssl/certs
как обычно, например, в Ubuntu
- Создайте каталог, в
DIR
котором вы храните 3 файла:
DIR/certificate.crt
который содержит сертификат
DIR/certificate.key
который содержит секретный ключ для вашего веб-сервиса (без парольной фразы)
DIR/certificate.bundle
который содержит CA-Bundle. О том, как подготовить связку, читайте ниже.
- Теперь запустите скрипт:
./check DIR/certificate
(предполагается, что скрипт назван check
в текущем каталоге)
- Это очень маловероятный случай, когда скрипт выводит
CA-Bundle is not needed
. Это означает, что вы (читайте /etc/ssl/certs/
:) уже доверяете сертификату подписи. Но в WWW это маловероятно.
- Для этого тестового порта 4433 не должен использоваться на вашей рабочей станции. И лучше запускать это только в безопасной среде, поскольку он вскоре откроет порт 4433 для публики, которая может увидеть внешние подключения во враждебной среде.
Как создать certificate.bundle
файл?
В WWW цепочка доверия обычно выглядит так:
- доверенный сертификат от
/etc/ssl/certs
- неизвестные промежуточные сертификаты, возможно, перекрестно подписанные другим ЦС
- ваш сертификат (
certificate.crt
)
Теперь оценка происходит снизу вверх, это означает, что сначала ваш сертификат считывается, затем требуется неизвестный промежуточный сертификат, затем, возможно, сертификат с перекрестной подписью, а затем /etc/ssl/certs
проводится консультация для поиска правильного доверенного сертификата.
Пакет ca-bundle должен быть составлен в точном соответствии с правильным порядком обработки, это означает, что первый необходимый сертификат (промежуточный сертификат, который подписывает ваш сертификат) идет первым в пакете. Тогда потребуется сертификат с перекрестной подписью.
Обычно ваш CA (орган, подписавший ваш сертификат) уже предоставляет такой правильный файл ca-bundle. Если нет, вам нужно собрать все необходимые промежуточные сертификаты и cat
их вместе в один файл (в Unix). В Windows вы можете просто открыть текстовый редактор (например, notepad.exe
) и вставить сертификаты в файл, первый из которых должен быть поверх остальных, а после остальных.
Есть еще кое-что. Файлы должны быть в формате PEM. Некоторые центры сертификации выдают формат DER (двоичный). PEM легко обнаружить: он читается в кодировке ASCII. Подробнее о том, как преобразовать что-либо в PEM, см. В разделе Как преобразовать .crt в .pem и следовать по дороге из желтого кирпича.
Пример:
У тебя есть:
intermediate2.crt
промежуточный сертификат, который подписал ваш certificate.crt
intermediate1.crt
еще один промежуточный сертификат, который подписал intermediate2.crt
crossigned.crt
который является сертификатом перекрестной подписи от другого центра сертификации, который подписал intermediate1.crt
crossintermediate.crt
который является еще одним промежуточным звеном от другого подписанного CA crossigned.crt
(вы, вероятно, никогда не увидите такого)
Тогда правильный cat
будет выглядеть так:
cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle
А как узнать, какие файлы нужны или нет и в какой последовательности?
Что ж, экспериментируйте, пока check
все в порядке. Это похоже на компьютерную головоломку, в которой нужно разгадывать загадку. Каждый. Не замужем. Время. Даже для профи. Но каждый раз, когда вам нужно это делать, вы будете поправляться. Так что вы определенно не одиноки со всей этой болью. Это SSL, понимаешь? SSL, вероятно, является одним из худших проектов, которые я когда-либо видел за более чем 30 лет профессионального системного администрирования. Вы когда-нибудь задумывались, почему криптовалюта не стала мейнстримом за последние 30 лет? Поэтому. 'достаточно.
man verify
, я обнаружил, что этот-untrusted
параметр является правильным для использования при указании промежуточного сертификата.