Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

青灯夜游
青灯夜游ke hadapan
2022-03-01 09:57:243295semak imbas

Artikel ini akan membawa anda melalui protokol QUIC dan mengambil protokol QUIC sebagai contoh untuk bercakap tentang cara mempelajari protokol rangkaian Saya harap ia akan membantu semua orang!

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Dalam artikel sebelumnya tentang s2n-quic, seorang pembaca bertanya kepada saya cara mempelajari protokol rangkaian seperti QUIC. Bagi kebanyakan pengamal Internet, walaupun mereka berurusan dengan Internet setiap hari, beberapa orang mengambil berat tentang butiran protokol rangkaian di bawah HTTP Selalunya, ia sudah cukup untuk mempunyai pemahaman umum dan mengetahui cara menggunakannya. Jika anda tidak tahu tentang QUIC, maka gambar berikut boleh membantu anda memahami dengan baik kedudukan QUIC dalam ekosistem HTTP/3:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Jadi, jika anda saya hanya ingin mengetahui lebih lanjut tentang QUIC Bagaimana untuk bermula?

Sebagai bekas pembangun protokol rangkaian dan peralatan rangkaian, pengalaman saya sendiri ialah: mulakan dengan RFC, ditambah dengan penangkapan paket wireshark, untuk menguasai protokol sasaran dengan cepat.

Untuk QUIC, perkara pertama yang perlu kita baca ialah RFC9000. Membaca perjanjian itu sangat membosankan dan memerlukan sedikit kesabaran Jika Bahasa Inggeris anda tidak begitu baik, anda boleh menggunakan Terjemahan Google untuk menterjemahkannya ke dalam bahasa Cina dan menyemak imbasnya dengan cepat (bacaan meluas). Bacaan pertama adalah untuk memahami konsep utama dan proses utama.

Selepas itu, kita boleh menulis program menggunakan protokol QUIC, dan kemudian menangkap paket melalui wireshark Dengan mengkaji mesej sebenar dan membandingkannya dengan kandungan protokol RFC (bacaan intensif), kita boleh memperolehi. pemahaman yang lebih mendalam tentang intipati protokol.

Kami akan membina klien dan pelayan gema berdasarkan kod dalam artikel sebelumnya. Untuk memudahkan semua orang membaca, saya juga telah menyiarkan kod tersebut. Pelajar yang berminat boleh mengklon repo saya dan menjalankan kod klien/pelayan.

Kod pelanggan (lihat github: tyrchen/rust-training/live_coding/quic-test/examples/client.rs):

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Kod pelayan (lihat github: tyrchen/rust-training/live_coding/quic-test/examples/server.rs):

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Kedua-dua ini kepingan kod membina pelayan gema yang paling mudah. Kita boleh menggunakan wireshark untuk memantau paket UDP di bawah antara muka gelung balik tempatan dan menangkap paket. Perlu diingatkan bahawa untuk trafik yang menggunakan protokol TLS seperti QUIC, walaupun paket ditangkap, hanya beberapa paket pertama boleh dibaca, dan paket berikutnya disulitkan dan tidak boleh dibaca. Oleh itu, apabila kami membina klien/pelayan, kami perlu mencari cara untuk menangkap kunci sesi yang dirundingkan antara pelayan dan klien untuk wireshark menyahsulit. Secara amnya, perpustakaan SSL/TLS menyediakan fungsi ini. Sebagai contoh, untuk Rustls, kita boleh menggunakan key_log dalam tls config. Jika anda melihat dengan teliti pada kod pelayan di atas, anda akan melihat ayat ini:

let config = Builder::new()
    .with_certificate(CERT_PEM, KEY_PEM)?
    .with_key_logging()? # 使能 keylogging
    .build()?;

Selepas menggunakan key_log, apabila memulakan pelayan, kita hanya perlu menentukan SSLKEYLOGFILE:

