持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
最近,我遇到了一个SaaS产品,该产品可以验证你的网站的SSL证书。 你需要在你的网站上执行三项重大检查。
- 首先,检查您的网站是否有SSL证书。您还需要知道您的网站是否正在使用不被视为有效证书的自签名SSL证书(需要由证书颁发机构签名)。
- 其次,查看SSL证书是否有正确的主机名。
- 第三,您需要知道服务器证书的到期日期。
先决条件:
- 你应该
go
你的电脑上设置。
第1步:检查您的网站是否有SSL证书
首先,我们将尝试检查该网站是否有SSL证书。
为此,我们需要与网站建立TLS连接。如果成功,则表示网站拥有有效的TLS证书。
要建立TLS连接,我们可以使用Gocrypto/tls
软件包。我们将使用Dial
方法连接到网站,如下所示:
package main
import (
"crypto/tls"
)
func main() {
conn, err := tls.Dial("tcp", "example.com:80", nil)
if err != nil {
panic("Server doesn't support SSL certificate err: " + err.Error())
}
}
main.go
我们将尝试在example.com
上运行我们的测试。当您运行上述代码时,您应该会收到以下错误:
$ go run main.go
panic: Server doesn't support SSL certificate err: tls: first record does not look like a TLS handshake
goroutine 1 [running]:
main.main()
/Users/umesh/personal/spike/main.go:99 +0x2ca
exit status 2
终端中的输出
基本上,它试图建立连接,但失败了。只有当网站拥有有效的证书时,Dial
方法才会成功(如果证书是自签名,则会失败)。
现在在启用了SSL的网站上尝试相同的代码。我使用我自己网站的URL作为示例:
package main
import (
"crypto/tls"
)
func main() {
conn, err := tls.Dial("tcp", "blog.umesh.wtf:443", nil)
if err != nil {
panic("Server doesn't support SSL certificate err: " + err.Error())
}
}
main.go
这一次,我们应该能够在没有代码恐慌的情况下成功建立连接。
在生产中,您不应该使用恐慌,而应该优雅地处理错误。
第2步:检查SSL证书和网站主机名是否匹配
要验证主机名,我们需要通过Dial
在conn
返回时调用VerifyHostname
。此方法试图将证书中指定的通用名称或主题alt名称与作为参数传递的域匹配。
package main
import (
"crypto/tls"
)
func main() {
conn, err := tls.Dial("tcp", "blog.umesh.wtf:443", nil)
if err != nil {
panic("Server doesn't support SSL certificate err: " + err.Error())
}
err = conn.VerifyHostname("blog.umesh.wtf")
if err != nil {
panic("Hostname doesn't match with certificate: " + err.Error())
}
}
main.go
这将成功执行,没有任何错误,因为证书的通用名称和主机名是相同的。
第3步:验证服务器SSL证书的到期日期
We can get the certificate chain using conn.ConnectionState().PeerCertificates
. We can then use this certificate to get the expiration date of the server certificate.
我们将使用证书列表中的第一个证书,并尝试使用NotAfter
字段获取到期日期。
package main
import (
"crypto/tls"
"fmt"
"time"
)
func main() {
conn, err := tls.Dial("tcp", "blog.umesh.wtf:443", nil)
if err != nil {
panic("Server doesn't support SSL certificate err: " + err.Error())
}
err = conn.VerifyHostname("blog.umesh.wtf")
if err != nil {
panic("Hostname doesn't match with certificate: " + err.Error())
}
expiry := conn.ConnectionState().PeerCertificates[0].NotAfter
fmt.Printf("Issuer: %s\nExpiry: %v\n", conn.ConnectionState().PeerCertificates[0].Issuer, expiry.Format(time.RFC850))
}
main.go
输出应包含证书的到期日期和发行人名称。
$ go run main.go
Issuer: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
Expiry: Wednesday, 16-Dec-20 16:20:00 UTC
终端中的输出
现在,我们已经成功验证了该网站的证书。
结论
您还可以获得详细信息,如根CA、证书签发日期和所有链式证书。