Menggunakan openssl untuk mendapatkan sertifikat dari server

354

Saya mencoba untuk mendapatkan sertifikat server jauh, yang kemudian dapat saya gunakan untuk menambah keystore saya dan menggunakan dalam aplikasi java saya.

Seorang pengembang senior (yang sedang berlibur :() memberi tahu saya bahwa saya dapat menjalankan ini:

openssl s_client -connect host.host:9999

Untuk mendapatkan sertifikat mentah yang dibuang, yang kemudian dapat saya salin dan ekspor. Saya menerima output berikut:

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:

Saya juga sudah mencoba dengan opsi ini

-showcerts 

dan yang ini (berjalan di debian mind you)

-CApath /etc/ssl/certs/ 

Tapi dapatkan kesalahan yang sama.

Sumber ini mengatakan saya bisa menggunakan flag CApath itu tetapi sepertinya tidak membantu. Saya mencoba beberapa jalur tetapi tidak berhasil.

Tolong beri tahu saya di mana saya salah.

pucat jahat
sumber

Jawaban:

463

Dengan SNI

Jika server jarak jauh menggunakan SNI (yaitu, berbagi beberapa host SSL pada satu alamat IP), Anda harus mengirim nama host yang benar untuk mendapatkan sertifikat yang tepat.

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

Tanpa SNI

Jika server jarak jauh tidak menggunakan SNI, maka Anda dapat melewati -servernameparameter:

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


Untuk melihat detail lengkap dari sertifikat situs, Anda dapat menggunakan rantai perintah ini juga:

$ echo | \
    openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null | \
    openssl x509 -text
Ari Maniatis
sumber
3
Hmm. Saya masih mendapatkan kesalahan yang sama ketika mencoba perintah itu. Saya perhatikan versi Opensl saya adalah 'OpenSSL 0.9.8g 19 Okt 2007'. Apakah Anda punya ide?
pucat jahat
39
Berguna: 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
Naskah alternatif yang bermanfaat, dari madboa.com :echo | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
rmeakins
9
Untuk membuatnya lebih ringkas, Anda bisa menggantinya seddengan openssl x509, dan membacanya menggunakan sub-shell:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
Gabe Martin-Dempesy
27
Jugaecho | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
MattSizzle
68

Sementara saya setuju dengan jawaban Ari (dan meningkatkannya :), saya perlu melakukan langkah ekstra untuk membuatnya bekerja dengan Java pada Windows (di mana itu perlu digunakan):

openssl s_client -showcerts -connect www.example.com:443 < /dev/null | openssl x509 -outform DER > derp.der

Sebelum menambahkan openssl x509 -outform DERkonversi, saya mendapatkan kesalahan dari keytool pada Windows mengeluh tentang format sertifikat. Mengimpor file .der berfungsi dengan baik.

David Jaquay
sumber
Aneh. Saya telah menggunakan sertifikat PEM dengan keytool di Windows sejak Java 6 dan tidak pernah menghadapi masalah.
imgx64
39

Ternyata ada lebih banyak kompleksitas di sini: Saya perlu memberikan lebih banyak detail untuk mendapatkan rolling ini. Saya pikir ini ada hubungannya dengan fakta bahwa ini adalah koneksi yang memerlukan otentikasi klien, dan hankshake memerlukan lebih banyak info untuk melanjutkan ke tahap di mana sertifikat dibuang.

Ini perintah kerja saya:

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

Semoga ini adalah dorongan ke arah yang benar bagi siapa saja yang bisa melakukan dengan beberapa info lebih lanjut.

pucat jahat
sumber
6
Maaf, tapi jawaban Anda tidak masuk akal. Anda perlu meneruskan sertifikat ke server untuk mendapatkan sertifikat?
Ari Maniatis
2
Ya. Autentikasi klien AFAIK.
pasty jahat
11
Ternyata '-prexit' akan mengembalikan data itu juga. Misalnya; openssl s_client -connect host: port -prexit
Robert
39

Satu baris untuk mengekstrak sertifikat dari server jauh dalam format PEM, kali ini menggunakan sed:

openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
André Fernandes
sumber
2
Yang ini hampir sempurna untuk mengekstrak sertifikat, hanya melewatkan -servernameopsi, tidak tahu mengapa, tapi saya harus menggunakannya untuk mendapatkan sertifikat lengkap.
Karl.S
-servername diperlukan untuk indikasi nama server (SNI). Pencarian web dapat berkembang pada sisanya.
Sam Gleske
32

Baris perintah termudah untuk ini, yang mencakup output PEM untuk menambahkannya ke keystore, serta output yang dapat dibaca manusia dan juga mendukung SNI, yang penting jika Anda bekerja dengan server HTTP adalah:

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

The -servername pilihan adalah untuk mengaktifkan dukungan SNI dan openssl x509 -teks cetak sertifikat dalam format yang dapat dibaca manusia.

Florian
sumber
Anda dapat menambahkan -servername subdomain Anda, misalnya ws.example.com alih-alih example.com (terapkan ini pada parameter -connect juga).
russellhoff
24

Untuk mendapatkan sertifikat server jauh, Anda dapat menggunakan opensslalat dan Anda dapat menemukannya di antara BEGIN CERTIFICATEdanEND CERTIFICATE yang perlu Anda salin dan tempel ke file sertifikat (CRT) Anda.

Ini adalah perintah yang menunjukkannya:

ex +'/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq > file.crt

Untuk mengembalikan semua sertifikat dari rantai, cukup tambahkan g(global) seperti:

ex +'g/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq

Kemudian Anda cukup mengimpor file sertifikat Anda (file.crt ) ke gantungan kunci Anda dan membuatnya tepercaya, jadi Java tidak perlu mengeluh.

Pada OS X Anda dapat mengklik dua kali pada file atau seret dan lepas di Akses Keychain Anda, sehingga akan muncul di login / Sertifikat. Kemudian klik dua kali pada sertifikat yang diimpor dan membuatnya Selalu Percaya untuk SSL .

Pada CentOS 5 Anda dapat menambahkannya ke /etc/pki/tls/certs/ca-bundle.crtfile (dan menjalankan sudo update-ca-trust force-enable:), atau di CentOS 6 menyalinnya ke dalam /etc/pki/ca-trust/source/anchors/dan menjalankan sudo update-ca-trust extract.

Di Ubuntu, salin ke /usr/local/share/ca-certificatesdan jalankan sudo update-ca-certificates.

kenorb
sumber
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
akond
sumber
6

untuk mencetak hanya rantai sertifikat dan bukan sertifikat server:

# 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}'

untuk memperbarui kepercayaan CA pada 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

pada 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
Mathieu CARBONNEAUX
sumber
Persis apa yang saya butuhkan di CentOS7. Terima kasih!
Arthur Hebert
5

Anda bisa mendapatkan dan menyimpan sertifikat root server menggunakan skrip bash berikutnya:

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'") }'

Timpa saja variabel yang diperlukan.

Andrei Aleksandrov
sumber
4

Jika server Anda adalah server email (MS Exchange atau Zimbra) mungkin Anda perlu menambahkan starttlsdan smtpmenandai:

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

Dimana,

  • HOST_EMAIL adalah domain server, misalnya, mail-server.com.

  • SECURE_PORT adalah port komunikasi, misalnya, 587 atau 465

  • Nama file keluaran CERTIFICATE_NAME (Format BASE 64 / PEM)

SHoko
sumber