SSLKEYLOGFILE=session.log cargo run --example server

Selepas penangkapan paket selesai, buka keutamaan wireshark, pilih protokol TLS, dan letakkan laluan log dalam:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Berikut ialah klien lengkap Menangkap paket yang berinteraksi dengan pelayan, kami melihat bahawa semua "muatan yang dilindungi" dipaparkan seperti biasa:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Oleh kerana klien gema kami hanya melakukan tindakan paling mudah (hanya satu aliran dwiarah dibuka), jadi melalui ini penangkapan paket, kita boleh memberi tumpuan kepada mengkaji proses mewujudkan sambungan melalui protokol QUIC.

Paket pertama yang dihantar oleh pelanggan

Mari kita lihat paket pertama yang dihantar oleh pelanggan:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Mesej ini mengandungi banyak maklumat. Pertama sekali, tidak seperti jabat tangan TCP, paket pertama QUIC adalah sangat besar, sebanyak 1200 bait (protokol memerlukan muatan UDP sekurang-kurangnya 1200 bait), termasuk pengepala QUIC, bingkai CRYPTO 255 ​​bait dan 890- bingkai PADDING bait. Seperti yang anda boleh lihat dari pengepala, jenis pakej QUIC ini adalah Permulaan.

Jenis mesej QUIC

Untuk paket QUIC, Pengepala adalah teks biasa dan semua muatan bingkai berikutnya adalah teks sifir (kecuali pengepala beberapa pakej ). Kami melihat bahawa paket pertama ini ialah mesej Pengepala Panjang Dalam Bahagian 17.2 RFC9000, Paket Pengepala Panjang ditakrifkan:

Long Header Packet {
   Header Form (1) = 1,
   Fixed Bit (1) = 1,
   Long Packet Type (2),
   Type-Specific Bits (4),
   Version (32),
   Destination Connection ID Length (8),
   Destination Connection ID (0..160),
   Source Connection ID Length (8),
   Source Connection ID (0..160),
   Type-Specific Payload (..),
 }

Jika anda berminat, anda boleh membaca sendiri bab RFC yang sepadan. Untuk mesej Pengepala Panjang, terdapat jenis berikut:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

既然有 Long Header packet,那么就有 Short Header packet,Short Header packet 目前的版本只有一种:

1-RTT Packet {
   Header Form (1) = 0,
   Fixed Bit (1) = 1,
   Spin Bit (1),
   Reserved Bits (2),
   Key Phase (1),
   Packet Number Length (2),
   Destination Connection ID (0..160),
   Packet Number (8..32),
   Packet Payload (8..),
}

为什么需要 connection id?

在我们捕获的这个报文头中,我们看到有 Source Connection ID(SCID)和 Destination Connection ID(DCID)这个新的概念。你也许会好奇:QUIC 不是基于 UDP/IP 的协议么?底层的协议已经有五元组(src ip / src port / dst ip / dst port / protocol)来描述一个连接(connection),为什么还需要 connection id 这样一个新的概念?

这是为了适应越来越多的移动场景。有了 QUIC 层自己的 connection id,底层网络(UDP/IP)的变化,并不会引发 QUIC 连接的中断,也就是说,你从家里开车出门,即便手机的网络从 WIFI(固网运营商分配给你的 IP)切换到蜂窝网络(移动运营商分配给你的 IP),整个 UDP/IP 网络变化了,但你的 QUIC 应用只会感受到细微的延迟,并不需要重新建立 QUIC 连接。

从这个使用场景来看,QUIC 底层使用无连接的 UDP 是非常必要的。

首包中就包含了 TLS hello?

我们接下来看看 CRYPTO frame:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

可以看到,QUIC 在建立连接的首包就把 TLS Client Hello 囊括在 CRYPTO frame 中。并且使用的 TLS版本是 1.3。在 Client Hello 的 extension 中,QUIC 协议使用了一个 quic_transport_parameters 的 extension,用来协商 QUIC 自己的一些初始值,比如支持多少个 stream,这个连接中可以最多使用多少个 active connection id 等等。

