Golang中如何处理TLS握手错误:未知证书问题
Golang中如何处理TLS握手错误:未知证书问题
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"os"
"time"
)
func main() {
max := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, _ := rand.Int(rand.Reader, max)
subject := pkix.Name{
Organization: []string{"Manning Publications Co."},
OrganizationalUnit: []string{"Books"},
CommonName: "Go Web Programming",
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
}
pk, _ := rsa.GenerateKey(rand.Reader, 2048)
derBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &pk.PublicKey, pk)
certOut, _ := os.Create("cert.pem")
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, _ := os.Create("key.pem")
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)})
keyOut.Close()
}
package main
import (
"fmt"
"net/http"
)
func a(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hello")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", a)
server := &http.Server{
Addr: ":9090",
Handler: nil,
}
server.ListenAndServeTLS("cert.pem", "key.pem")
}
更多关于Golang中如何处理TLS握手错误:未知证书问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何处理TLS握手错误:未知证书问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Golang中处理TLS握手错误中的未知证书问题,通常需要配置自定义的TLS配置来跳过证书验证或添加证书信任。以下是几种解决方案:
1. 跳过证书验证(仅用于测试环境)
package main
import (
"crypto/tls"
"fmt"
"net/http"
)
func handler(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hello with custom TLS")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
// 创建自定义TLS配置
tlsConfig := &tls.Config{
InsecureSkipVerify: true, // 跳过证书验证
}
server := &http.Server{
Addr: ":9090",
Handler: mux,
TLSConfig: tlsConfig,
}
server.ListenAndServeTLS("cert.pem", "key.pem")
}
2. 添加自定义证书到信任池
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
)
func handler(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hello with custom certificate pool")
}
func main() {
// 读取自签名证书
caCert, err := ioutil.ReadFile("cert.pem")
if err != nil {
panic(err)
}
// 创建证书池
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 配置TLS
tlsConfig := &tls.Config{
RootCAs: caCertPool, // 使用自定义证书池
}
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
server := &http.Server{
Addr: ":9090",
Handler: mux,
TLSConfig: tlsConfig,
}
server.ListenAndServeTLS("cert.pem", "key.pem")
}
3. 客户端连接时处理未知证书
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// 客户端请求时处理证书
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // 跳过验证
},
},
}
resp, err := client.Get("https://localhost:9090")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("Response: %s\n", body)
}
4. 使用自定义验证回调
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
)
func handler(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hello with custom verification")
}
func main() {
// 自定义证书验证函数
tlsConfig := &tls.Config{
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// 这里可以实现自定义的证书验证逻辑
// 例如:检查特定证书指纹或允许特定自签名证书
fmt.Println("Custom certificate verification")
return nil // 返回nil表示验证通过
},
InsecureSkipVerify: true, // 需要设置为true才能使用自定义验证
}
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
server := &http.Server{
Addr: ":9090",
Handler: mux,
TLSConfig: tlsConfig,
}
server.ListenAndServeTLS("cert.pem", "key.pem")
}
5. 完整的客户端示例(包含错误处理)
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
"time"
)
func main() {
// 加载自签名证书
caCert, err := ioutil.ReadFile("cert.pem")
if err != nil {
fmt.Printf("Error reading certificate: %v\n", err)
return
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
fmt.Println("Failed to append certificate")
return
}
// 创建HTTP客户端
client := &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
},
},
}
// 发起请求
resp, err := client.Get("https://localhost:9090")
if err != nil {
fmt.Printf("Request error: %v\n", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Read error: %v\n", err)
return
}
fmt.Printf("Status: %d\nBody: %s\n", resp.StatusCode, body)
}
这些示例展示了在Golang中处理TLS握手时未知证书问题的不同方法。对于生产环境,建议使用第二种方法(自定义证书池)来确保安全性,而第一种方法(跳过验证)仅适用于测试环境。

