Announcement

👇Official Account👇

图片

Welcome to join the group & private message

Article first/tail QR code

Skip to content

Golang 中的网络安全 TLS/SSL 的实现

TLS/SSL 是网络通信安全的基础。本文详细讲解 Go 语言中 TLS 的实现方法。

一、TLS 基础

1.1 TLS 握手流程

客户端                    服务器
  |                         |
  |------- ClientHello ---->|
  |                         |
  |<------ ServerHello -----|
  |<------ Certificate -----|
  |<------ ServerKeyExchange |
  |<------ ServerHelloDone -|
  |                         |
  |------ ClientKeyExchange>|
  |------ [ChangeCipherSpec]>|
  |------ Finished -------->|
  |                         |
  |<------ [ChangeCipherSpec]|
  |<------ Finished ---------|
  |                         |
  |<===== 加密通信 ========>|

1.2 证书类型

类型用途示例
自签名证书开发测试本地 HTTPS
CA 签名证书生产环境Let's Encrypt
客户端证书双向认证mTLS

二、基础 TLS 服务器

go
package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, TLS!"))
    })
    
    // 使用证书和私钥启动 HTTPS 服务器
    log.Fatal(http.ListenAndServeTLS(":8443", "server.crt", "server.key", nil))
}

三、自定义 TLS 配置

go
package main

import (
    "crypto/tls"
    "net/http"
)

func main() {
    // 自定义 TLS 配置
    tlsConfig := &tls.Config{
        // 最低 TLS 版本
        MinVersion: tls.VersionTLS12,
        
        // 允许的密码套件
        CipherSuites: []uint16{
            tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
            tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
        },
        
        // 优先使用服务器密码套件
        PreferServerCipherSuites: true,
        
        // 启用 HTTP/2
        NextProtos: []string{"h2", "http/1.1"},
    }
    
    server := &http.Server{
        Addr:      ":8443",
        TLSConfig: tlsConfig,
    }
    
    server.ListenAndServeTLS("server.crt", "server.key")
}

四、客户端 TLS

go
package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "net/http"
)

func createTLSClient() (*http.Client, error) {
    // 加载 CA 证书
    caCert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        return nil, err
    }
    
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)
    
    // 配置 TLS
    tlsConfig := &tls.Config{
        RootCAs:    caCertPool,
        MinVersion: tls.VersionTLS12,
    }
    
    transport := &http.Transport{
        TLSClientConfig: tlsConfig,
    }
    
    client := &http.Client{
        Transport: transport,
    }
    
    return client, nil
}

func main() {
    client, err := createTLSClient()
    if err != nil {
        panic(err)
    }
    
    resp, err := client.Get("https://localhost:8443")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    // 处理响应
}

五、双向认证 (mTLS)

5.1 mTLS 服务器

go
package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "net/http"
)

func main() {
    // 加载 CA 证书
    caCert, _ := ioutil.ReadFile("ca.crt")
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)
    
    // 配置 TLS(要求客户端证书)
    tlsConfig := &tls.Config{
        ClientCAs:  caCertPool,
        ClientAuth: tls.RequireAndVerifyClientCert,
        MinVersion: tls.VersionTLS12,
    }
    
    server := &http.Server{
        Addr:      ":8443",
        TLSConfig: tlsConfig,
    }
    
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 获取客户端证书信息
        if len(r.TLS.PeerCertificates) > 0 {
            cert := r.TLS.PeerCertificates[0]
            w.Write([]byte("Hello, " + cert.Subject.CommonName))
        }
    })
    
    server.ListenAndServeTLS("server.crt", "server.key")
}

5.2 mTLS 客户端

go
package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "net/http"
)

func createMTLSClient() (*http.Client, error) {
    // 加载客户端证书
    cert, err := tls.LoadX509KeyPair("client.crt", "client.key")
    if err != nil {
        return nil, err
    }
    
    // 加载 CA 证书
    caCert, _ := ioutil.ReadFile("ca.crt")
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)
    
    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{cert},
        RootCAs:      caCertPool,
        MinVersion:   tls.VersionTLS12,
    }
    
    transport := &http.Transport{
        TLSClientConfig: tlsConfig,
    }
    
    return &http.Client{Transport: transport}, nil
}

六、证书管理

6.1 生成自签名证书

go
package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "math/big"
    "os"
    "time"
)

func generateCert() error {
    // 生成私钥
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        return err
    }
    
    // 创建证书模板
    template := x509.Certificate{
        SerialNumber: big.NewInt(1),
        Subject: pkix.Name{
            Organization: []string{"My Org"},
        },
        NotBefore:             time.Now(),
        NotAfter:              time.Now().Add(365 * 24 * time.Hour),
        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        BasicConstraintsValid: true,
        IPAddresses:           []net.IP{net.IPv4(127, 0, 0, 1)},
    }
    
    // 生成证书
    certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
    if err != nil {
        return err
    }
    
    // 保存证书
    certFile, _ := os.Create("server.crt")
    pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
    certFile.Close()
    
    // 保存私钥
    keyFile, _ := os.Create("server.key")
    pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
    keyFile.Close()
    
    return nil
}

七、总结

场景配置要点
基础 HTTPSListenAndServeTLS
自定义配置tls.Config
客户端验证RootCAs
双向认证ClientAuth: RequireAndVerifyClientCert
证书生成crypto/x509

TLS/SSL 是网络安全的基石,正确配置能有效保护通信安全。

上次更新于: