Contents

获取 SSL 服务器证书

1. 概述

当我们要调试HTTPS连接时,往往需要获取服务器证书。该证书在 SSL 握手发生时传输,因此我们有多种获取方式。

在本快速教程中,我们将了解如何使用 Web 浏览器或 OpenSSL 命令行实用程序获取服务器证书。

2. 使用网络浏览器

我们获得证书的最简单方法是通过网络浏览器。让我们看看如何在 Firefox 中做到这一点。

首先,让我们点击地址栏中的站点信息(锁定符号)

/uploads/ssl_certificates/1.png

接下来,在连接详细信息菜单中,让我们点击更多信息

/uploads/ssl_certificates/3.png

现在,让我们点击查看证书

/uploads/ssl_certificates/5.png

在此之后,将打开一个新选项卡:

/uploads/ssl_certificates/6.png

在这里,我们可以通过单击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

让我们分解命令:

  • 首先,我们调用openssl s_client命令并将空设备/dev/null)重定向到其标准输入
  • 结果,交互式会话关闭,因为它读取EOF
  • 最后,我们使用sed 过滤输出并将证书转储到文件中

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

现在,我们得到与以前相同的结果。