如何调测HTTPS SNI 问题
curl -vvv https://www.example.com:443 -H 'Host: www.example.com'
# curl -vvv https://www.example.com:443 -H 'Host: www.example.com'
* About to connect() to www.example.com port 443 (#0)
* Trying 93.184.215.14...
* Connected to www.example.com (93.184.215.14) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=www.example.org,O=Internet Corporation for Assigned Names and Numbers,L=Los Angeles,ST=California,C=US
* start date: Jan 30 00:00:00 2024 GMT
* expire date: Mar 01 23:59:59 2025 GMT
* common name: www.example.org
* issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1,O=DigiCert Inc,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: www.example.com
>
< HTTP/1.1 200 OK
< Age: 342842
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Sun, 15 Sep 2024 03:41:21 GMT
< Etag: "3147526947+ident"
< Expires: Sun, 22 Sep 2024 03:41:21 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECAcc (sac/255D)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
* Connection #0 to host www.example.com left intact
echo "" | openssl s_client -showcerts -connect www.example.com:443
# echo "" | openssl s_client -showcerts -connect www.example.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G2
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert Global G2 TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C = US, ST = California, L = Los Angeles, O = Internet\C2\A0Corporation\C2\A0for\C2\A0Assigned\C2\A0Names\C2\A0and\C2\A0Numbers, CN = www.example.org
verify return:1
---
Certificate chain
0 s:/C=US/ST=California/L=Los Angeles/O=Internet\xC2\xA0Corporation\xC2\xA0for\xC2\xA0Assigned\xC2\xA0Names\xC2\xA0and\xC2\xA0Numbers/CN=www.example.org
i:/C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
-----BEGIN CERTIFICATE-----
MIIHbjCCBlagAwIBAgIQB1vO8waJyK3fE+Ua9K/hhzANBgkqhkiG9w0BAQsFADBZ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTMwMQYDVQQDEypE
aWdpQ2VydCBHbG9iYWwgRzIgVExTIFJTQSBTSEEyNTYgMjAyMCBDQTEwHhcNMjQw
MTMwMDAwMDAwWhcNMjUwMzAxMjM1OTU5WjCBljELMAkGA1UEBhMCVVMxEzARBgNV
BAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVzMUIwQAYDVQQKDDlJ
bnRlcm5ldMKgQ29ycG9yYXRpb27CoGZvcsKgQXNzaWduZWTCoE5hbWVzwqBhbmTC
oE51bWJlcnMxGDAWBgNVBAMTD3d3dy5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAIaFD7sO+cpf2fXgCjIsM9mqDgcpqC8IrXi9wga/
9y0rpqcnPVOmTMNLsid3INbBVEm4CNr5cKlh9rJJnWlX2vttJDRyLkfwBD+dsVvi
vGYxWTLmqX6/1LDUZPVrynv/cltemtg/1Aay88jcj2ZaRoRmqBgVeacIzgU8+zmJ
7236TnFSe7fkoKSclsBhPaQKcE3Djs1uszJs8sdECQTdoFX9I6UgeLKFXtg7rRf/
hcW5dI0zubhXbrW8aWXbCzySVZn0c7RkJMpnTCiZzNxnPXnHFpwr5quqqjVyN/aB
KkjoP04Zmr+eRqoyk/+lslq0sS8eaYSSHbC5ja/yMWyVhvMCAwEAAaOCA/IwggPu
MB8GA1UdIwQYMBaAFHSFgMBmx9833s+9KTeqAx2+7c0XMB0GA1UdDgQWBBRM/tAS
TS4hz2v68vK4TEkCHTGRijCBgQYDVR0RBHoweIIPd3d3LmV4YW1wbGUub3Jnggtl
eGFtcGxlLm5ldIILZXhhbXBsZS5lZHWCC2V4YW1wbGUuY29tggtleGFtcGxlLm9y
Z4IPd3d3LmV4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5lZHWCD3d3dy5leGFtcGxl
Lm5ldDA+BgNVHSAENzA1MDMGBmeBDAECAjApMCcGCCsGAQUFBwIBFhtodHRwOi8v
d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG
CCsGAQUFBwMBBggrBgEFBQcDAjCBnwYDVR0fBIGXMIGUMEigRqBEhkJodHRwOi8v
Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxHMlRMU1JTQVNIQTI1NjIw
MjBDQTEtMS5jcmwwSKBGoESGQmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdp
Q2VydEdsb2JhbEcyVExTUlNBU0hBMjU2MjAyMENBMS0xLmNybDCBhwYIKwYBBQUH
AQEEezB5MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wUQYI
KwYBBQUHMAKGRWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds
b2JhbEcyVExTUlNBU0hBMjU2MjAyMENBMS0xLmNydDAMBgNVHRMBAf8EAjAAMIIB
fQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdABOdaMnXJoQwzhbbNTfP1LrHfDgjhuN
acCx+mSxYpo53wAAAY1b0vxkAAAEAwBFMEMCH0BRCgxPbBBVxhcWZ26a8JCe83P1
JZ6wmv56GsVcyMACIDgpMbEo5HJITTRPnoyT4mG8cLrWjEvhchUdEcWUuk1TAHYA
fVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGNW9L8MAAABAMARzBF
AiBdv5Z3pZFbfgoM3tGpCTM3ZxBMQsxBRSdTS6d8d2NAcwIhALLoCT9mTMN9OyFz
IBV5MkXVLyuTf2OAzAOa7d8x2H6XAHcA5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6
hzId/R43jlAAAAGNW9L8XwAABAMASDBGAiEA4Koh/VizdQU1tjZ2E2VGgWSXXkwn
QmiYhmAeKcVLHeACIQD7JIGFsdGol7kss2pe4lYrCgPVc+iGZkuqnj26hqhr0TAN
BgkqhkiG9w0BAQsFAAOCAQEABOFuAj4N4yNG9OOWNQWTNSICC4Rd4nOG1HRP/Bsn
rz7KrcPORtb6D+Jx+Q0amhO31QhIvVBYs14gY4Ypyj7MzHgm4VmPXcqLvEkxb2G9
Qv9hYuEiNSQmm1fr5QAN/0AzbEbCM3cImLJ69kP5bUjfv/76KB57is8tYf9sh5ik
LGKauxCM/zRIcGa3bXLDafk5S2g5Vr2hs230d/NGW1wZrE+zdGuMxfGJzJP+DAFv
iBfcQnFg4+1zMEKcqS87oniOyG+60RMM0MdejBD7AS43m9us96Gsun/4kufLQUTI
FfnzxLutUV++3seshgefQOy5C/ayi8y1VTNmujPCxPCi6Q==
-----END CERTIFICATE-----
1 s:/C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root G2
-----BEGIN CERTIFICATE-----
MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yMTAzMzAwMDAwMDBaFw0zMTAzMjkyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKkRpZ2lDZXJ0IEdsb2Jh
bCBHMiBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMz3EGJPprtjb+2QUlbFbSd7ehJWivH0+dbn4Y+9lavyYEEV
cNsSAPonCrVXOFt9slGTcZUOakGUWzUb+nv6u8W+JDD+Vu/E832X4xT1FE3LpxDy
FuqrIvAxIhFhaZAmunjZlx/jfWardUSVc8is/+9dCopZQ+GssjoP80j812s3wWPc
3kbW20X+fSP9kOhRBx5Ro1/tSUZUfyyIxfQTnJcVPAPooTncaQwywa8WV0yUR0J8
osicfebUTVSvQpmowQTCd5zWSOTOEeAqgJnwQ3DPP3Zr0UxJqyRewg2C/Uaoq2yT
zGJSQnWS+Jr6Xl6ysGHlHx+5fwmY6D36g39HaaECAwEAAaOCAYIwggF+MBIGA1Ud
EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHSFgMBmx9833s+9KTeqAx2+7c0XMB8G
A1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYIKwYBBQUHAQEEajBoMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQAYIKwYBBQUHMAKG
NGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RH
Mi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29t
L0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA9BgNVHSAENjA0MAsGCWCGSAGG/WwC
ATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG
9w0BAQsFAAOCAQEAkPFwyyiXaZd8dP3A+iZ7U6utzWX9upwGnIrXWkOH7U1MVl+t
wcW1BSAuWdH/SvWgKtiwla3JLko716f2b4gp/DA/JIS7w7d7kwcsr4drdjPtAFVS
slme5LnQ89/nD/7d+MS5EHKBCQRfz5eeLjJ1js+aWNJXMX43AYGyZm0pGrFmCW3R
bpD0ufovARTFXFZkAdl9h6g4U5+LXUZtXMYnhIHUfoyMo5tS58aI7Dd8KvvwVVo4
chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN
JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Los Angeles/O=Internet\xC2\xA0Corporation\xC2\xA0for\xC2\xA0Assigned\xC2\xA0Names\xC2\xA0and\xC2\xA0Numbers/CN=www.example.org
issuer=/C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3791 bytes and written 415 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: D47E52A551733EF7629BF646EAD1C5A953FA57DA930EC07C5602936FBCE58F9B
Session-ID-ctx:
Master-Key: FE65C22202FB1552E273A738B94C7DCC52E58D9E8BADCB4C5FB926A363037358A20146C6D7C8C6AB63FEC8AEBB0B0D10
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - f0 1e 9f 13 41 95 4c 0b-72 cf 31 3e c3 aa 1b 97 ....A.L.r.1>....
0010 - 49 5e bc 68 fb 99 61 0b-82 38 c5 4c 4b 17 56 78 I^.h..a..8.LK.Vx
0020 - c8 46 2b 85 eb 8a df 06-bc 48 f8 cb b6 59 71 38 .F+......H...Yq8
0030 - 61 c9 4b b4 60 92 b6 ea-10 82 d4 52 72 24 79 27 a.K.`......Rr$y'
0040 - e8 4a 2e 95 86 12 8e 19-cf db 75 22 54 a0 f1 71 .J........u"T..q
0050 - 66 0e dc e9 56 d8 8b c0-f1 8e 99 56 27 c6 ab 0e f...V......V'...
0060 - c8 e5 ac ad 42 66 0b c4-3f be 60 d0 e4 46 f7 b7 ....Bf..?.`..F..
0070 - a9 07 22 1f 31 30 16 98-78 5a d5 fa db fd c6 3f ..".10..xZ.....?
0080 - b8 05 61 e6 ab 1a c2 7d-46 48 83 66 67 3c 0b 25 ..a....}FH.fg<.%
0090 - 22 14 10 4e ef e1 7b d1-3d 84 c7 fb fd 13 a3 93 "..N..{.=.......
Start Time: 1726371571
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE
curl --resolve 'www.example.com:443:xx.xx.xx.xx' https://www.example.com -vvv
# ping www.example.com
PING www.example.com (93.184.215.14) 56(84) bytes of data.
64 bytes from 93.184.215.14 (93.184.215.14): icmp_seq=1 ttl=43 time=132 ms
# curl --resolve 'www.example.com:443:93.184.215.14' https://www.example.com -vvv
* Added www.example.com:443:93.184.215.14 to DNS cache
* About to connect() to www.example.com port 443 (#0)
* Trying 93.184.215.14...
* Connected to www.example.com (93.184.215.14) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=www.example.org,O=Internet Corporation for Assigned Names and Numbers,L=Los Angeles,ST=California,C=US
* start date: Jan 30 00:00:00 2024 GMT
* expire date: Mar 01 23:59:59 2025 GMT
* common name: www.example.org
* issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1,O=DigiCert Inc,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.example.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Age: 208511
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Sun, 15 Sep 2024 04:37:44 GMT
< Etag: "3147526947+gzip+ident"
< Expires: Sun, 22 Sep 2024 04:37:44 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECAcc (sac/2567)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
* Connection #0 to host www.example.com left intact
示例1:
# curl --resolve 'www.example.com:443:180.101.50.188' https://www.example.com -vvv
* Added www.example.com:443:180.101.50.188 to DNS cache
* About to connect() to www.example.com port 443 (#0)
* Trying 180.101.50.188...
* Connected to www.example.com (180.101.50.188) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=baidu.com,O="Beijing Baidu Netcom Science Technology Co., Ltd",L=beijing,ST=beijing,C=CN
* start date: Jul 08 01:41:02 2024 GMT
* expire date: Aug 09 01:41:01 2025 GMT
* common name: baidu.com
* issuer: CN=GlobalSign RSA OV SSL CA 2018,O=GlobalSign nv-sa,C=BE
* NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN)
* Unable to communicate securely with peer: requested domain name does not match the server's certificate.
* Closing connection 0
curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.
这个 curl
命令尝试连接到 www.example.com
,并使用了 --resolve
选项来直接指定 IP 地址。根据返回的详细日志,连接过程中出现了 SSL/TLS 证书域名不匹配的问题。以下是详细解读:
-
--resolve
选项的使用:-
curl --resolve 'www.example.com:443:180.101.50.188' https://www.example.com -vvv
命令指定了一个自定义的 DNS 解析规则,将www.example.com
域名解析为 IP 地址180.101.50.188
。
-
-
连接建立过程:
-
* Added www.example.com:443:180.101.50.188 to DNS cache
表示curl
将指定的 IP 地址和端口添加到了 DNS 缓存中。 -
* About to connect() to www.example.com port 443 (#0)
表示curl
正准备连接到www.example.com
的 443 端口。 -
* Trying 180.101.50.188...
表示curl
正尝试连接到 IP 地址180.101.50.188
。 -
* Connected to www.example.com (180.101.50.188) port 443 (#0)
表示成功建立了连接。
-
-
SSL/TLS 证书相关信息:
-
* Initializing NSS with certpath: sql:/etc/pki/nssdb
表示正在初始化 NSS(Network Security Services),这是用于处理 SSL/TLS 的库。 -
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
表示curl
使用的 CA 证书文件路径。 -
* Server certificate:
部分列出了服务器的 SSL/TLS 证书信息,包括证书的主题(CN=baidu.com
)、有效期等。
-
-
证书域名不匹配错误:
-
* NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN)
和* Unable to communicate securely with peer: requested domain name does not match the server's certificate.
表示出现了 SSL/TLS 域名不匹配的错误。 - 具体而言,证书的主题是
baidu.com
,而你请求的是www.example.com
。这意味着服务器的证书是为baidu.com
签发的,但你连接到的却是www.example.com
,导致域名不匹配。
-
-
连接关闭:
-
* Closing connection 0
表示curl
正在关闭连接。 -
curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.
是curl
报告的错误,指出由于域名不匹配,无法建立安全连接。
-
解决方案
-
确保正确的域名和证书匹配:
- 确保你请求的域名(
www.example.com
)与服务器的 SSL/TLS 证书中的主题域名匹配。如果你实际访问的应该是baidu.com
,则你应该使用baidu.com
作为目标域名。
- 确保你请求的域名(
-
使用正确的 IP 地址:
- 如果你需要测试某个域名,确保你使用的 IP 地址和域名匹配,并且该 IP 地址上的服务器有正确的证书配置。
-
检查服务器配置:
- 如果你控制服务器,检查服务器的 SSL/TLS 配置,确保它提供了正确的证书,特别是证书中的域名(Common Name 或 Subject Alternative Name)应与请求的域名匹配。
通过这些步骤,你应该能解决这个域名不匹配的问题。
SNI(Server Name Indication)是一个在 HTTPS 协议中非常重要的扩展,它允许客户端在建立 TLS 连接时指定所请求的主机名。
这对于使用 CDN(内容分发网络)和共享 IP 地址的服务器特别重要。
让我们深入探讨 SNI 的作用及其在 CDN 和 HTTPS 配置中的关系。
SNI 和 HTTPS
-
SNI 基本概念:
- SNI 的作用:SNI 扩展允许客户端在发起 TLS 握手时发送主机名。这使得服务器能够根据客户端请求的主机名选择合适的 SSL/TLS 证书来建立加密连接。
- 为什么需要 SNI:在没有 SNI 的情况下,服务器在 TLS 握手开始时无法知道客户端请求的是哪个主机名,从而无法提供正确的证书。这就造成了一个问题:多个主机名(或网站)共享一个 IP 地址时,服务器无法知道要提供哪个证书。
-
SNI 的工作原理:
-
客户端行为:客户端(如浏览器或
curl
)在 TLS 握手的开始阶段,会在“Client Hello”消息中发送请求的主机名。 - 服务器行为:服务器接收到客户端的主机名后,可以选择合适的证书来回应,确保证书中的主机名与客户端请求的主机名匹配。
-
客户端行为:客户端(如浏览器或
CDN 和 SNI
-
CDN 的作用:
- CDN 的基本功能:CDN 通过将内容缓存分布到多个地理位置的服务器上,来加速用户的访问速度,并减轻原始服务器的负担。
- CDN 和 IP 地址共享:多个域名(网站)可能通过同一个 CDN 配置,这样它们可能会共享相同的 IP 地址。CDN 服务器会根据请求的主机名来提供适当的内容。
-
CDN 中的 SNI:
- SNI 的重要性:由于 CDN 服务器通常使用共享 IP 地址来处理来自不同域名的请求,SNI 允许 CDN 确保客户端请求的主机名能够正确映射到 CDN 为每个域名配置的 SSL/TLS 证书。
- 证书管理:使用 SNI,CDN 提供商可以为不同的域名配置不同的证书,即使它们共享同一个 IP 地址。这样,即使多个域名都通过 CDN 进行服务,也能确保每个域名都有正确的 SSL/TLS 证书。
实际例子
假设你通过 CDN 提供两个网站服务,分别是 www.example.com
和 www.example2.com
。它们共享一个 IP 地址。没有 SNI,CDN 服务器在建立 TLS 连接时无法知道客户端请求的是哪个域名,因此可能无法提供正确的证书。然而,通过 SNI,当客户端发起 TLS 连接时,它会在握手过程中告知服务器其请求的主机名。CDN 服务器使用这个信息来选择并提供正确的证书,从而实现安全的 HTTPS 连接。
你的示例中的问题与 SNI
在你给出的 curl
命令的输出中,curl
报告了证书域名不匹配的错误,提示服务器返回了一个与请求的域名不匹配的证书。这个问题通常发生在以下几种情况:
没有使用 SNI: 如果客户端在发起请求时没有指定主机名,服务器可能无法提供正确的证书,尤其是在 CDN 环境中。
DNS 解析问题: 如果你使用
--resolve
选项来指定 IP 地址,但这个 IP 地址上的服务器没有为你请求的域名(www.example.com
)配置正确的证书,那么你会遇到证书域名不匹配的问题。证书配置问题: 服务器或 CDN 配置可能不正确,导致返回了与请求主机名不匹配的证书。
通过确保使用 SNI 和正确配置证书,可以避免此类证书域名不匹配的问题。
示例2:
# curl --resolve 'www.example.com:443:125.77.134.38' https://www.example.com -vvv
* Added www.example.com:443:125.77.134.38 to DNS cache
* About to connect() to www.example.com port 443 (#0)
* Trying 125.77.134.38...
* Connected to www.example.com (125.77.134.38) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -5938 (PR_END_OF_FILE_ERROR)
* Encountered end of file
* Closing connection 0
curl: (35) Encountered end of file
当然,这条 curl
命令和其输出中包含的信息可以从以下几个方面来解读:
命令解析
命令:
curl --resolve 'www.example.com:443:125.77.134.38' https://www.example.com -vvv
-
--resolve 'www.example.com:443:125.77.134.38'
:这个选项告诉curl
使用指定的 IP 地址(125.77.134.38)来访问www.example.com
的 443 端口。也就是说,它会绕过 DNS 查找,直接连接到这个 IP。 -
https://www.example.com
:这是要请求的 URL。 -
-vvv
:这个选项开启了curl
的详细输出模式,以帮助调试。
输出分析
-
DNS 缓存
* Added www.example.com:443:125.77.134.38 to DNS cache
这条消息表明
curl
将指定的 IP 地址和主机名映射添加到了 DNS 缓存中。此步骤是因为使用了--resolve
选项。 -
连接
* About to connect() to www.example.com port 443 (#0) * Trying 125.77.134.38... * Connected to www.example.com (125.77.134.38) port 443 (#0)
curl
正在尝试连接到 IP 地址为 125.77.134.38 的主机上的 443 端口,并成功建立了连接。 -
初始化 NSS
* Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none
curl
正在初始化 NSS(Network Security Services)库来处理 SSL/TLS 证书。它会查找证书颁发机构 (CA) 的证书文件,以验证服务器的证书。 -
错误信息
* NSS error -5938 (PR_END_OF_FILE_ERROR) * Encountered end of file * Closing connection 0 curl: (35) Encountered end of file
这里
curl
遇到了一个 SSL/TLS 错误,具体是PR_END_OF_FILE_ERROR
,这个错误通常表示在 SSL 握手过程中,连接意外地关闭或中断。可能的原因包括:- 服务器端的 SSL/TLS 配置问题。
- 服务器拒绝了连接,或者没有正确地响应 SSL 握手。
- 证书链不完整或证书无效。
可能的解决方案
检查服务器端 SSL/TLS 配置:确保服务器配置正确,并且支持您尝试使用的协议和加密套件。
-
查看服务器证书:使用工具(如
openssl
)检查服务器的证书链是否完整并且有效。例如:openssl s_client -connect www.example.com:443
更新 CA 证书:确保本地的 CA 证书文件是最新的。可能需要更新
ca-bundle.crt
文件。测试其他客户端:使用其他工具或浏览器尝试访问相同的 URL,以确认问题是否特定于
curl
。
这个错误通常需要从服务器端和客户端两个方面去调查,找到问题的根源,并做相应的修复。
示例3:
# curl --resolve 'www.example.com:443:120.92.36.128' https://www.example.com -vvv
* Added www.example.com:443:120.92.36.128 to DNS cache
* About to connect() to www.example.com port 443 (#0)
* Trying 120.92.36.128...
* Connected to www.example.com (120.92.36.128) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.
当然,这条 curl
命令及其输出表明了不同的 SSL/TLS 错误。让我们详细解读一下。
命令解析
命令:
curl --resolve 'www.example.com:443:120.92.36.128' https://www.example.com -vvv
-
--resolve 'www.example.com:443:120.92.36.128'
:指定www.example.com
使用 IP 地址 120.92.36.128 进行连接。 -
https://www.example.com
:请求的 URL。 -
-vvv
:启用详细模式以便于调试。
输出分析
-
DNS 缓存
* Added www.example.com:443:120.92.36.128 to DNS cache
curl
将主机名和指定的 IP 地址添加到了 DNS 缓存中。 -
连接
* About to connect() to www.example.com port 443 (#0) * Trying 120.92.36.128... * Connected to www.example.com (120.92.36.128) port 443 (#0)
curl
成功建立了与 IP 地址 120.92.36.128 的连接,并且连接到了 443 端口(HTTPS)。 -
初始化 NSS
* Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none
curl
正在初始化 NSS(Network Security Services)库,并指定了 CA 证书文件的路径,用于验证 SSL/TLS 证书。 -
错误信息
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG) * SSL received a record that exceeded the maximum permissible length. * Closing connection 0 curl: (35) SSL received a record that exceeded the maximum permissible length.
这里
curl
遇到了SSL_ERROR_RX_RECORD_TOO_LONG
错误。这表明 SSL/TLS 协议中的一个记录(数据包)超出了允许的最大长度。这通常意味着以下几种情况:- 服务器端配置错误:服务器可能将非 SSL/TLS 数据(例如,HTTP 数据)发送到 SSL/TLS 连接上,导致协议混淆。
- 端口配置错误:有可能服务器的 443 端口未配置为 SSL/TLS 服务,或者服务器错误地将 443 端口配置为普通 HTTP 服务。
- 反向代理或负载均衡器问题:如果有反向代理或负载均衡器,它们可能没有正确地处理 SSL/TLS 流量,从而导致这个错误。
可能的解决方案
-
检查服务器配置:确保服务器在 443 端口上正确配置了 SSL/TLS。可以通过使用工具如
openssl
来检查服务器响应:openssl s_client -connect www.example.com:443
确认服务器端口:确保端口 443 确实是用于 SSL/TLS 的,而不是用作其他用途。
检查代理和负载均衡器:如果有使用反向代理或负载均衡器,确保它们正确处理 SSL/TLS 连接。
验证 SSL/TLS 配置:如果你有访问服务器的权限,检查服务器的 SSL/TLS 配置,确保没有配置错误。
这些步骤将帮助你找出并解决造成 SSL_ERROR_RX_RECORD_TOO_LONG
错误的根本原因。
参考
How to troubleshoot SNI enabled endpoints with curl and openssl?
https://www.suse.com/support/kb/doc/?id=000020154
什么是SNI?TLS服务器名称指示如何工作
https://www.cloudflare.com/zh-cn/learning/ssl/what-is-sni/
在 curl 中使用指定 ip 来进行请求 https
https://blog.mozcp.com/curl-request-https-specify-ip/
记一次 HTTPS 抓包分析和 SNI 的思考
https://imlht.com/archives/394/
回源SNI
https://www.ctyun.cn/document/10015932/10150658
SNI (Server Name Indication)
https://zqfan.github.io/2020/01/24/sni/
HTTPS之SNI介绍
https://blog.51cto.com/zengestudy/2170245
SNI可能引发的HTTPS访问异常
https://help.aliyun.com/zh/anti-ddos/how-to-handle-https-access-exceptions-that-occur-when-clients-do-not-support-sni
零基础如何使用CDN
https://www.ctyun.cn/document/10015932/10136415
SNI兼容性导致HTTPS访问异常(服务器证书不可信)
https://help.aliyun.com/zh/waf/https-access-exceptions-arising-from-sni-compatibility
SNI所导致的证书错误问题
https://stephenzhou.net/2018/07/12/sni-https-failed/
CDN回源时网站出现5xx报错的排查方法
https://help.aliyun.com/zh/oss/how-to-troubleshoot-5xx-errors-reported-on-websites-when-cdn-initiates-a-back-to-origin-request
iOS 支持 SNI 方案调研
https://github.com/yuhanle/blogbag/issues/15
浅谈SNI 兼容性导致 HTTPS 出错问题
https://wwww.lvmoo.com/933.love/
HOW WELL DO YOU KNOW SSL?
https://www.ssllabs.com/ssltest/
User Agent Capabilities
https://www.ssllabs.com/ssltest/clients.html
什么是加密的 SNI? | ESNI 如何工作
https://www.cloudflare-cn.com/learning/ssl/what-is-encrypted-sni/