获取 SSL 服务器证书
1. 概述
当我们要调试HTTPS连接时,往往需要获取服务器证书。该证书在 SSL 握手发生时传输,因此我们有多种获取方式。
在本快速教程中,我们将了解如何使用 Web 浏览器或 OpenSSL 命令行实用程序获取服务器证书。
2. 使用网络浏览器
我们获得证书的最简单方法是通过网络浏览器。让我们看看如何在 Firefox 中做到这一点。
首先,让我们点击地址栏中的站点信息(锁定符号):
接下来,在连接详细信息菜单中,让我们点击更多信息:
现在,让我们点击查看证书:
在此之后,将打开一个新选项卡:
在这里,我们可以通过单击download字段中的链接,从杂项部分以PEM格式保存证书。
我们也可以从第二个环节得到完整的证书链。
3. 使用 OpenSSL
当我们无法访问浏览器时,我们也可以从命令行获取证书。
我们可以使用openssl s_client命令与我们的服务器建立交互式 SSL 连接:
$ openssl s_client -connect blogdemo.com:443
CONNECTED(00000003)
## # some debugging output
MIIE6DCCBI2gAwIBAgIQDJkqrAVVvIBWJvIMDkzpwzAKBggqhkjOPQQDAjBvMQsw
CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
GTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkRmxhcmUg
SW5jIEVDQyBDQS0yMB4XDTIwMDEzMTAwMDAwMFoXDTIwMTAwOTEyMDAwMFowbTEL
## # certificate output trimmed
# some more output
Q
这会使交互式会话保持打开状态,直到我们键入Q(退出)并按Enter,或者直到遇到EOF 。
我们可以使用*-showcerts*选项来获取完整的证书链:
$ openssl s_client -showcerts -connect blogdemo.com:443
CONNECTED(00000003)
## # some debugging output
MIIE6DCCBI2gAwIBAgIQDJkqrAVVvIBWJvIMDkzpwzAKBggqhkjOPQQDAjBvMQsw
CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
GTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkRmxhcmUg
SW5jIEVDQyBDQS0yMB4XDTIwMDEzMTAwMDAwMFoXDTIwMTAwOTEyMDAwMFowbTEL
# certificate output trimmed
## -----END CERTIFICATE-----
MIIDozCCAougAwIBAgIQD/PmFjmqPRoSZfQfizTltjANBgkqhkiG9w0BAQsFADBa
MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl
clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE1
MTAxNDEyMDAwMFoXDTIwMTAwOTEyMDAwMFowbzELMAkGA1UEBhMCVVMxCzAJBgNV
## # certificate output trimmed
# some more output
我们可以将这些输出复制粘贴到文件中,然后进行进一步处理。但是,让我们使用一些 Linux 魔法,只从整个输出中提取证书:
$ openssl s_client -showcerts -connect blogdemo.com:443 </dev/null | sed -n -e '/-.BEGIN/,/-.END/ p' > certifs.pem
现在让我们看一下certifs.pem文件:
## $ cat certifs.pem
MIIE6DCCBI2gAwIBAgIQDJkqrAVVvIBWJvIMDkzpwzAKBggqhkjOPQQDAjBvMQsw
CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
GTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkRmxhcmUg
SW5jIEVDQyBDQS0yMB4XDTIwMDEzMTAwMDAwMFoXDTIwMTAwOTEyMDAwMFowbTEL
# certificate output trimmed
## -----END CERTIFICATE-----
MIIDozCCAougAwIBAgIQD/PmFjmqPRoSZfQfizTltjANBgkqhkiG9w0BAQsFADBa
MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl
clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE1
MTAxNDEyMDAwMFoXDTIwMTAwOTEyMDAwMFowbzELMAkGA1UEBhMCVVMxCzAJBgNV
## # certificate output trimmed
让我们分解命令:
3.1.反向代理背后的服务器
在某些情况下,我们的服务器可能出于负载平衡的目的而位于反向代理后面。
首先,让我们使用nslookup 找到我们的主机 IP :
$ nslookup blogdemo.com
Server: 192.168.0.1
Address: 192.168.0.1#53
Non-authoritative answer:
Name: blogdemo.com
Address: 172.64.104.34
# some more output
让我们运行之前的示例,但使用主机 IP 地址:
$ openssl s_client -showcerts -connect 172.64.104.34:443
CONNECTED(00000003)
140695394247936:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake
failure:ssl/record/rec_layer_s3.c:1543:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 293 bytes
# some more output
我们得到一个错误。反向代理(由 172.64.104.34地址标识)服务于多个 Web 服务器,包括我们自己的。
因此,我们需要向它发送一个服务器名称,以便它知道要返回哪个证书。这种机制称为服务器名称指示。
但是为什么我们的第一个例子没有这个选项也能工作呢?默认情况下,OpenSSL使用传递给connect的相同值填充servername。
让我们通过blogdemo.com看看会发生什么:
$ openssl s_client -servername blogdemo.com -showcerts -connect 172.64.104.34:443
CONNECTED(00000003)
## # some debugging output
MIIE6DCCBI2gAwIBAgIQDJkqrAVVvIBWJvIMDkzpwzAKBggqhkjOPQQDAjBvMQsw
CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
GTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkRmxhcmUg
SW5jIEVDQyBDQS0yMB4XDTIwMDEzMTAwMDAwMFoXDTIwMTAwOTEyMDAwMFowbTEL
# certificate output trimmed
## -----END CERTIFICATE-----
MIIDozCCAougAwIBAgIQD/PmFjmqPRoSZfQfizTltjANBgkqhkiG9w0BAQsFADBa
MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl
clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE1
MTAxNDEyMDAwMFoXDTIwMTAwOTEyMDAwMFowbzELMAkGA1UEBhMCVVMxCzAJBgNV
## # certificate output trimmed
# some more output
Q
现在,我们得到与以前相同的结果。