Golang Go语言中 https://www.boc.cn 握手失败

Go client 请求 https://www.boc.cn 直接遇到 remote error: tls: handshake failure. 但是 Chrome 和 curl 都能正常返回。

查了半天没看出具体什么问题。有没有人遇到过这样情况的?谢谢!

  • Go 直接用的 &http.Client{} 没有任何配置
  • 中国银行用的是 DigiCert Inc 的 RSA 证书,看上去似乎也不是 CA 的问题?
  • 不知道是不是具体的 cipher suite 不匹配?好像也不像
  • 还能有什么可能的原因?

Chrome: The connection to this site is encrypted and authenticated using TLS 1.2, RSA, and AES_256_CBC with HMAC-SHA1.

curl: SSL connection using TLSv1.2 / ECDHE-RSA-AES128-SHA256

*   Trying 2402:93c0:20::16:443...
*   Trying 219.141.191.47:443...
* Connected to www.boc.cn (2402:93c0:20::16) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: jurisdictionC=CN; jurisdictionST=Beijing; businessCategory=Private Organization; serialNumber=911000001000013428; C=CN; ST=Beijing; O=Bank of China Limited; CN=www.boc.cn
*  start date: Nov  1 00:00:00 2023 GMT
*  expire date: Nov 27 23:59:59 2024 GMT
*  subjectAltName: host "www.boc.cn" matched cert's "www.boc.cn"
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Secure Site Pro Extended Validation CA G2
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /sourcedb/whpj/index.html HTTP/1.1
> Host: www.boc.cn
> User-Agent: curl/7.81.0
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse

Golang Go语言中 https://www.boc.cn 握手失败
9 回复

可能是通过 ja3 指纹

更多关于Golang Go语言中 https://www.boc.cn 握手失败的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


用的是 go1.22

更新日志里 <a target="_blank" href="https://go.dev/doc/go1.22" rel="nofollow noopener">https://go.dev/doc/go1.22</a> 看一下 crypto/tls,加上环境变量 GODEBUG=tls10server=1,tlsrsakex=1 试试

如果加上环境变量可用,修改 http.Clienttls.Config

go<br> &amp;tls.Config{<br> CipherSuites: tlsCipherSuites,<br> MinVersion: tls.VersionTLS10,<br> }<br><br>// copy from golang/1.22.1/go/src/crypto/tls/cipher_suites.go:270<br><br>var tlsCipherSuites = []uint16{<br> // AEADs w/ ECDHE<br> tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,<br> tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,<br> tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,<br><br> // CBC w/ ECDHE<br> tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,<br> tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,<br><br> // AEADs w/o ECDHE<br> tls.TLS_RSA_WITH_AES_128_GCM_SHA256,<br> tls.TLS_RSA_WITH_AES_256_GCM_SHA384,<br><br> // CBC w/o ECDHE<br> tls.TLS_RSA_WITH_AES_128_CBC_SHA,<br> tls.TLS_RSA_WITH_AES_256_CBC_SHA,<br><br> // 3DES<br> tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,<br> tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,<br>}<br>

tcpdump 抓个包,看看是 handshake 哪个阶段失败的。

应该就是 #2 提到的问题

谢谢!是#2 的问题

https://github.com/golang/go/issues/62459
go 1.22 开始指定默认 TLS 版本为 v1.2 ,但看起来#2 的方法是指定允许 TLS v1.0 的连接?
cURL 的执行结果显示支持 TLS v1.2 呀?迷惑



上面那段代码是直接搬过来用了,实际上根源是 1.22 版本中取消了基于 RSA 的加密方式,和 TLS 版本无关


<br> // CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of<br> // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.<br> //<br> // If CipherSuites is nil, a safe default list is used. The default cipher<br> // suites might change over time. In Go 1.22 RSA key exchange based cipher<br> // suites were removed from the default list, but can be re-added with the<br> // GODEBUG setting tlsrsakex=1.<br> CipherSuites []uint16<br>

明白了,感谢指教

针对您提到的在Golang中使用HTTPS与https://www.boc.cn(中国银行官网)进行握手失败的问题,这里有几个可能的解决方向和检查点:

  1. 证书验证:首先确认服务器的SSL/TLS证书是否有效且由受信任的证书颁发机构签发。可以通过浏览器访问该网址查看证书详情,或使用命令行工具如openssl s_client -connect www.boc.cn:443来检查证书链和有效期。

  2. TLS版本:检查您的Golang代码中是否指定了支持的TLS版本。某些老旧或特定版本的TLS可能不被服务器接受。尝试显式设置更高版本的TLS(如TLS 1.2或TLS 1.3)。

  3. Cipher Suites:服务器可能配置了特定的加密算法套件(Cipher Suites)。如果客户端不支持这些套件,也会导致握手失败。可以调整Golang的TLS配置以包含更广泛的Cipher Suites。

  4. 代理与防火墙:如果您的网络环境中有代理服务器或防火墙,它们可能会干扰TLS握手过程。检查这些中间设备是否配置了正确的转发规则或是否允许TLS流量通过。

  5. 代码审查:最后,仔细检查您的Golang代码中的HTTPS请求部分,确保没有编程错误,如错误的端口号、错误的请求方法等。

如果以上步骤仍未解决问题,建议捕获握手过程中的详细错误信息(如通过Go的tls.Config.InsecureSkipVerify临时设置为true来绕过证书验证,仅用于调试,生产环境禁用),以便进一步分析。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!