Golang中SSL/HTTPS异常:首个记录不符合TLS握手协议的问题解决
Golang中SSL/HTTPS异常:首个记录不符合TLS握手协议的问题解决 我正在使用以下代码提供HTTPS服务,一切运行正常,客户端能正常访问页面,没有SSL错误,所有功能都正常工作,也没有生成日志,但是几乎每秒都会出现"first record does not look like a tls handshake"这条消息,这条消息被打印了数百次。以下是我使用的代码:
err := http.ListenAndServeTLS(":81", PastaCertSSL+"hlsatsslcrt.pem", PastaCertSSL+"server.key", nil)
if err != nil {
GeraLog(err.Error())
}
客户端使用正确的URL进行访问:
有人知道如何解决这个问题吗?
更多关于Golang中SSL/HTTPS异常:首个记录不符合TLS握手协议的问题解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我指的是我的客户,抱歉。
更多关于Golang中SSL/HTTPS异常:首个记录不符合TLS握手协议的问题解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你所说的客户端是指什么?是网页浏览器还是其他什么?
你确定他们的 HTTP 客户端真的使用了 TLS 吗?
这意味着有人连接并尝试使用非TLS协议进行通信。可能您的图片链接使用了普通的HTTP协议,或存在类似情况。
这是一个 REST API,没有图像也没有 HTML 内容,它只是一个向输出写入 JSON 的 REST API……
我找到了问题的症结所在。这个 REST API 为 Android 应用提供数据,部分设备版本过旧,仍尝试连接旧的 HTTP 网址。由于新旧网址相同且端口一致,唯一的区别在于 HTTPS,这些设备最终连接到了新的 TLS 服务,因此出现了握手警告。感谢各位。
这是一个典型的TLS握手异常问题,通常发生在非TLS客户端尝试连接到HTTPS端口时。最常见的原因是端口扫描、爬虫或错误配置的客户端发送了非TLS流量到你的HTTPS端口。
以下是几种解决方案:
方案1:添加TLS配置和连接过滤
import (
"crypto/tls"
"net"
"net/http"
"time"
)
func main() {
// 创建自定义TLS配置
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
},
}
// 创建自定义服务器
server := &http.Server{
Addr: ":81",
TLSConfig: tlsConfig,
}
// 使用自定义监听器
ln, err := net.Listen("tcp", ":81")
if err != nil {
GeraLog(err.Error())
return
}
// 包装为TLS监听器
tlsListener := tls.NewListener(ln, tlsConfig)
err = server.Serve(tlsListener)
if err != nil {
GeraLog(err.Error())
}
}
方案2:实现连接嗅探和过滤
import (
"bufio"
"crypto/tls"
"net"
"net/http"
"strings"
"time"
)
type tlsSniffConn struct {
net.Conn
r *bufio.Reader
}
func (c *tlsSniffConn) Read(b []byte) (int, error) {
return c.r.Read(b)
}
func main() {
ln, err := net.Listen("tcp", ":81")
if err != nil {
GeraLog(err.Error())
return
}
for {
conn, err := ln.Accept()
if err != nil {
GeraLog("Accept error: " + err.Error())
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
// 设置读取超时
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
// 创建带缓冲的读取器来嗅探第一个数据包
r := bufio.NewReader(conn)
peek, err := r.Peek(1)
if err != nil {
conn.Close()
return
}
// 重置读取超时
conn.SetReadDeadline(time.Time{})
// 检查是否是TLS握手(TLS握手通常以0x16开头)
if len(peek) > 0 && peek[0] == 0x16 {
// 是TLS流量,进行TLS握手
tlsConn := tls.Server(&tlsSniffConn{conn, r}, &tls.Config{
Certificates: []tls.Certificate{loadCertificate()},
})
// 创建HTTP服务器处理TLS连接
http.Serve(tlsConn, nil)
} else {
// 非TLS流量,直接关闭连接
conn.Close()
}
}
func loadCertificate() tls.Certificate {
cert, err := tls.LoadX509KeyPair(PastaCertSSL+"hlsatsslcrt.pem", PastaCertSSL+"server.key")
if err != nil {
GeraLog("Certificate load error: " + err.Error())
}
return cert
}
方案3:使用更严格的TLS配置
func main() {
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
},
// 拒绝不完整的TLS握手
VerifyConnection: func(cs tls.ConnectionState) error {
if !cs.HandshakeComplete {
return tls.CertificateVerificationError{Err: errors.New("incomplete handshake")}
}
return nil
},
}
server := &http.Server{
Addr: ":81",
TLSConfig: tlsConfig,
// 设置更短的读写超时
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
err := server.ListenAndServeTLS(PastaCertSSL+"hlsatsslcrt.pem", PastaCertSSL+"server.key")
if err != nil {
GeraLog(err.Error())
}
}
这些方案通过过滤非TLS流量、加强TLS配置和设置适当的超时来减少"first record does not look like a tls handshake"警告的出现频率。方案2的连接嗅探方法能最有效地阻止非TLS流量到达TLS层。

