场景说明
- 通信双方使用自签名证书进行安全通信。
- 启用双向验证。
- 使用 ECC 证书。ECC 证书在建立握手时的通信数据量、链接建立速度、安全性相比 RSA 都有优势。
制作证书
tls.Config 配置要点
Certificates
证书,对于服务器端就是服务器的证书,对于客户端就是客户的证书。ClientAuth
客户端验证策略,这里我们选择RequireAndVerifyClientCert
,即要求客户端发送证书并验证其真实性。ClientCAs
签名使用的根证书,服务器端使用,用于验证客户端的真实性(如果开启了客户端验证)。RootCAs
签名使用的根证书,客户端使用,用于验证服务器的真实性。ServerName
服务器端证书对应的CommonName
,用于验证服务器的真实性。CipherSuites
用于协商加密策略,由于我们使用 ECC 证书,所以只选择ECDHE_ECDSA
系列,排除掉安全性较差的AES_128_CBC_SHA
方式,最终选择ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
ECDHE_ECDSA_WITH_CHACHA20_POLY1305
这三种方式。MinVersion
要求最小 TLS 版本号,计划通信双方都使用 Golang 开发,不存在兼容性问题,MinVerson
直接开到最高,即VersionTLS12
。
主要流程
-
服务器端
- 载入根证书,用于验证客户端的真实性。Golang 没有提供便捷的载入自签名根证书的方法,需要自行通过
x509.NewCertPool()
去创建 CertPool 然后添加证书。 - 载入服务器证书,用于发送给客户端以验证服务器真实性。Golang 提供了
tls.LoadX509KeyPair
函数去加载证书和私钥对。 - 配置
tls.Config
- 使用
Listen
监听端口,之后接受连接,收发数据与一般 TCP 链接无异
- 载入根证书,用于验证客户端的真实性。Golang 没有提供便捷的载入自签名根证书的方法,需要自行通过
-
客户端
- 载入根证书,用于验证服务器端的真实性。
- 载入客户证书,用于发送给服务器端以验证客户的真实性。
- 配置
tls.Config
- 使用
Dial
请求连接,之后收发数据与一般 TCP 链接无异