Ssl

HAProxy 後端伺服器返回“SSL 握手錯誤”

  • December 18, 2020

我知道這是一個常見問題,通常意味著證書驗證存在問題。似乎不是這樣,因為我沒有驗證證書。

這就是我的伺服器規範一開始的樣子:

server 1.base.maps.ls.hereapi.com 1.base.maps.ls.hereapi.com:443 ssl verify none check resolvers mydns 

後來演變成

server 1.base.maps.ls.hereapi.com ipv4@1.base.maps.ls.hereapi.com:443 ssl verify none force-tlsv12 check resolvers mydns resolve-prefer ipv4

但它總是返回相同的錯誤:

Server freehere_maps_redirect/1.base.maps.ls.hereapi.com is DOWN, reason: Layer6 invalid response, info: "SSL handshake failure"

URL 是真實的伺服器名稱。此後端中還有 3 台伺服器(2.base.maps、3.base.maps、4.base.maps…),它們都返回相同的錯誤。這些伺服器不在我的控制之下。

我也嘗試啟用證書驗證,但當然,它並沒有解決問題。不用說,curl其他連接到後端伺服器的嘗試都完美無缺。

HA-Proxy 版本 1.8.4-1deb90d 2018/02/08 在 CentOS7 上執行。

您的想法將不勝感激:)

更新:這是使用 curl 發出的成功請求的輸出:

$ curl -v --tls-max 1.2 'https://1.base.maps.ls.hereapi.com/maptile/2.1/maptile/newest/normal.day/11/525/761/256/png8?apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

*   Trying 13.33.243.105:443...
*   Trying 2600:9000:2118:be00:2:b190:a500:93a1:443...
* Connected to 1.base.maps.ls.hereapi.com (13.33.243.105) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
 CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=NL; ST=Noord-Brabant; L=Eindhoven; O=HERE Global BV; CN=*.base.maps.ls.hereapi.com
*  start date: May 10 17:54:34 2020 GMT
*  expire date: May 11 17:54:34 2021 GMT
*  subjectAltName: host "1.base.maps.ls.hereapi.com" matched cert's "*.base.maps.ls.hereapi.com"
*  issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55b593a60020)
> GET /maptile/2.1/maptile/newest/normal.day/11/525/761/256/png8?apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx HTTP/2
> Host: 1.base.maps.ls.hereapi.com
> user-agent: curl/7.72.0
> accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< content-type: image/png
< content-length: 30653
< access-control-allow-origin: *
< cache-control: public,max-age=86400
< date: Thu, 03 Dec 2020 12:51:37 GMT
< etag: 4742ccdf6d
< expires: Fri, 04 Dec 2020 12:51:37 GMT
< last-modified: Thu, 19 Nov 2020 20:58:37 GMT
< server: nginx
< x-nlp-irt: D=68945
< x-ols-tid: hjBM-ZZ2dSrOCS0R3IovQk_icd0LanCeb81VKszvSQzzTLygjksosg==
< x-served-by: i-094a2ddaf9791ccf9.eu-west-1b
< x-cache: Hit from cloudfront
< via: 1.1 228e9f9ffd3a938a52da99b2c67d587f.cloudfront.net (CloudFront)
< x-amz-cf-pop: HEL50-C1
< x-amz-cf-id: gALOyDPx1QY7dsP0NlaEBivgFHjgP8kLWPw5l2U2DfS1ZCEXOg7FDQ==
< 
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
* Failure writing output to destination
* stopped the pause stream!
* Connection #0 to host 1.base.maps.ls.hereapi.com left intact

Update2:我嘗試通過將後端修改為:用 TCP 檢查替換 HTTP 檢查:

backend freehere_maps_redirect
       http-send-name-header Host
       http-request set-uri http://%[req.hdr(Host)]%[path]?apiKey=xxxxxxxxxxx&%[query]
       option tcp-check
       tcp-check connect port 443
       server 1.base.maps.ls.hereapi.com ipv4@1.base.maps.ls.hereapi.com:443 check

tcp-check 通過,但我仍然無法從上行鏈路伺服器獲得任何結果。另一方面,它可能指向更深層次的問題,因為我從 CloudFront 收到 HTTP 400(錯誤請求):

<H1>400 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.

更新 3: 更多細節。我嘗試使用 ssldump 查看 SSL 握手過程。這是使用 haproxy 的外觀:

