Sử dụng openssl để lấy chứng chỉ từ máy chủ


354

Tôi đang cố lấy chứng chỉ của một máy chủ từ xa, sau đó tôi có thể sử dụng để thêm vào kho khóa của mình và sử dụng trong ứng dụng java của mình.

Một nhà phát triển cấp cao (đang trong kỳ nghỉ :() thông báo cho tôi rằng tôi có thể chạy cái này:

openssl s_client -connect host.host:9999

Để có được một chứng chỉ thô được đổ ra, sau đó tôi có thể sao chép và xuất. Tôi nhận được đầu ra sau:

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:

Tôi cũng đã thử với tùy chọn này

-showcerts 

và cái này (chạy trên tâm trí debian bạn)

-CApath /etc/ssl/certs/ 

Nhưng nhận được cùng một lỗi.

Nguồn này nói rằng tôi có thể sử dụng cờ CApath đó nhưng dường như không có ích. Tôi đã thử nhiều đường dẫn nhưng không có kết quả.

Xin vui lòng cho tôi biết tôi đang đi sai ở đâu.

Câu trả lời:


463

Với SNI

Nếu máy chủ từ xa đang sử dụng SNI (nghĩa là chia sẻ nhiều máy chủ SSL trên một địa chỉ IP), bạn sẽ cần gửi đúng tên máy chủ để có được chứng chỉ phù hợp.

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

Không có SNI

Nếu máy chủ từ xa không sử dụng SNI, thì bạn có thể bỏ qua -servernametham số:

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


Để xem chi tiết đầy đủ về chứng chỉ của trang web, bạn cũng có thể sử dụng chuỗi lệnh này:

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

3
Hừm. Tôi vẫn nhận được lỗi tương tự khi thử lệnh đó. Tôi nhận thấy phiên bản Openssl của mình là 'OpenSSL 0.9.8g ngày 19 tháng 10 năm 2007'. Bạn có bất cứ ý tưởng?
pasty khó chịu

39
Hữu ích: 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
Kịch bản hữu ích thay thế, từ madboa.com :echo | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
rmeakins

9
Để làm cho điều này ngắn gọn hơn một chút, bạn có thể thay thế sedbằng openssl x509và đọc nó bằng cách sử dụng lớp vỏ phụ:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
Gabe Martin-Dempesy

27
Ngoài raecho | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
MattSizzle

68

Mặc dù tôi đồng ý với câu trả lời của Ari (và nâng cấp nó :), tôi cần thực hiện thêm một bước để làm cho nó hoạt động với Java trên Windows (nơi cần triển khai):

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

Trước khi thêm openssl x509 -outform DERchuyển đổi, tôi đã gặp lỗi từ keytool trên Windows phàn nàn về định dạng của chứng chỉ. Nhập tệp .der hoạt động tốt.


Lạ Tôi đã sử dụng chứng chỉ PEM với keytool trên Windows kể từ Java 6 và chưa bao giờ gặp sự cố.
imgx64

39

Hóa ra có sự phức tạp hơn ở đây: Tôi cần cung cấp nhiều chi tiết hơn để có được sự lăn lộn này. Tôi nghĩ đó là một cái gì đó để làm với thực tế là một kết nối cần xác thực ứng dụng khách và hankshake cần thêm thông tin để tiếp tục đến giai đoạn mà các chứng chỉ bị hủy bỏ.

Đây là lệnh làm việc của tôi:

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

Hy vọng rằng đây là một bước đi đúng hướng cho bất cứ ai có thể làm với một số thông tin thêm.


6
Tôi xin lỗi, nhưng câu trả lời của bạn không có nhiều ý nghĩa. Bạn cần phải chuyển chứng chỉ đến máy chủ để lấy chứng chỉ?
Ari Maniatis

2
Vâng. Xác thực khách hàng AFAIK.
pasty khó chịu

11
Hóa ra '-prexit' cũng sẽ trả lại dữ liệu đó. Ví dụ; openssl s_client -connect host: port -prexit
Robert

39

Một lớp lót để trích xuất chứng chỉ từ máy chủ từ xa ở định dạng PEM, lần này sử dụng sed:

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

2
Cái này gần như hoàn hảo để trích xuất chứng chỉ, chỉ thiếu -servernametùy chọn, không biết tại sao, nhưng tôi phải sử dụng nó để có được chứng chỉ đầy đủ.
Karl.S

-servername là bắt buộc để chỉ định tên máy chủ (SNI). Tìm kiếm trên web có thể mở rộng trên phần còn lại.
Sam Gleske

32

Dòng lệnh dễ nhất cho việc này, bao gồm đầu ra PEM để thêm nó vào kho khóa, cũng như đầu ra có thể đọc được của con người và cũng hỗ trợ SNI, điều này rất quan trọng nếu bạn đang làm việc với máy chủ HTTP là:

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

Các -servername lựa chọn là để cho phép hỗ trợ SNI và openssl x509 -văn bản in giấy chứng nhận ở định dạng có thể đọc được của con người.


Bạn có thể thêm vào -servername tên miền phụ của bạn, ví dụ ws.example.com thay vì example.com (áp dụng điều này cho tham số -connect quá).
russellhoff

24

Để có được chứng chỉ của máy chủ từ xa, bạn có thể sử dụng opensslcông cụ và bạn có thể tìm thấy nó giữa BEGIN CERTIFICATEEND CERTIFICATEbạn cần sao chép và dán vào tệp chứng chỉ của mình (CRT).

Đây là lệnh chứng minh điều đó:

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

Để trả lại tất cả các chứng chỉ từ chuỗi, chỉ cần thêm g(toàn cầu) như:

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

Sau đó, bạn có thể chỉ cần nhập tệp chứng chỉ ( file.crt) vào móc khóa của mình và làm cho nó đáng tin cậy, vì vậy Java không nên phàn nàn.

Trên OS X, bạn có thể nhấp đúp vào tệp hoặc kéo và thả trong Quyền truy cập Keychain, vì vậy nó sẽ xuất hiện trong thông tin đăng nhập / Chứng chỉ. Sau đó nhấp đúp chuột vào chứng nhận đã nhập và làm cho nó Luôn tin tưởng cho SSL .

Trên CentOS 5, bạn có thể nối chúng vào /etc/pki/tls/certs/ca-bundle.crttệp (và chạy sudo update-ca-trust force-enable:) hoặc trong CentOS 6 sao chép chúng vào /etc/pki/ca-trust/source/anchors/và chạy sudo update-ca-trust extract.

Trong Ubuntu, sao chép chúng vào /usr/local/share/ca-certificatesvà chạy 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

chỉ in chuỗi chứng chỉ chứ không phải chứng chỉ của máy chủ:

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

để cập nhật niềm tin CA trên 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

trên 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

Chính xác những gì tôi cần trên CentOS7. Cảm ơn!
Arthur Hebert

5

Bạn có thể nhận và lưu trữ chứng chỉ gốc của máy chủ bằng cách sử dụng tập lệnh bash tiếp theo:

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

Chỉ cần ghi đè các biến cần thiết.


4

Nếu máy chủ của bạn là máy chủ email (MS Exchange hoặc Zimbra), có thể bạn cần thêm starttlssmtpcờ:

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

Ở đâu,

  • HOST_EMAIL là miền máy chủ, ví dụ: mail-server.com.

  • SECURE_PORT là cổng giao tiếp, ví dụ: 587 hoặc 465

  • Tên tệp đầu ra của CERTIFICATE_NAME (Định dạng BASE 64 / PEM)


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.