QUIC 支持哪些 frame?

现在我们已经见到了两种 Frame:CRYPTO 和 PADDING。下表中罗列了 QUIC 所有支持的 frame:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

服务器的回包

我们来看 server 的回包:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

这里有一些新东西。首先,一个 UDP 包内部可以包含若干个 QUIC payload,我们看到 server 回复了一个 QUIC Initial 报文和一个 QUIC Handshake 报文。在 Initial 报文中,我们看到了一个 ACK frame,可见 QUIC 虽然构建于 UDP,但在 QUIC 协议内部构建了类似 TCP 的确认机制。

我们之前看到,在 Initial 报文的 CRYPTO frame 中,客户端发送了 TLS Client Hello,同样的,服务器在 Initial 报文的 CRYPTO frame 中发送了 TLS Server Hello。这个我们就略过不看。

在 Handshake 报文中:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

服务器发送了自己的证书,并结束了 TLS handshake。

客户端结束 Handshake

我们再看第三个包,客户端发送给服务器结束 TLS 握手:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

这个包依旧包含两个 QUIC 报文,其中第一个就是一个 ACK frame,来确认收到了服务器的 Server Hello 那个 QUIC 报文;第二个包含一个 ACK frame,确认服务器的 Handshake,随后有一个 CRYPTO frame 结束客户端的 TLS handshake。

TLS 握手结束之后,客户端和服务器就开始应用层的数据交换,此刻,所有数据都是加密的。

客户端发送一个 “hello” 文本

在我们的  echo client/server 代码中,客户端连接到服务器后,就可以等待用户在 stdin 的输入,然后将其发送到服务器。服务器收到客户端数据,原封不动发回,客户端再将其显示到 stdout 上。在这个过程的前后,客户端和服务器间有一些用于连接管理的 QUIC 报文,比如 PING。我们就略过,只看发送应用层数据的报文。下图是客户端发送的包含 “hello” 文本的报文:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Seperti yang anda lihat, mesej QUIC di sini ialah paket Pengepala Pendek Selain bingkai ACK, ia juga mempunyai bingkai STREAM. Dua digit terendah ID strim strim ini ialah 00, yang mewakili strim dwiarah yang dimulakan pelanggan. Memandangkan dua bit digunakan untuk menyatakan jenis, aliran QUIC mempunyai jenis berikut:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Mari kita lihat panjang(6) dan Data(68 65 6c 6c 6f 0a daripada bingkai STREAM ). Jika kandungan dalam Data dinyatakan dalam ASCII, ia betul-betul "hello", dan panjangnya ialah 6 bait.

Pelayan membalas dengan teks "hello"

Akhirnya pelayan bergema kembali:

Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC

Ini betul-betul sama dengan mesej di atas, jadi saya tidak akan menerangkannya.

Sage Moment

Saya percaya pengenalan di atas kepada QUIC berdasarkan penangkapan paket wireshark boleh memberi anda pemahaman awal tentang protokol QUIC. tahu. Dalam artikel terakhir, kami mengatakan bahawa QUIC menyokong pemultipleksan dan menyelesaikan masalah penyekatan kepala baris gilir pada lapisan pengangkutan. Melalui pengenalan artikel ini, bolehkah anda menjawab dua soalan berikut?

  • Jenis bingkai manakah yang QUIC gunakan untuk pemultipleksan?

  • Bagaimanakah QUIC menyelesaikan sekatan kepala baris gilir pada lapisan pengangkutan?

Cadangan berkaitan: keselamatan pelayan web

Atas ialah kandungan terperinci Mari lihat cara mempelajari protokol rangkaian melalui protokol QUIC. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:微信公众号-程序人生. Jika ada pelanggaran, sila hubungi admin@php.cn Padam