ChatGPT解决这个技术问题 Extra ChatGPT

使用 openssl 从服务器获取证书

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

一位高级开发人员(正在度假 :( )告诉我我可以运行这个:

openssl s_client -connect host.host:9999

得到一个原始证书,然后我可以复制和导出。我收到以下输出:

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:

我也试过这个选项:

-showcerts

而这个(在Debian上运行请注意):

-CApath /etc/ssl/certs/

但我得到同样的错误。

This source 说我可以使用那个 CApath 标志,但它似乎没有帮助。我尝试了多种路径均无济于事。

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


G
Greg Dubicki

使用 SNI

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

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

没有 SNI

如果远程服务器没有使用 SNI,那么您可以跳过 -servername 参数:

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

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

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

唔。尝试该命令时我仍然遇到相同的错误。我注意到我的 Openssl 版本是“OpenSSL 0.9.8g 2007 年 10 月 19 日”。你有什么想法?
有用:echo "" | openssl s_client -connect server:port -prexit 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' stackoverflow.com/a/12918442/843000
替代有用的脚本,来自 madboa.comecho | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
为了更简洁,您可以将 sed 替换为 openssl x509,并使用子 shell 读取它:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
还有echo | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
A
André Fernandes

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

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

这个提取证书几乎是完美的,只是少了-servername选项,不知道为什么,但我不得不用它来获取完整的证书。
服务器名称指示 (SNI) 需要 -servername。网络搜索可以扩展其余部分。
u
user314104

虽然我同意 Ari 的回答(并赞成 :),但我需要做一个额外的步骤才能让它在 Windows 上与 Java 一起工作(需要部署它的地方):

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

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


奇怪的。自 Java 6 以来,我一直在 Windows 上使用带有 keytool 的 PEM 证书,并且从未遇到过问题。
c
chown

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

这是我的工作命令:

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

希望这对于任何可以使用更多信息的人来说都是一个正确的方向。


我很抱歉,但你的回答没有多大意义。您需要将证书传递给服务器才能获得证书吗?
是的。客户端身份验证 AFAIK。
事实证明,'-prexit' 也会返回该数据。例如; openssl s_client -connect 主机:端口 -prexit
s
slm

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

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

-servername 选项用于启用 SNI 支持,而 openssl x509 -text 以人类可读格式打印证书。


您可以将子域添加到您的 -servername 中,例如 ws.example.com 而不是 example.com(也将其应用于 -connect 参数)。
k
kenorb

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

这是演示它的命令:

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

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

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

然后您可以简单地将您的证书文件 (file.crt) 导入您的钥匙串并使其受信任,因此 Java 不应该抱怨。

在 OS X 上,您可以双击文件或拖放到钥匙串访问中,这样它就会出现在登录/证书中。然后双击导入的证书并使其始终信任 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


a
akond
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

I
Ironcache

只打印证书链而不是服务器的证书:

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

在 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

在 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

正是我在 CentOS7 上所需要的。谢谢!
H
Hakan54

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

用法

打印到控制台

crip print --url=https://stackoverflow.com/ --format=pem

导出到 p12 信任库

crip export --url=https://stackoverflow.com/

很实用的工具!有什么方法可以指定导出的目标文件吗?我正在考虑路径和格式。谢谢
我正要分叉并添加该选项,但我看到您已经添加了它 - 非常感谢! :)
是的,我已添加并今天发布。感谢您提及这个想法,在应用程序中有这个选项很好
我注意到一个小问题,发布的源代码不是最新的^^
debian 软件包中还有另一个 crip 实用程序,因此不要混淆。
A
Andrei Aleksandrov

您可以使用下一个 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'") }'

只需覆盖所需的变量。


J
JuanMoreno

如果您的服务器是电子邮件服务器(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 格式)


C
Community

为了像我这样在访问 AWS CloudFront 时尝试遵循此处的好建议但失败的其他人的利益,诀窍是添加 -servername domain.name..

来源:https://serverfault.com/a/780450/8972


A
Alexandre Salomé

启动客户端:

openssl s_client -showcerts stackoverflow.com:443

通过停止 STDIN (CTRL+D) 或终止进程 (CTRL+C) 退出。

要在显示证书后禁用输入并强制客户端退出:

openssl s_client -showcerts stackoverflow.com:443 < /dev/null