Golang TLS 安全链接通信

场景说明

  • 通信双方使用自签名证书进行安全通信。
  • 启用双向验证。
  • 使用 ECC 证书。ECC 证书在建立握手时的通信数据量、链接建立速度、安全性相比 RSA 都有优势。

制作证书

参见: 使用 OpenSSL 制作自签名 ECC 证书

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

主要流程

  • 服务器端

    1. 载入根证书,用于验证客户端的真实性。Golang 没有提供便捷的载入自签名根证书的方法,需要自行通过 x509.NewCertPool() 去创建 CertPool 然后添加证书。
    2. 载入服务器证书,用于发送给客户端以验证服务器真实性。Golang 提供了 tls.LoadX509KeyPair 函数去加载证书和私钥对。
    3. 配置 tls.Config
    4. 使用 Listen 监听端口,之后接受连接,收发数据与一般 TCP 链接无异
  • 客户端

    1. 载入根证书,用于验证服务器端的真实性。
    2. 载入客户证书,用于发送给服务器端以验证客户的真实性。
    3. 配置 tls.Config
    4. 使用 Dial 请求连接,之后收发数据与一般 TCP 链接无异