Пакет crypto/tls
Пакет crypto/tls реализует протокол TLS 1.2 и 1.3,
обеспечивая шифрование и аутентификацию сетевых соединений.
Он используется для создания защищенных каналов связи поверх
TCP-соединений. В первый параметр функций Dial и Listen мы
передаем сетевой протокол, во второй - адрес соединения,
в третий - конфигурацию TLS.
Основные компоненты
Пакет предоставляет функцию Dial для установки клиентских
соединений, функцию Listen для создания серверных
слушателей, структуру Config для настройки параметров
TLS и функции LoadX509KeyPair для загрузки сертификатов.
Пример клиентского соединения
Давайте установим защищенное соединение с сервером и выполним HTTP-запрос:
package main
import (
"crypto/tls"
"fmt"
"io"
"log"
)
func main() {
conn, err := tls.Dial("tcp", "example.com:443", &tls.Config{
InsecureSkipVerify: false,
})
if err != nil {
log.Fatal(err)
}
defer conn.Close()
_, err = conn.Write([]byte("GET / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"Connection: close\r\n\r\n"))
if err != nil {
log.Fatal(err)
}
resp, err := io.ReadAll(conn)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(resp[:100]))
}
Результат выполнения кода:
"HTTP/1.1 200 OK\r\nDate: Mon, 01 Jan 2024 00:00:00 GMT\r\n"
Пример серверной конфигурации
Создадим TLS-сервер с использованием минимальной версии протокола и списка поддерживаемых шифров:
package main
import (
"crypto/tls"
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("secure connection"))
})
server := &http.Server{
Addr: ":443",
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
},
Handler: mux,
}
err := server.ListenAndServeTLS("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
}
Пример загрузки сертификатов
Загрузим сертификат и приватный ключ из файлов для использования в TLS-конфигурации:
package main
import (
"crypto/tls"
"fmt"
"log"
)
func main() {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatal(err)
}
config := &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS13,
}
fmt.Println("TLS configuration created successfully")
conn, err := tls.Dial("tcp", "localhost:443", config)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
fmt.Println("Connection established")
}
Результат выполнения кода:
"TLS configuration created successfully"
"Connection established"
Пример кастомной проверки сертификата
Реализуем собственную логику проверки сертификата сервера при установке соединения:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
)
func main() {
config := &tls.Config{
InsecureSkipVerify: false,
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if len(rawCerts) == 0 {
return fmt.Errorf("no certificates provided")
}
cert, err := x509.ParseCertificate(rawCerts[0])
if err != nil {
return err
}
fmt.Printf("Server certificate: %s\n", cert.Subject.CommonName)
return nil
},
}
conn, err := tls.Dial("tcp", "google.com:443", config)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
fmt.Println("Connected to server")
}
Результат выполнения кода:
"Server certificate: *.google.com"
"Connected to server"
Смотрите также
-
структуру
tls.Config,
которая настраивает параметры TLS-соединения -
функцию
tls.Dial,
которая устанавливает клиентское TLS-соединение -
функцию
tls.Listen,
которая создает TLS-слушатель для сервера -
функцию
tls.LoadX509KeyPair,
которая загружает сертификат и ключ из файлов