menu E4b9a6's blog
rss_feed
E4b9a6's blog
有善始者实繁,能克终者盖寡。

HTTPS证书Curl报错浏览器正常

作者:E4b9a6, 创建:2024-07-17, 字数:6891, 已阅:401, 最后更新:2024-07-17

在更新证书后,使用 curl 访问我部署的网站发现出现SSL证书错误

Bash
$ curl https://www.chancel.me
curl: (60) SSL certificate problem: unable to get local issuer certificate

在浏览器端访问正常,而 curl 却显示如上错误

使用 openssl 排除一下证书问题:

Bash
openssl s_client -showcerts -connect chancel.me:443

输出如下

Bash
$ openssl s_client -showcerts -connect chancel.me:443
CONNECTED(00000003)
depth=0 CN = chancel.me
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = chancel.me
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 CN = chancel.me
verify return:1
Certificate chain
 0 s:CN = chancel.me
   i:C = AT, O = ZeroSSL, CN = ZeroSSL ECC Domain Secure Site CA
   a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA384
   v:NotBefore: Jun 26 00:00:00 2024 GMT; NotAfter: Sep 24 23:59:59 2024 GMT
-----BEGIN CERTIFICATE--MIIEBjCCA4ugAwIBAgIQLVWuBcqS3xONihxJEXDyMTAKBggqhkjOPQQDAzBLMQsw
CQYDVQQGEwJBVDEQMA4GA1UEChMHWmVyb1NTTDEqMCgGA1UEAxMhWmVyb1NTTCBF
Q0MgRG9tYWluIFNlY3VyZSBTaXRlIENBMB4XDTI0MDYyNjAwMDAwMFoXDTI0MDky
NDIzNTk1OVowFTETMBEGA1UEAxMKY2hhbmNlbC5tZTBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABHQ12fODbsvJMao6BNN2nMGRi0y2jDIBExk43H4yfTFXOYJatYU4
PCW0KN1Cwxgvf4Kb6VIPAEVe789y5GE7H9yjggKFMIICgTAfBgNVHSMEGDAWgBQP
a+ZLzjlHrvZ+kB558DCRkshfozAdBgNVHQ4EFgQUqugludSLW3PChXfCQKJHuXA+
9K0wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMEkGA1UdIARCMEAwNAYLKwYBBAGyMQECAk4wJTAjBggr
BgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQIBMIGIBggr
BgEFBQcBAQR8MHowSwYIKwYBBQUHMAKGP2h0dHA6Ly96ZXJvc3NsLmNydC5zZWN0
aWdvLmNvbS9aZXJvU1NMRUNDRG9tYWluU2VjdXJlU2l0ZUNBLmNydDArBggrBgEF
BQcwAYYfaHR0cDovL3plcm9zc2wub2NzcC5zZWN0aWdvLmNvbTCCAQUGCisGAQQB
1nkCBAIEgfYEgfMA8QB2AHb/iD8KtvuVUcJhzPWHujS0pM27KdxoQgqf5mdMWjp0
AAABkFI2CNgAAAQDAEcwRQIgKIOe2YkObvn+GQd9K8MgCr9j14QqzVnAz2nPr1Ct
Tx8CIQDblmd6EXJlLZ0oQfs2ENK0+09BIsbjeUujfdRrTJVJWwB3AD8XS0/XIkdY
lB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRuAAABkFI2CLsAAAQDAEgwRgIhAJDnLWJs
mc2C6n6nJJt3LTMeu4w5PxNBiOYqGcDTRgDKAiEAi0FrGPsNn75a45OGcVPPc8k3
0BlLv8Ru7DQ08FXy/okwIwYDVR0RBBwwGoIKY2hhbmNlbC5tZYIMKi5jaGFuY2Vs
Lm1lMAoGCCqGSM49BAMDA2kAMGYCMQDmY3cpMfSdL7nfpjy15MNouJSyB5DfE4OG
VVq26xsZUSYt/BsEgCBtibY/Wng4DSACMQCSneonTloCu9LvE2W5rCFsmA2cLpMo
eYfNg7axJK9iDOnP9vTDKQn7X94jHMZT8UM=
-----END CERTIFICATE--Server certificate
subject=CN = chancel.me
issuer=C = AT, O = ZeroSSL, CN = ZeroSSL ECC Domain Secure Site CA
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
SSL handshake has read 1510 bytes and written 409 bytes
Verification error: unable to verify the first certificate
New, TLSv1.2, Cipher is ECDHE-ECDSA-AES256-GCM-SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384
    Session-ID: 868ED2651AF3111499B9B5DBE520E70620DF31F26979CCB6B5C5A899C8CAECEE
    Session-ID-ctx: 
    Master-Key: 812652A6004A21536D8F9BCF39F87B55A374239BC4C59598CAAF98DB6AA940C4101ADE7B7648F33A3FDD743910DAE9E0
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 63 6f d7 c2 ca e2 54 26-74 ca c0 9f cc c3 79 89   co....T&t.....y.
    0010 - 68 a2 be 18 93 07 c2 9d-20 49 50 3f 54 bd 55 d0   h....... IP?T.U.
    0020 - 82 5f b8 99 9f db 05 a6-36 60 35 cf d3 d3 69 67   ._......6`5...ig
    0030 - cf 2e 57 cd e1 2f 1f 33-af 34 a8 e5 7a 0c 4d 7c   ..W../.3.4..z.M|
    0040 - 69 45 35 87 1a 47 74 38-b9 66 04 58 71 89 eb d2   iE5..Gt8.f.Xq...
    0050 - 49 de fc 35 3c 93 90 76-21 d8 d6 a6 5d a5 7b 4b   I..5<..v!...].{K
    0060 - 4e 36 95 bb 4c 98 e6 dc-37 a6 86 f4 cc b0 27 8b   N6..L...7.....'.
    0070 - 0e f1 00 b9 88 7d 23 23-d4 21 68 95 cd dc 94 21   .....}##.!h....!
    0080 - 51 60 38 43 bf 17 cd d0-b5 fb 9c 4b c2 da a9 ab   Q`8C.......K....
    0090 - 22 aa 43 7c a9 80 b0 d1-77 20 c2 28 42 f8 fb f5   ".C|....w .(B...
    00a0 - 9a ef d5 53 d3 f0 f7 1c-74 3f ee 26 b8 4d 93 ef   ...S....t?.&.M..
    00b0 - 2d 13 bf c0 f0 4a aa 22-cf 92 13 26 c9 ee a7 4b   -....J."...&...K

    Start Time: 1721189955
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: yes

