Eine vollständige Anleitung zu TLS in Go: Vollständiger Prozess erklärt
Olivia Novak
Dev Intern · Leapcell

Erklärung des TLS-Handshake-Prozesses
Der TLS-Handshake (Transport Layer Security) ist ein wichtiger Vorgang, der eine sichere Kommunikation zwischen einem Client (z. B. einem Webbrowser) und einem Server (z. B. einem Webserver) ermöglicht. Nachfolgend finden Sie eine detaillierte Aufschlüsselung des gesamten TLS-Handshake-Prozesses:
-
Client Hello
- Der Client startet den Handshake, indem er eine "Client Hello"-Nachricht an den Server sendet.
- Diese Nachricht enthält:
- Die vom Client unterstützten TLS-Versionen.
- Eine Liste der Cipher Suites (Verschlüsselungsalgorithmen), die er unterstützt.
- Eine zufällige Byte-Zeichenkette (als Client Random bezeichnet).
-
Server Hello
- Der Server antwortet mit einer "Server Hello"-Nachricht.
- Diese Nachricht enthält:
- Die ausgewählte TLS-Version.
- Die gewählte Cipher Suite.
- Eine zufällige Byte-Zeichenkette (bekannt als Server Random).
- Das digitale Zertifikat des Servers (ausgestellt von einer vertrauenswürdigen Zertifizierungsstelle, CA).
-
Zertifikatsverifizierung
- Der Client verifiziert das Zertifikat des Servers über die Zertifizierungsstellenkette (CA).
- Er stellt sicher, dass das Zertifikat gültig, nicht abgelaufen und für die korrekte Domäne ausgestellt ist.
-
Pre - Master Secret Generation
- Der Client generiert ein "Pre - Master Secret" mit dem öffentlichen Schlüssel des Servers (aus dem Zertifikat extrahiert).
- Dieses Geheimnis wird verschlüsselt und an den Server gesendet.
-
Master Secret Derivation
- Sowohl der Client als auch der Server generieren das "Master Secret" anhand der folgenden Angaben:
- Der Client Random.
- Der Server Random.
- Das Pre - Master Secret.
- Das Master Secret wird verwendet, um Sitzungsschlüssel für Verschlüsselung und Integritätsprüfungen abzuleiten.
- Sowohl der Client als auch der Server generieren das "Master Secret" anhand der folgenden Angaben:
-
Sitzungsschlüssel Erstellung
- Unter Verwendung des Master Secret erstellen beide Parteien:
- Verschlüsselungsschlüssel für die symmetrische Verschlüsselung.
- MAC-Schlüssel (Message Authentication Code) für Integritätsprüfungen.
- Unter Verwendung des Master Secret erstellen beide Parteien:
-
Client Finished
- Der Client sendet eine "Finished"-Nachricht, die mit den Sitzungsschlüsseln verschlüsselt ist.
- Dies bestätigt, dass der Handshake erfolgreich war und dass zukünftige Nachrichten verschlüsselt werden.
-
Server Finished
- Der Server sendet seine eigene "Finished"-Nachricht, die mit den Sitzungsschlüsseln verschlüsselt ist.
- Dies markiert das Ende des Handshake und den Beginn der verschlüsselten Kommunikation.
-
Datentransfer
- Die gesamte nachfolgende Kommunikation wird mit den abgeleiteten Sitzungsschlüsseln verschlüsselt.
- Daten werden in verschlüsselten Paketen mit Integritätsprüfungen gesendet.
Diagramm des TLS-Handshake-Prozesses
+----------------------------------------+ +----------------------------------------+
| Client | | Server |
+----------------------------------------+ +----------------------------------------+
| | | |
| ClientHello |----->| |
| [TLS Version, Cipher Suites, Random] | | |
| | | |
| | | ServerHello |
| |<-----| [TLS Version, Cipher Suite, Random] |
| | | |
| |<-----| Certificate |
| | | [Server's Public Key] |
| | | |
| |<-----| ServerHelloDone |
| | | |
| CertificateVerify | | |
| [Verify Server's Certificate] | | |
| | | |
| ClientKeyExchange |----->| |
| [Encrypted Pre-Master Secret] | | |
| | | |
| ChangeCipherSpec |----->| |
| [Start Using Encryption] | | |
| | | |
| Finished |----->| |
| [Verifies Handshake Integrity] | | |
| | | |
| |<-----| ChangeCipherSpec |
| | | [Start Using Encryption] |
| | | |
| |<-----| Finished |
| | | [Verifies Handshake Integrity] |
| | | |
| Secure Communication |<--->| Secure Communication |
| [Encrypted Data Transfer] | | [Encrypted Data Transfer] |
+----------------------------------------+ +----------------------------------------+
Abrufen der TLS Client Hello Nachricht mit GoLang
Hier ist, wie man einen Server implementiert, der alle ClientHello Nachrichten mit GoLang erfasst:
Zertifikatsgenerierung
Zuerst generieren Sie die notwendigen SSL-Zertifikate:
# Generieren Sie einen privaten Schlüssel openssl genrsa -out server.key 2048 # Generieren Sie einen öffentlichen Schlüssel (Zertifikat) openssl req -new -x509 -key server.key -out server.pem -days 3650
Server Implementierung
Das Folgende ist der vollständige Servercode zur Erfassung von ClientHello Informationen:
package main import ( "bufio" "crypto/tls" "encoding/json" "fmt" "io/ioutil" "log" "net" "os" "sync" "time" ) type CollectInfos struct { ClientHellos []*tls.ClientHelloInfo sync.Mutex } var collectInfos CollectInfos var currentClientHello *tls.ClientHelloInfo func (c *CollectInfos) collectClientHello(clientHello *tls.ClientHelloInfo) { c.Lock() defer c.Unlock() c.ClientHellos = append(c.ClientHellos, clientHello) } func (c *CollectInfos) DumpInfo() { c.Lock() defer c.Unlock() data, err := json.Marshal(c.ClientHellos) if err != nil { log.Fatal(err) } ioutil.WriteFile("hello.json", data, os.ModePerm) } func getCert() *tls.Certificate { cert, err := tls.LoadX509KeyPair("server.pem", "server.key") if err != nil { log.Println(err) return nil } return &cert } func buildTlsConfig(cert *tls.Certificate) *tls.Config { cfg := &tls.Config{ Certificates: []tls.Certificate{*cert}, GetConfigForClient: func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) { collectInfos.collectClientHello(clientHello) currentClientHello = clientHello return nil, nil }, } return cfg } func serve(cfg *tls.Config) { ln, err := tls.Listen("tcp", ":443", cfg) if err != nil { log.Println(err) return } defer ln.Close() for { conn, err := ln.Accept() if err != nil { log.Println(err) continue } go handler(conn) } } func handler(conn net.Conn) { defer conn.Close() r := bufio.NewReader(conn) for { msg, err := r.ReadString('\n') if err != nil { log.Println(err) return } fmt.Println(msg) data, err := json.Marshal(currentClientHello) if err != nil { log.Fatal(err) } _, err = conn.Write(data) if err != nil { log.Println(err) return } } } func main() { go func() { for { collectInfos.DumpInfo() time.Sleep(10 * time.Second) } }() cert := getCert() if cert != nil { serve(buildTlsConfig(cert)) } }
Client Implementierung
Der entsprechende Client-Code lautet wie folgt:
func main() { conn, err := tls.Dial("tcp", "localhost:443", &tls.Config{InsecureSkipVerify: true}) if err != nil { log.Fatal(err) } defer conn.Close() _, err = conn.Write([]byte("hello\n")) if err != nil { log.Fatal(err) } buf := make([]byte, 1000) n, err := conn.Read(buf) if err != nil { log.Fatal(err) } fmt.Println(string(buf[:n])) }
Diese Implementierung ermöglicht es Ihnen, detaillierte Informationen aus ClientHello-Nachrichten während des TLS-Handshake-Prozesses zu erfassen. Der Server exportiert diese Informationen regelmäßig zur Analyse in eine JSON-Datei.
Leapcell: Das Beste von Serverless Web Hosting
Empfehlen Sie abschließend eine Plattform, die sich am besten für die Bereitstellung von Go-Diensten eignet: Leapcell
🚀 Entwickeln Sie mit Ihrer Lieblingssprache
Entwickeln Sie mühelos in JavaScript, Python, Go oder Rust.
🌍 Stellen Sie unbegrenzt Projekte kostenlos bereit
Sie zahlen nur für das, was Sie nutzen – keine Kosten, wenn keine Anfragen vorliegen.
⚡ Pay - as - You - Go, Keine versteckten Kosten
Keine Leerlaufgebühren, nur nahtlose Skalierbarkeit.
📖 Erkunden Sie unsere Dokumentation
🔹 Folgen Sie uns auf Twitter: @LeapcellHQ