Использование openssl для получения сертификата с сервера
Я пытаюсь получить сертификат удаленного сервера, который затем могу использовать для добавления в хранилище ключей и использования в моем приложении Java.
Старший разработчик (который в отпуске:() сообщил мне, что я могу запустить это:
openssl s_client -connect host.host:9999
Чтобы получить необработанный сертификат, который я могу затем скопировать и экспортировать. Я получаю следующий вывод:
depth=1 /C=NZ/ST=Test State or Province/O=Organization Name/OU=Organizational Unit Name/CN=Test CA
verify error:num=19:self signed certificate in certificate chain
verify return:0
23177:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1086:SSL alert number 40
23177:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:
Я также пытался с этой опцией
-showcerts
и этот (работает на Debian)
-CApath /etc/ssl/certs/
Но получите ту же ошибку.
Этот источник говорит, что я могу использовать этот флаг CApath, но он, похоже, не помогает. Я пробовал несколько путей безрезультатно.
Пожалуйста, дайте мне знать, где я иду не так.
15 ответов
Оказывается, здесь сложнее: мне нужно было предоставить гораздо больше подробностей, чтобы начать работу. Я думаю, что это как-то связано с тем, что это соединение, которое требует аутентификации клиента, и hankshake требовалось больше информации, чтобы перейти к этапу, когда сертификаты были сброшены.
Вот моя рабочая команда:
openssl s_client -connect host:port -key our_private_key.pem -showcerts \
-cert our_server-signed_cert.pem
Надеюсь, это толчок в правильном направлении для тех, кто мог бы получить больше информации.
С SNI
Если удаленный сервер использует SNI (то есть разделяет несколько хостов SSL на одном IP-адресе), вам необходимо отправить правильное имя хоста, чтобы получить правильный сертификат.
openssl s_client -showcerts -servername www.example.com -connect www.example.com:443 </dev/null
Без SNI
Если удаленный сервер не использует SNI, вы можете пропустить -servername
параметр:
openssl s_client -showcerts -connect www.example.com:443 </dev/null
Чтобы просмотреть полную информацию о сертификате сайта, вы также можете использовать эту цепочку команд:
$ echo | \
openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null | \
openssl x509 -text
Однострочник для извлечения сертификата с удаленного сервера в формате PEM, на этот раз с использованием sed
:
openssl s_client -connect www.google.com:443 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
Хотя я согласен с ответом Ари (и проголосовал за него:), мне нужно было сделать дополнительный шаг, чтобы заставить его работать с Java на Windows (где его нужно было развернуть):
openssl s_client -showcerts -connect www.example.com:443 < /dev/null | openssl x509 -outform DER > derp.der
Перед добавлением openssl x509 -outform DER
Я получил сообщение об ошибке от keytool в Windows с жалобой на формат сертификата. Импорт файла.der работал нормально.
Самая простая командная строка для этого, которая включает вывод PEM для добавления его в хранилище ключей, а также вывод, читаемый человеком, а также поддерживает SNI, что важно, если вы работаете с сервером HTTP:
openssl s_client -servername example.com -connect example.com:443 \
</dev/null 2>/dev/null | openssl x509 -text
Параметр -servername включает поддержку SNI, а текст openssl x509 печатает сертификат в удобочитаемом формате.
Для получения сертификата удаленного сервера вы можете использовать openssl
инструмент, и вы можете найти его между BEGIN CERTIFICATE
а также END CERTIFICATE
который вам нужно скопировать и вставить в файл сертификата (CRT).
Вот команда, демонстрирующая это:
ex +'/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq > file.crt
Чтобы вернуть все сертификаты из цепочки, просто добавьте g
(глобальный) как:
ex +'g/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq
Тогда вы можете просто импортировать файл сертификата (file.crt
) в вашу связку ключей и сделайте ее доверенной, чтобы Java не жаловалась.
В OS X вы можете дважды щелкнуть файл или перетащить его в свой брелок для доступа, чтобы он появился в логине / сертификатах. Затем дважды щелкните по импортированному сертификату и сделайте его Always Trust for SSL.
На CentOS 5 вы можете добавить их в /etc/pki/tls/certs/ca-bundle.crt
файл (и запустить: sudo update-ca-trust force-enable
) или в CentOS 6 скопируйте их в /etc/pki/ca-trust/source/anchors/
и беги sudo update-ca-trust extract
,
В Ubuntu скопируйте их в /usr/local/share/ca-certificates
и беги sudo update-ca-certificates
,
HOST=gmail-pop.l.google.com
PORT=995
openssl s_client -servername $HOST -connect $HOST:$PORT < /dev/null 2>/dev/null | openssl x509 -outform pem
У меня тоже была такая же проблема, и рядом с этим я обнаружил, что openssl не возвращает корневой ca. Я создал альтернативу специально для этой цели, которая может быть полезна другим разработчикам, см. Здесь: GitHub - Certificate ripper
Применение
- Печать на консоль
crip print --url=https://stackoverflow.com/ --format=pem
- Экспорт в трубу p12
crip export --url=https://stackoverflow.com/
Распечатать только цепочку сертификатов, а не сертификат сервера:
# MYHOST=myhost.com
# MYPORT=443
# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}'
обновить доверие CA на CentOS/RHEL 6/7:
# update-ca-trust enable
# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}' >/etc/pki/ca-trust/source/anchors/myca.cert
# update-ca-trust extract
на CentOS/RHEL 5:
# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}' >>/etc/pki/tls/certs/ca-bundle.crt
Если ваш сервер является сервером электронной почты (MS Exchange или Zimbra), возможно, вам нужно добавить starttls
а также smtp
флаги:
openssl s_client -starttls smtp -connect HOST_EMAIL:SECURE_PORT 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > CERTIFICATE_NAME.pem
Где,
HOST_EMAIL - это домен сервера, например, mail-server.com.
SECURE_PORT - порт связи, например, 587 или 465
Имя выходного файлаCERTIFICATE_NAME (формат BASE 64/PEM)
Вы можете получить и сохранить корневой сертификат сервера, используя следующий bash-скрипт:
CERTS=$(echo -n | openssl s_client -connect $HOST_NAME:$PORT -showcerts | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p')
echo "$CERTS" | awk -v RS="-----BEGIN CERTIFICATE-----" 'NR > 1 { printf RS $0 > "'$SERVER_ROOT_CERTIFICATE'"; close("'$SERVER_ROOT_CERTIFICATE'") }'
Просто перезапишите обязательные переменные.
Уже есть хорошие ответы. Но стоит упомянуть, что последняя версия curl (>7.88.0) сделает это за вас просто...
curl https://example.com -w "%{certs}" -o /dev/null > cacert.pem
Добавлять--insecure
если сервер использует самоподписанный сертификат. И добавить--head
чтобы избежать тела ответа.
См. доступность и требования здесь:функция cURL -w certs
Запускаем клиент:
openssl s_client -showcerts stackoverflow.com:443
Выйдите, остановив STDIN (CTRL+D), или завершите процесс (CTRL+C).
Чтобы отключить ввод и принудительно завершить работу клиента после отображения сертификатов:
openssl s_client -showcerts stackoverflow.com:443 < /dev/null
В интересах других, таких как я, которые пытались следовать полезному совету при доступе к AWS CloudFront, но не смогли, хитрость заключается в том, чтобы добавить -servername domain.name..
,
Источник: /questions/43714703/regulyarnoe-vyirazhenie-dlya-zamenyi-atributa-xml/43714719#43714719
Я был в случае, когда два сертификата были выведены из вышеперечисленных команд; так что я дошел до этого момента, чтобы извлечь только 2-ю часть: сертификат сервера
Извините за длинную команду:
openssl s_client -servername token.actions.githubusercontent.com -showcerts -connect token.actions.githubusercontent.com:443 2>/dev/null </dev/null | awk '/BEGIN CERTIFICATE/ && c++,/END CERTIFICATE/'