40673039367F0000:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:../ssl/record/rec_layer_s3.c:303:

可以看到有 unable to verify the first certificate 的错误输出,这说明证书链不完整,检查 nginx 配置

TEXT
...
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_certificate /home/chancel/.acme.sh/chancel.me_ecc/chancel.me.cer;
ssl_certificate_key /home/chancel/.acme.sh/chancel.me_ecc/chancel.me.key;

ssl_certificate 应该是全链证书,这里写成 chancel.me.cer 证书导致curl无法验证,而浏览器的访问https是自带证书链的

正确配置应该是全链证书

TEXT
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_certificate /home/chancel/.acme.sh/chancel.me_ecc/fullchain.cer;
ssl_certificate_key /home/chancel/.acme.sh/chancel.me_ecc/chancel.me.key;

再次使用 curl 检查,问题已解决

Bash
$ curl -v https://chancel.me
*   Trying 103.99.178.98:443...
* Connected to chancel.me (103.99.178.98) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (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-ECDSA-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=chancel.me
*  start date: Jun 26 00:00:00 2024 GMT
*  expire date: Sep 24 23:59:59 2024 GMT
*  subjectAltName: host "chancel.me" matched cert's "chancel.me"
*  issuer: C=AT; O=ZeroSSL; CN=ZeroSSL ECC Domain Secure Site CA
*  SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: chancel.me]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x55b2d5adcc70)
> GET / HTTP/2
> Host: chancel.me
> user-agent: curl/7.88.1
> accept: */*
> 
< HTTP/2 301 
< server: nginx/1.22.1
< date: Wed, 17 Jul 2024 04:25:45 GMT
< content-type: text/html
< content-length: 169
< location: http://www.chancel.me/
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.22.1</center>
</body>
</html>
* Connection #0 to host chancel.me left intact

[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
gravatar
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]