使用 curl -vvv 簡單查看 HTTPS (TLS 通訊)
您好,我是無能。
前言
HTTPS 本身是 TLS 通訊,正如 HTTP over TLS 所述,HTTP 通訊被 TLS 通訊包裹。如果只關注 TLS 通訊,它將與針對支援 HTTPS 通訊的網域的請求不同,因此可以透過使用curl -vvv進行詳細偵錯,從client hello開始確認該通訊。話雖如此,這是我偶然發現的。
查看
那麼,我們來如下所示窺視一下。
curl -vvv -sl
-vvv # 詳細偵錯選項
-s # 靜音模式,可選
-I # 僅將標頭輸出到標準輸出
那麼我們來看看吧。
$ curl -vvv https://soulminingrig.com/ -sI
19:30:07.019276 [0-x] == Info: [READ] client_reset, clear readers
19:30:07.064770 [0-0] == Info: Host soulminingrig.com:443 was resolved.
19:30:07.065031 [0-0] == Info: IPv6: (none)
19:30:07.065180 [0-0] == Info: IPv4: 167.179.75.206
19:30:07.065413 [0-0] == Info: [HTTPS-CONNECT] adding wanted h2
19:30:07.065587 [0-0] == Info: [HTTPS-CONNECT] added
19:30:07.065718 [0-0] == Info: [HTTPS-CONNECT] connect, init
19:30:07.065881 [0-0] == Info: Trying 167.179.75.206:443...
19:30:07.066065 [0-0] == Info: [HTTPS-CONNECT] connect -> 0, done=0
19:30:07.066197 [0-0] == Info: [HTTPS-CONNECT] Curl_conn_connect(block=0) -> 0, done=0
19:30:07.066400 [0-0] == Info: [HTTPS-CONNECT] adjust_pollset -> 1 socks
19:30:07.083945 [0-0] == Info: [HTTPS-CONNECT] connect -> 0, done=0
19:30:07.084308 [0-0] == Info: [HTTPS-CONNECT] Curl_conn_connect(block=0) -> 0, done=0
19:30:07.084750 [0-0] == Info: [HTTPS-CONNECT] adjust_pollset -> 1 socks
19:30:07.095330 [0-0] == Info: [SSL] cf_connect()
19:30:07.095574 [0-0] == Info: [SSL] ossl_connect, step1
19:30:07.098502 [0-0] == Info: ALPN: curl offers h2,http/1.1
19:30:07.098614 [0-0] == Info: [SSL] ossl_connect, step2
19:30:07.099069 [0-0] => Send SSL data, 5 bytes (0x5)
0000: .....
19:30:07.099205 [0-0] == Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):
19:30:07.099360 [0-0] => Send SSL data, 1563 bytes (0x61b)
~省略~
於是,出現了大量的字串...
通訊確認
在這裡,在 443 埠上完成了 DNS 名稱解析
19:30:07.064770 [0-0] == Info: Host soulminingrig.com:443 was resolved.
在這裡,請求並建立了 h2、HTTP/2 連線
19:30:07.065413 [0-0] == Info: [HTTPS-CONNECT] adding wanted h2
19:30:07.065587 [0-0] == Info: [HTTPS-CONNECT] added
19:30:07.065718 [0-0] == Info: [HTTPS-CONNECT] connect, init
19:30:07.065881 [0-0] == Info: Trying 167.179.75.206:443...
19:30:07.066065 [0-0] == Info: [HTTPS-CONNECT] connect -> 0, done=0
然後終於 SSL/TLS 通訊開始了
19:30:07.095330 [0-0] == Info: [SSL] cf_connect()
19:30:07.095574 [0-0] == Info: [SSL] ossl_connect, step1
19:30:07.098502 [0-0] == Info: ALPN: curl offers h2,http/1.1
19:30:07.098614 [0-0] == Info: [SSL] ossl_connect, step2
19:30:07.099069 [0-0] => Send SSL data, 5 bytes (0x5)
然後,在 TLS1.3 中,協定上的client hello的 TLS 握手終於開始了!
19:30:07.099205 [0-0] == Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):
作為客戶端的發送,封包發送開始了
19:30:07.099205 [0-0] == Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):
19:30:07.099360 [0-0] => Send SSL data, 1563 bytes (0x61b)
0000: .........r.q.....GC...._4....k..C.P... ..?...x...HT..09..z4b....
0040: ..,9....<.......,.0.........+./...$.(.k.#.'.g.....9.....3.....=.
0080: <.5./..................soulminingrig.com........................
00c0: .............h2.http/1.1.........1.....6.4......................
0100: ...............................+........-.....3...........RIw..7
此時,請求本身中網域soulminingrig.com以明文發送,如果伺服器支援 SNI,則可以保持一致性
19:30:07.105068 [0-0] == Info: [SSL] ossl_bio_cf_out_write(len=1568) -> 0, 1568
19:30:07.105244 [0-0] == Info: [SSL] ossl_bio_cf_in_read(len=5) -> 81, 0
19:30:07.105355 [0-0] == Info: [SSL] ossl_populate_x509_store, path=/etc/ssl/certs/ca-certificates.crt, blob=0
19:30:07.114557 [0-0] == Info: CAfile: /etc/ssl/certs/ca-certificates.crt
19:30:07.114669 [0-0] == Info: CApath: none
19:30:07.114768 [0-0] == Info: [SSL] SSL_connect() -> err=-1, detail=2
19:30:07.114903 [0-0] == Info: [SSL] SSL_connect() -> want recv
19:30:07.115050 [0-0] == Info: [SSL] cf_connect() -> 0, done=0
此時,客戶端已準備好其擁有的根憑證
連線尚未建立
對於 Let’s Encrypt 來說,這似乎是ISRG Root X1
Chain of Trust - Let’s Encrypt
$ grep -A 3 "ISRG Root X1" /etc/ssl/certs/ca-certificates.crt
# ISRG Root X1
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
然後Server Hello回來了!
19:30:07.178149 [0-0] == Info: [SSL] ossl_bio_cf_in_read(len=122) -> 0, 122
19:30:07.178363 [0-0] == Info: TLSv1.3 (IN), TLS handshake, Server hello (2):
19:30:07.178583 [0-0] <= Recv SSL data, 122 bytes (0x7a)
0000: ...v....y'...>........&.....,5O....... ..?...x...HT..09..z4b....
0040: ..,9.........+.....3.$... F........`~..l[..uhE..F.P?..V..6
19:30:07.179600 [0-0] == Info: [SSL] ossl_bio_cf_in_read(len=5) -> 0, 5
19:30:07.179730 [0-0] <= Recv SSL data, 5 bytes (0x5)
然後,伺服器端傳回了憑證
19:30:07.183139 [0-0] <= Recv SSL data, 2049 bytes (0x801)
0000: ...........0...0.................g...4...C..0...*.H.=...021.0...
0040: U....US1.0...U....Let's Encrypt1.0...U....E50...250714140356Z..2
0080: 51012140355Z0.1.0...U....soulminingrig.com0Y0...*.H.=....*.H.=..
00c0: ..B...V...$.....}.hN.f......n@F&...GR.....-.....?z]6d.=..<..eu..
使用伺服器端擁有的私鑰,簽名已發送過來
0000: .
19:30:07.199683 [0-0] == Info: TLSv1.3 (IN), TLS handshake, CERT verify (15):
19:30:07.199941 [0-0] <= Recv SSL data, 79 bytes (0x4f)
在這裡,TLS 握手終於結束並建立了
19:30:07.202057 [0-0] == Info: TLSv1.3 (IN), TLS handshake, Finished (20):
不常見的 TLS 握手
起初,即使我問 ChatGPT 等工具,他們也說要使用 Wireshark 等工具,但 Wireshark 中有很多雜訊,所以我一直在想有沒有什麼可以簡單確認的方法,然後我突然想到並嘗試了一下,結果成功了。
作為 TLS 握手失敗的模式,您也可以嘗試在以下網站確認,可能會很有趣。
badssl.com
$ curl -vvv -sl https://wrong.host.badssl.com/
19:50:53.161049 [0-x] == Info: [READ] client_reset, clear readers
19:50:53.202041 [0-0] == Info: Host wrong.host.badssl.com:443 was resolved.
19:50:53.202233 [0-0] == Info: IPv6: (none)
19:50:53.202326 [0-0] == Info: IPv4: 104.154.89.105
19:50:53.202496 [0-0] == Info: [HTTPS-CONNECT] adding wanted h2
~~~
19:50:53.759424 [0-0] == Info: SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 / secp256r1 / rsaEncryption
19:50:53.759894 [0-0] == Info: ALPN: server accepted http/1.1
19:50:53.760124 [0-0] == Info: [SSL] ossl_connect, step3
19:50:53.760337 [0-0] == Info: Server certificate:
19:50:53.760541 [0-0] == Info: subject: CN=*.badssl.com
19:50:53.760763 [0-0] == Info: start date: Jul 15 20:02:58 2025 GMT
19:50:53.761029 [0-0] == Info: expire date: Oct 13 20:02:57 2025 GMT
19:50:53.761406 [0-0] == Info: subjectAltName does not match hostname wrong.host.badssl.com
19:50:53.761853 [0-0] == Info: SSL: no alternative certificate subject name matches target hostname 'wrong.host.badssl.com'
19:50:53.762409 [0-0] == Info: [SSL] cf_connect() -> 60, done=0
在這種情況下,因為已經取得了*.badssl.com的憑證,而應該取得*.host.badssl.com的萬用字元憑證,所以因為錯誤而發出警告了。
那麼下次再見。請多關照。