Використання openssl для отримання сертифіката від сервера


353

Я намагаюся отримати сертифікат віддаленого сервера, який я потім можу використовувати, щоб додати до мого магазину ключів і використовувати в моєму додатку 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, але він, здається, не допомагає. Я спробував кілька шляхів безрезультатно.

Будь ласка, дайте мені знати, де я помиляюся.

Відповіді:


461

З СНІ

Якщо віддалений сервер використовує SNI (тобто обмін декількома хостами SSL на одній IP-адресі), вам потрібно буде надіслати правильне ім’я хоста, щоб отримати потрібний сертифікат.

openssl s_client -showcerts -servername www.example.com -connect www.example.com:443 </dev/null

Без СНІ

Якщо віддалений сервер не використовує 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

3
Хм. Я все одно отримую ту саму помилку при спробі цієї команди. Я помітив, що моя версія Openssl - це OpenSSL 0.9.8g 19 жовтня 2007 року. У вас є ідеї?
бридкий пастоз

39
Корисне: echo "" | openssl s_client -connect server:port -prexit 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' stackoverflow.com/a/12918442/843000
mbrownnyc

16
Альтернативний корисний сценарій, з madboa.com :echo | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
rmeakins

9
Для того, щоб зробити це трохи більш коротким, ви можете замінити sedз openssl x509, і читати його в використанні подоболочкі:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
Гейб Martin-Dempesy

27
Такожecho | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
MattSizzle

68

Хоча я згоден з відповіддю Арі (і підтримав це :), мені потрібно було зробити додатковий крок, щоб змусити його працювати з 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-сертифікати з keytool для Windows з Java 6 і жодного разу не стикався з проблемою.
imgx64

39

Виявляється, тут є більше складності: мені потрібно було надати ще багато деталей, щоб отримати цю інформацію. Я думаю, що це щось пов’язане з тим, що його з'єднання, яке потребує аутентифікації клієнта, і рукоятці потребують додаткової інформації, щоб продовжувати етап, де сертифікати скидалися.

Ось моя робоча команда:

openssl s_client -connect host:port -key our_private_key.pem -showcerts \
                 -cert our_server-signed_cert.pem

Сподіваємось, це підштовхування в правильному напрямку для кожного, хто міг би зробити трохи більше інформації.


6
Мені дуже шкода, але ваша відповідь не має великого сенсу. Вам потрібно було передати сертифікат на сервер, щоб отримати сертифікат?
Арі Маніатіс

2
Так. Аутентифікація клієнта AFAIK.
бридкий пастоз

11
Виявляється, «-prexit» також поверне ці дані. Наприклад; openssl s_client -connect хост: порт -prexit
Роберт

39

Одноланковий витяг сертифіката з віддаленого сервера у форматі PEM, на цей раз за допомогою sed:

openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

2
Цей майже ідеальний для вилучення сертифіката, просто пропущений -servernameваріант, не знаю чому, але мені довелося використовувати його, щоб отримати повний сертифікат.
Karl.S

- ім'я сервера потрібно для вказівки імені сервера (SNI). Пошук у Інтернеті може розширитися на решті.
Сем Глеске

32

Найпростіший для цього командний рядок, який включає вихід PEM для додавання його до сховища ключів, а також читаний людиною вихід, а також підтримує SNI, що важливо, якщо ви працюєте з сервером HTTP:

openssl s_client -servername example.com -connect example.com:443 \
    </dev/null 2>/dev/null | openssl x509 -text

Варіант -sername полягає в тому, щоб увімкнути підтримку SNI, і openssl x509 -text друкує сертифікат у читаному для людини форматі.


Ви можете додати до -менного імені свій піддомен, наприклад, ws.example.com замість example.com (застосуйте це також до параметра -connect).
russellhoff

24

Щоб отримати сертифікат віддаленого сервера, ви можете скористатися 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 ви можете двічі клацнути по файлу або перетягнути його в Keychain Access, щоб він відображався у вході / сертифікатах. Потім двічі клацніть на імпортованому сертифікованому і зробіть його завжди довіреним для 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.


12
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

6

друкувати тільки ланцюжок сертифікатів, а не сертифікат сервера:

# 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

Саме те, що мені було потрібно в CentOS7. Дякую!
Артур Геберт

5

Ви можете отримати та зберегти кореневий сертифікат сервера, використовуючи наступний скрипт 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'") }'

Просто перезапишіть потрібні змінні.


4

Якщо ваш сервер - сервер електронної пошти (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)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.