使用openssl从服务器获取证书

nas*_*sty 314 linux security openssl certificate ssl-certificate

我正在尝试获取远程服务器的证书,然后我可以使用它来添加到我的密钥库并在我的java应用程序中使用.

一位资深开发者(节假日:())告诉我,我可以运行这个:

openssl s_client -connect host.host:9999
Run Code Online (Sandbox Code Playgroud)

要获取原始证书,我可以将其复制并导出.我收到以下输出:

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:
Run Code Online (Sandbox Code Playgroud)

我也试过这个选项

-showcerts 
Run Code Online (Sandbox Code Playgroud)

而这一个(在debian上运行你的头脑)

-CApath /etc/ssl/certs/ 
Run Code Online (Sandbox Code Playgroud)

但得到同样的错误.

这个消息来源说我可以使用那个CApath标志,但它似乎没有帮助.我尝试了多条路径无济于事.

请让我知道我哪里出错了.

Ari*_*tis 414

随着SNI

如果远程服务器正在使用SNI(即,在单个IP地址上共享多个SSL主机),则需要发送正确的主机名才能获得正确的证书.

openssl s_client -showcerts -servername www.example.com -connect www.example.com:443 </dev/null
Run Code Online (Sandbox Code Playgroud)

没有SNI

如果远程服务器未使用SNI,则可以跳过-servername参数:

openssl s_client -showcerts -connect www.example.com:443 </dev/null
Run Code Online (Sandbox Code Playgroud)


要查看站点证书的完整详细信息,您还可以使用此命令链:

$ echo | \
    openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null | \
    openssl x509 -text
Run Code Online (Sandbox Code Playgroud)

  • 有用:`echo""| openssl s_client -connect server:port -prexit 2>/dev/null | sed -n -e'/ BEGIN\CERTIFICATE /,/ END\CERTIFICATE/p'` http://stackoverflow.com/a/12918442/843000 (37认同)
  • 还有`echo | openssl s_client -connect google.com:443 2>/dev/null | openssl x509` (24认同)
  • 另一个有用的脚本,来自[madboa.com](http://www.madboa.com/geek/openssl/):`echo | openssl s_client -connect服务器:端口2>&1 | sed -ne'/ -BEGIN CERTIFICATE - /,/ - END CERTIFICATE-/p'> cert.pem` (16认同)
  • 为了使这更简洁,您可以将`sed`替换为`openssl x509`,并使用子shell读取它:`openssl x509 -in <(openssl s_client -connect server:port -prexit 2> /开发/空)` (9认同)
  • 嗯.尝试该命令时仍然会出现相同的错误.我注意到我的Openssl版本是'OpenSSL 0.9.8g 2007年10月19日'.你有什么想法? (3认同)
  • `echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -text`也可以获得人类可读的输出.也作为[答案](http://stackoverflow.com/a/35442314/289064). (2认同)
  • 如果它是使用 starttls 的邮件服务器(SMTP),您想从中获取证书,请使用:`openssl s_client -connect server:port -starttls smtp` (2认同)
  • 从 OpenSSL 1.1.1 开始,默认启用 SNI:“如果未提供 -servername,则 TLS SNI 扩展将使用给 -connect 指定的名称填充(如果它遵循 DNS 名称格式)。” (2认同)

Dav*_*uay 66

虽然我同意Ari的回答(并赞同它:),但我需要做一个额外的步骤,让它在Windows上运行Java(需要部署它):

openssl s_client -showcerts -connect www.example.com:443 < /dev/null | openssl x509 -outform DER > derp.der
Run Code Online (Sandbox Code Playgroud)

在添加openssl x509 -outform DER转换之前,我从Windows上的keytool收到错误,抱怨证书的格式.导入.der文件工作正常.


nas*_*sty 38

事实证明这里有更多的复杂性:我需要提供更多细节才能实现这一目标.我认为它与需要客户端身份验证的连接这一事实有关,并且hankshake需要更多信息才能继续到转储证书的阶段.

这是我的工作命令:

openssl s_client -connect host:port -key our_private_key.pem -showcerts \
                 -cert our_server-signed_cert.pem
Run Code Online (Sandbox Code Playgroud)

希望这对任何能够提供更多信息的人来说都是正确的方向.

  • 事实证明'-prexit'也将返回该数据.例如; openssl s_client -connect host:port -prexit (11认同)
  • 对不起,但你的答案没有多大意义.您需要将证书传递给服务器才能获得证书吗? (5认同)
  • 是的.客户端身份验证AFAIK. (2认同)

Flo*_*ian 32

最简单的命令行,包括将其添加到密钥库的PEM输出,以及人类可读输出,还支持SNI,如果您使用的是HTTP服务器,这很重要:

openssl s_client -servername example.com -connect example.com:443 \
    </dev/null 2>/dev/null | openssl x509 -text
Run Code Online (Sandbox Code Playgroud)

-servername选项是让SNI支持和OpenSSL的X509 -text打印人类可读格式的证书.


And*_*des 27

以PEM格式从远程服务器提取证书的单行程序,这次使用sed:

openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
Run Code Online (Sandbox Code Playgroud)

  • 这是提取证书的完美选择,只是缺少`-servername`选项,不知道为什么,但是我不得不使用它来获取完整的证书。 (2认同)

ken*_*orb 23

要获取远程服务器的证书,您可以使用openssl工具,您可以在它之间BEGIN CERTIFICATE以及END CERTIFICATE需要复制并粘贴到证书文件(CRT)中找到它.

这是展示它的命令:

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

要从链中返回所有证书,只需添加g(全局),如:

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

然后,您只需将证书文件(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.


ako*_*ond 10

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
Run Code Online (Sandbox Code Playgroud)


Hak*_*n54 10

我也遇到了同样的挑战,接下来我发现 openssl 不会返回根 ca。我专门为此目的构建了一个替代方案,这可能对其他开发人员有用,请参阅此处:GitHub - 证书开膛手

用法

  • 打印到控制台
crip print --url=https://stackoverflow.com/ --format=pem
Run Code Online (Sandbox Code Playgroud)
  • 导出到 p12 trustore
crip export pkcs12 --url=https://stackoverflow.com/
Run Code Online (Sandbox Code Playgroud)

如果您想要不同的输出,pkcs12可以替换该选项。pemder

  • debian 软件包中还有另一个“crip”实用程序,因此不要混淆。 (2认同)

Mat*_*AUX 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}'
Run Code Online (Sandbox Code Playgroud)

在 CentOS/RHEL 6/7 上更新 CA 信任:

# 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
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)


小智 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'") }'
Run Code Online (Sandbox Code Playgroud)

只需覆盖所需的变量。


SHo*_*oko 5

如果您的服务器是电子邮件服务器(MS Exchange 或 Zimbra),您可能需要添加starttlssmtp标志:

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 格式)


MrS*_*ind 5

已经有很好的答案了。但值得一提的是,最新的curl版本(>7.88.0)将为您做这件事简单......

curl https://example.com -w "%{certs}" -o /dev/null > cacert.pem
Run Code Online (Sandbox Code Playgroud)

--insecure如果服务器使用自签名证书,则添加。并添加--head避免响应正文。

请参阅此处的可用性和要求: cURL -w certs feature

  • 为清楚起见,在撰写本文时,curl 7.88 实际上尚未发布 - 将于 2023 年 2 月发布。 (2认同)