Быстрый просмотр HTTPS (TLS-соединения) с помощью curl -vvv

12 min

language: ja bn en es hi pt ru zh-cn zh-tw

Здравствуйте, я некомпетентен.

Введение

Сам по себе HTTPS — это TLS-соединение, и, как следует из HTTP over TLS, HTTP-соединение обернуто в TLS-соединение. Если сосредоточиться только на TLS-соединении, это будет отличаться от запроса к домену, поддерживающему HTTPS-соединение. Поэтому вы можете проверить это соединение, начиная с client hello, выполнив подробную отладку с помощью curl -vvv. Впрочем, я нашел это случайно.

Давайте посмотрим

Итак, давайте заглянем следующим образом.

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)
~省略~

И вот, появилось огромное количество строк...

Проверка связи

Здесь было выполнено разрешение имен DNS для порта 443.

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)

И вот, наконец, началось TLS-рукопожатие client hello по протоколу TLS 1.3!

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.
Цепочка доверия - 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 как wildcard-сертификат, поэтому он ругается на ошибку.

До новых встреч. С наилучшими пожеланиями.

Related Posts