Golang 使用 crypto-tls 包實現 SSL-TLS 協議的 TCP 服務器

在網絡通信中,安全性至關重要。SSL/TLS 協議是一種廣泛使用的加密通信協議,用於保護敏感數據的傳輸。在本文中,我們將介紹如何使用 Golang 編程語言實現一個 SSL/TLS 協議的服務器,以確保我們的網絡通信是安全可靠的。

1. SSL/TLS 簡介

SSL/TLS(Secure Sockets Layer/Transport Layer Security)是一組加密協議,用於在計算機網絡上提供安全的數據傳輸。它們位於傳輸層,確保在客戶端和服務器之間的通信過程中數據的機密性、完整性和身份驗證。

2. Golang 中的 SSL/TLS 支持

Golang 是一種簡潔而高效的編程語言,它提供了強大的網絡編程能力和對 SSL/TLS 的支持。標準庫中的 "crypto/tls" 包提供了 SSL/TLS 協議的實現,使我們能夠輕鬆地構建安全的網絡應用程序。

3. 使用 openssl 創建數字證書

創建根證書

# 生成根證書私鑰
openssl genrsa -out ca.key 2048
# 使用私鑰創建根證書
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt

創建 SSL 證書

# 生成SSL私鑰
openssl genrsa -out server.key 2048
# 使用私鑰生成證書籤發請求
openssl req -new -key server.key -out server.csr
# 創建簽署證書相關目錄和文件
mkdir demoCA &&cd demoCA&&mkdir newcerts&&echo '10' > serial &&touch index.txt&&cd ..
# 使用根證書籤署SSL證書
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
# 查看證書
openssl x509 -in server.crt -noout -text

Mac 系統如果根證書籤署 SSL 證書時報錯:

Using configuration from /private/etc/ssl/openssl.cnf
variable lookup failed for ca::default_ca
140704333022784:error:0EFFF06C:configuration file routines:CRYPTO_internal:no value:/AppleInternal/Library/BuildRoots/c2cb9645-dafc-11ed-aa26-6ec1e3b3f7b3/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/conf/conf_lib.c:322:group=ca name=default_ca

是因爲系統默認的 openssl 使用的 / private/etc/ssl/openssl.cnf 配置文件中缺失 default_ca 的配置。 

解決方法:使用 brew 安裝的 openssl 而不使用系統默認的 openssl, brew 安裝好 openssl 後在終端執行命令

export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"

4. 使用 Golang 創建 SSL/TLS 的 TCP 服務器

使用 "crypto/tls" 包,我們可以輕鬆地爲我們的服務器生成自簽名的證書,並將其用於 SSL/TLS 連接。

package main
import (
  "crypto/tls"
  "github.com/sirupsen/logrus"
  "log"
  "net"
)
func handleConnection(conn net.Conn) {
  defer conn.Close()
  buffer := make([]byte, 1024)
  for {
    l, err := conn.Read(buffer)
    if err != nil {
      log.Println(err.Error())
      break
    }
    logrus.Infoln("Receive Data: %s\n", string(buffer[:l]))
  }
  logrus.Infoln("Client " + conn.RemoteAddr().String() + " Connection Closed.....")
}
func main() {
  port := "8888"
  crt, err := tls.LoadX509KeyPair("server.crt", "server.key")
  if err != nil {
    log.Fatalln(err.Error())
  }
  tlsConfig := &tls.Config{}
  tlsConfig.Certificates = []tls.Certificate{crt}
  ln, err := tls.Listen("tcp", ":"+port, tlsConfig)
  if err != nil {
    logrus.Fatalf("TCP server failed to listen on port %s. Error: %s", port, err.Error())
  }
  logrus.Infof("TCP server listening on port %s", port)
  defer ln.Close()
  for {
    conn, err := ln.Accept()
    if err != nil {
      logrus.Fatalf("TCP server failed to accept connection on port %s. Error: %v", port, err)
    } else {
      go handleConnection(conn)
    }
  }
}

運行結果:

INFO[0000] TCP server listening on port 8888            
INFO[0221] Receive Data: %s
 Hello SSL/TLS              
2023/06/25 21:33:52 EOF
INFO[0221] Client 127.0.0.1:50909 Connection Closed..... 
INFO[0271] Receive Data: %s
 Hello SSL/TLS              
2023/06/25 21:34:41 EOF
INFO[0271] Client 127.0.0.1:50915 Connection Closed.....

5. 客戶端代碼

客戶端需要配置 InsecureSkipVerify 參數,該參數表示客戶端跳過對證書鏈的校驗,因爲 CA 證書是不是自己生成的,不是系統信任的證書。

6. 結論

通過使用 Golang 的 "crypto/tls" 包,我們成功地實現了一個使用 SSL/TLS 協議的 TCP 服務器。通過加載證書和私鑰,我們確保了安全的通信連接,並且可以進行安全的數據傳輸。

SSL/TLS 協議在保護網絡通信方面起着重要作用,它使得數據在傳輸過程中免受竊聽和篡改的風險。通過掌握 Golang 中的 SSL/TLS 支持,我們可以構建安全可靠的網絡應用程序。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/tfeFhDEMrYQUfdyZqM0qCA