1 1  0.1478 (0.1478)  C>S  Handshake
     ClientHello
       Version 3.3 
       cipher suites
       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
       TLS_DH_DSS_WITH_AES_256_GCM_SHA384
       TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
       TLS_DH_RSA_WITH_AES_256_GCM_SHA384
       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
       TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
       TLS_DH_RSA_WITH_AES_256_CBC_SHA256
       TLS_DH_DSS_WITH_AES_256_CBC_SHA256
       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
       TLS_DHE_DSS_WITH_AES_256_CBC_SHA
       TLS_DH_RSA_WITH_AES_256_CBC_SHA
       TLS_DH_DSS_WITH_AES_256_CBC_SHA
       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
       TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
       TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
       TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
       TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
       TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
       TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
       TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
       TLS_RSA_WITH_AES_256_GCM_SHA384
       TLS_RSA_WITH_AES_256_CBC_SHA256
       TLS_RSA_WITH_AES_256_CBC_SHA
       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
       TLS_DH_DSS_WITH_AES_128_GCM_SHA256
       TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
       TLS_DH_RSA_WITH_AES_128_GCM_SHA256
       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
       TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
       TLS_DH_RSA_WITH_AES_128_CBC_SHA256
       TLS_DH_DSS_WITH_AES_128_CBC_SHA256
       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
       TLS_DHE_DSS_WITH_AES_128_CBC_SHA
       TLS_DH_RSA_WITH_AES_128_CBC_SHA
       TLS_DH_DSS_WITH_AES_128_CBC_SHA
       TLS_DHE_RSA_WITH_SEED_CBC_SHA
       TLS_DHE_DSS_WITH_SEED_CBC_SHA
       TLS_DH_RSA_WITH_SEED_CBC_SHA
       TLS_DH_DSS_WITH_SEED_CBC_SHA
       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
       TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
       TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
       TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
       TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
       TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
       TLS_RSA_WITH_AES_128_GCM_SHA256
       TLS_RSA_WITH_AES_128_CBC_SHA256
       TLS_RSA_WITH_AES_128_CBC_SHA
       TLS_RSA_WITH_SEED_CBC_SHA
       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
       TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
       TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
       TLS_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_RSA_WITH_IDEA_CBC_SHA
       TLS_ECDHE_RSA_WITH_RC4_128_SHA
       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
       TLS_ECDH_RSA_WITH_RC4_128_SHA
       TLS_ECDH_ECDSA_WITH_RC4_128_SHA
       TLS_RSA_WITH_RC4_128_SHA
       TLS_RSA_WITH_RC4_128_MD5
       TLS_EMPTY_RENEGOTIATION_INFO_SCSV
       compression methods
                 NULL
1 2  0.3019 (0.1541)  S>C  Alert
   level           fatal
   value           handshake_failure
1 3  0.3019 (0.0000)  S>C  Alert
   level           warning
   value           close_notify
1    0.3024 (0.0004)  S>C  TCP FIN
1    0.3112 (0.0087)  C>S  TCP FIN

這是使用 curl 的成功交換:

New TCP connection #1: localhost.localdomain(60630) <-> server-13-33-243-73.hel50.r.cloudfront.net(443)
1 1  0.2425 (0.2425)  C>S  Handshake
     ClientHello
       Version 3.3 
       cipher suites
       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
       Unknown value 0xcca9
       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
       Unknown value 0xcca8
       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
       TLS_DHE_DSS_WITH_AES_256_CBC_SHA
       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
       Unknown value 0xccaa
       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
       TLS_DHE_DSS_WITH_AES_128_CBC_SHA
       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
       TLS_RSA_WITH_AES_256_GCM_SHA384
       TLS_RSA_WITH_AES_256_CBC_SHA
       TLS_RSA_WITH_AES_256_CBC_SHA256
       TLS_RSA_WITH_AES_128_GCM_SHA256
       TLS_RSA_WITH_AES_128_CBC_SHA
       TLS_RSA_WITH_AES_128_CBC_SHA256
       TLS_RSA_WITH_3DES_EDE_CBC_SHA
       TLS_RSA_WITH_RC4_128_SHA
       TLS_RSA_WITH_RC4_128_MD5
       compression methods
                 NULL
1 2  0.3793 (0.1367)  S>C  Handshake
     ServerHello
       Version 3.3 
       session_id[32]=
         f8 f2 8b 5b 48 eb bb 7f d8 5c 70 e0 9c 86 30 0d 
         f7 3d 6c 52 2f 66 b7 33 84 09 1f bb 25 14 d9 f6 
       cipherSuite         TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
       compressionMethod                   NULL
1 3  0.3994 (0.0201)  S>C  Handshake
     Certificate
1 4  0.3994 (0.0000)  S>C  Handshake
     ServerKeyExchange
1 5    0.3994   (0.0000)    S>C    Handshake
       ServerHelloDone
etc.

這是否意味著這是密碼不匹配問題?但是遠端伺服器在 curl 交換期間選擇的 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 也存在於 haproxy 提供的密碼列表中。

也嘗試添加sni str(d2t4vhngii5504.cloudfront.net)or sni str(1.base.maps.ls.hereapi.com),但它也沒有幫助。

server ... ipv4@1.base.maps.ls.hereapi.com:443 ssl ... check ...

有問題的伺服器需要 SNI。因此check-sni name,而不是check需要使用。從文件中

check-sni

此選項允許您指定在通過 SSL 進行健康檢查時要使用的 SNI。只能使用字元串來設置。如果要為代理流量設置 SNI,請參閱“sni”。

因此它應該是:

server ... ipv4@1.base.maps.ls.hereapi.com:443 ssl ... check check-sni 1.base.maps.ls.hereapi.com

引用自:https://serverfault.com/questions/1044816