میخوام در رابطه با HTTP over QUIC صحبت کنم، از مشکلات و مسیر پیشرفت HTTP بگم و بعد نظرات شخصیم رو بر اساس شواهد در رابطه با جایگاهش در ایران بیان کنم.
این رو قبلش بگم که تا آخر ماجرا منظورم از QIUC و HTTP/3 مفاهیم زیر هست:
وقتی میگم QUIC منظورم پروتکل انتقالی هست که توسط IETF داره روش کار میشه اولین نسخه اون توسط گوگل توسعه پیدا کرد که طرفای 2013 منتشر شد و تا حدودای 2016 روش کار کردن و بعدش هم برخی از اعضای اون تیم رفتن با IETF همکاری کنن ... پس اون نسخه قدیمی تحت عنوان gQUIC شناخته میشه. جزئیات نسخه جدید رو تحت عنوان QUIC و یا QUIC v2 میتونید پیدا کنید.
وقتی میگم HTTP/3 منظور نسخه سوم از پروتکل HTTP هست که روی لایه انتقال QUIC پیاده سازی شده.
نسخه اول HTTP توی سال 1997 معرفی شد، بعدش یه فاصله طولانی داشتیم و توی 2015 نسخه دومش منتشر شد و بلافاصله بعدش داستانهای نسخه سوم شروع شد.
توی نسخه اول دادهها به صورت متن واضح و در قالب ASCII ارسال میشن، نسخه دوم (بیشتر بدونید) و سوم به صورت رمزنگاری شده و در قالب باینری.
اولین روش پیاده سازی به صورت HTTP over TCP بود و بعدش هم HTTPS شروع شد که اساس HTTP/2 رو شکل داد.
پروتکل TCP برای خیلی سال پیشه، اگرچه خب دستخوش تغییراتی هم شده اما ماهیت کلی اون اینه که بستهها مثل زنجیر هستن و یه سلام و احوالپرسی طولانی باید انجام بشه که تازه بعدش بتونی شروع کنی به ارسال داده. این جوک گویای همه چیزه:
Hello, would you like to hear a TCP joke?
Yes, I'd like to hear a TCP joke.
OK, I'll tell you a TCP joke.
OK, I'll hear a TCP joke.
Are you ready to hear a TCP joke?
Yes, I am ready to hear a TCP joke.
OK, I'm about to send the TCP joke. It will last 10 seconds, it has two characters, it does not have a setting, it ends with a punchline.
OK, I'm ready to hear the TCP joke that will last 10 seconds, has two characters, does not have a setting and will end with a punchline.
I'm sorry, your connection has timed out... ...Hello, would you like to hear a TCP joke?
تازه مسئله TCP HOL Blocking هم داریم، یعنی فرض کنید یکی از بستهها کند بشه و دیرتر برسه؛ همه بستههای قبلی هم مسدود میشن.
تازه این روزها دیگه بخش بزرگی از وب HTTPS هست، یعنی ما دیگه فقط TCP خالی رو نداریم بلکه TLS هم باید یه دور سلام احوالپرسی کنه. درواقع RTT یا همون مجموع مدت زمانی که طول میکشه تا یه سیگنال ارسال بشه، و جواب اینکه «بله ما سیگنالتون رو دریافت کردیم»؛ دریافت بشه، خیلی زیاده.
الان یه درخواست عادی وب با TLS نسخه 1.2 یا قبل تر، چهارتا RTT انجام میده و اگه دوباره به همون وبسایت وصل بشید 3 تا. ناگفته نماند شما قبلش باید درخواست DNS بزنی و اونم خودش RTT داره مخصوصا اگه DoH استفاده کنید 3 یا 4 RTT دیگه انجام میشه - منتها خب آدم عاقل DNS رو کش میکنه یا حالا سیستمعامل تا یه حدی براش کش میکنه. (اینجا درمورد DoH نوشتم)
صحبتهای این بخش، HTTP/1.1 و هرچی قبلش بوده رو شامل میشه، به طور کلی برای سرعت بخشیدن به وب ایده این بود که بیایم چندتا اتصال کوتاه TCP به صورت موازی بزنیم به سرور که معمولا هم 6 تا بیشتر نمیشد. یعنی شما حساب کن اون همه عکس و جاوا اسکریپت و CSS (خدا نکنه یکی حالا gif گذاشته بود یا آهنگ پخش میکرد وقتی وارد سایت میشدی ...) باید همشون توی 6 تا اتصال میاومدن روی کامپیوتر کاربر.
فاصله زمانی توسعه نسخه 1 و 2 خیلی زیاده برای همینه مباحثی مثل css sprites و چپوندن همه کدهای front-end توی یه فایل بزرگ مد شد، ایده این بود که توی این چندتا اتصال، سریع جمع و جور کنیم بره. که خب کار بدی نبود مرورگرها خیلی از این فایلها رو کش میکنن شما یک بار دانلود کنی تا یه مدت طولانی اعتبار داره.
اما غافل از اینکه، بستههای TCP یکهو که با تمام سرعت ارسال نمیشه! کمکم، زیاد میشه تا وقتی که میرسه به حد نهایی (اگه تورنت انجام داده باشین احتمالا متوجه شدین سرعت اولش کمه بعد یکهو زیاد میشه، یه همچین داستانی هست - حالا نه دقیقا - ولی برای درک بهتر اونطوری بهش فکر کنید).
بعلاوه اون جوک TCP یادتونه؟ چقدر طول میکشید تا اتصال TCP وصل بشه ! حالا فکر کن بخوای تندتند سلام احوالپرسی کنی! این که کند تره!!
و در نهایت HTTP HOL Blocking هم وجود داره! یعنی شما نمیتونی یقین پیدا کنی کدوم یک از اون 6 تا اتصال سریع تره تا درخواست رو از اون طریق بفرستی. در نتیجه به طور میانگین یک اتصال میزدن مرورگرها.
خب توی نسخه دوم، یک اتصال TCP به چندین جریان موازی تقسیم میشه که اینجا دیگه TCP HOL Blocking اتفاق میافته و بالاتر گفتم. شما اگه یکی از این جریان ها رو از دست بدی بقیه شونم بلاک میشن. به تعبیری سرعت شما برابره با سرعت کند ترین جریان توی اون اتصال TCP.
بحث RTT هم وجود داره که خب اونم اشاره کردم، حالا البته TLS 1.3 معرفی شد که هزینه اتصال جدید و اتصال مجدد ثابته (هردو سه تا RTT) بعد یه بحث دیگه مطرح شد تحت عنوان 0-RTT یعنی درواقع دفعات بعدی که سایت رو بازدید میکنی دیگه Full TLS Handshake انجام نده. که فعال کردن این ویژگی باعث میشه آدمای بد بتونن Replay Attack انجام بدن. (یکی درخواست رمزنگاری شده شما رو دریافت میکنه، اونو دوباره میفرسته به سرور اصلی و وانمود میکنه که شماست -- پایین تر توضیح میدم تاثیرش توی ایران رو).
اما پروتکلی که درحال استاندارد شدنه. یک لایه انتقال هست و درواقع HTTP/3 به عنوان Application Layer روی این لایه سوار میشه.مجموع این حرفها یعنی ممکنه DNS over QUIC هم بیاد و خیلی چیزای دیگه !!
برخلاف TCP؛ این پروتکل جدید اتصالات رو به یک IP مرتبط نمیکنه و به جاش از Connection-ID استفاده میکنه که یعنی اگه از روی WIFI بریم روی 4G خودش میفهمه که ما همون اتصال قبلی هستیم.
این پروتکل مشکل HOL Blocking نداره، درواقع جریانها موازی و ناپیوسته ایجاد میشن برای همین اگر چندتا جریان داده دچار مشکل بشن، فقط همون چندتا هستن که دیرتر میرسن و بقیه به مسیرشون ادامه میدن بعلاوه خب چون از TLS1.3 استفاده میکنه میتونه یک اتصال با Zero-RTT ایجادکنه و خب این باعث میشه مثل TFO بتونیم ارسال داده رو زودتر آغاز کنیم (و همزمان معایب TFO رو نداشته باشیم -- در ادامه بحث رو باز میکنم).
اما خب QUIC یه لایه انتقال هست روی یک لایه انتقال دیگه (UDP) حالا درسته به مراتب سریعتر از TCP اما خود پروتکل UDP هنوزم نیاز به بهینه سازی داره. جدای از این بحثها QUIC یک user space protocol هست. یعنی هرکسی میتونه (با رعایت قوانین حاکم) نسخه خودش رو بزنه که بازم «میتونه» با نسخه یه شرکت/گروه دیگه چند درجه متفاوت باشه. مسئله ای که ما سر DoH و DoT داشتیم و داریم اینجا باز تکرار شده.
اینکه هرکسی بتونه نسخه خودشو بزنه در اوایل خوبه اما در آینده ممکنه توروالدز تصمیم بگیره یکی از این نسخهها رو توی کرنل قرار بده بعد مایکروسافت یه نسخه کمی متفاوت تر رو قرار بده ... اونوقت میشه با آنالیز تفاوت بستهها فهمید کی ویندوز داره و کی لینوکس (بلایی که سر TCP اومده، پکتها توی ویندوز و لینوکس تفاوتهایی دارن که تشخیص سیستمعامل رو ممکن میکنه)
اگه به تصویر دقت کنید میبینید که TLS داخل QUIC استفاده میشه یعنی ما داده ها رو به لایه بالاتر انتقال نمیدیم بلکه یک سری از پیغامهای TLS رو مستقیم داخل خود QUIC استفاده میکنیم این یعنی کتابخانههای موجود برای TLS باید بروزرسانی بشن و این سبک جدید از «احوالپرسی» رو پشتیبانی کنن. و خود این موضوع به تنهایی یک بحث خیلی گسترده هست که من قبلا درموردش توییت هایی زدم.
بحث اصلی اینه که پیداکردن کتابخانه(ها)ای که بهت اجازه بدن «تمام فیلدهای TLS» رو تنظیم کنی، سخته. شاید بشه uTLS رو مثال زد اما حتی اونم جای خطا داره. فکر کن یه API جدید نیازه که به علت پیشرفت سریعتر QUIC؛ قطعا کامل نیست. این بحث انقدر مهمه که حتی کتابخانه پولی هم در اومده براش.
تا اینجای کار چون فقط HTTP/3 رو داریم که روی QUIC پیاده شده به نحوی میشه گفت این دو برابر هستن. اما یه سوال پیش میاد، چطوری بفهمیم
https://virgool.io
میخواد با QUIC ارتباط برقرار کنه یا با HTTP over TCP؟ - جوابش فیلد Alt-Svc هست. فرض کنید آدرس یه محله به شما دادن ولی نمیدونید کدوم پلاک مال خونهای هست که مد نظرشماست. از یه نفر میپرسید «ببخشید منزل فلانی کجاست؟» و اون شخص به سمت منزل «اشاره» میکنه.
این فیلد «اشاره میکنه» که راستی، من روی UDP/443 هم سرویس میدم. پس اولین درخواست شما (حداقل در لحظه نوشتن این مقاله) یک درخواست TCP هست و بعدش با خوندن Alt-Svc مرورگر میفهمه که سرور شما از QUIC پشتیبانی میکنه. در آینده میتونه برعکس باشه... و بگه من تا فلان روز و فلان ساعت از سرویس HTTP Over TCP پشتیبانی میکنم.
این قسمت رو گذاشتم آخر چون حکم نتیجه گیری داره و اینکه بیشترش نظر شخصی من هست بر اساس شواهد موجود.
اول اینکه، اینترنت کلی مسیریاب و فایروال و اصطلاحا Middlebox داره که شرکتها (چه داخل ایران و چه از دید بین المللی) هزینه زیادی بابتشون دادن. و اشاره کردم فاصله بین HTTP/1 تا الان خیلی زیاده در نتیجه دستگاههای زیادی هستن که باید بروز بشن (حالا دیر یا زود یا اینکه اصلا ممکنه بروز نشه بماند).
دوم اینکه مفهومی هست به اسم "ossification" یا استخراج و بهینه سازی. به این معنا که دستگاه مثلا برای استخراج و بهینه کردن HTTP/1 الگوریتم داره ولی HTTP/2 رو تشخیص نمیده در نتیجه خیال میکنه همون نسخه قبلیه و کار رو خراب میکنه. برای همینه که HTTP/2 استفاده از TLS رو الزامی کرده تا نشه دستکاری بیجا انجام داد. شما هنوزم میتونی برای آزمایش کردن اون رو به صورت متن واضح ارسال کنی!
بالاتر گفتم TFO ایراد داره، خب این ویژگی ده سال پیش اضافه شده به TCP و اینطوریه که یه سری بایت اضافی ارسال میکنه که بگه من درخواست TFO هستم بعد خیلی از Middlebox ها بروز نشدن یا به دلایلی نمیخوان که اینو به رسمیت بشناسن در نتیجه drop میشه. حالا کلاینت بازم باید یه درخواست TCP معمولی بزنه و دوباره کاری میشه. برای همین میزان خیلی کمی از TFO استفاده میکنن و موفق نبود. (یه دلیل دیگه رو توی توییتهام گفتم).
سوم اینکه، فعلا شواهد کافی نیست که یقین پیدا کرد QUIC در ایران عمدا قطع میشه یا Middleboxها بروز نشدن. صادقانه بگم، استفاده از QUIC به عنوان لایه انتقال در ابزارهای ضدسانسور قبلا هم انجام شده. و خب به خاطر استفاده از zero-RTT میشه بهش Replay Attack زد که یقین پیدا کرد این اتصال فیلترشکن هست یا نه (البته این موش و گربه بازی ادامه داره، میشه جلوش رو گرفت). یا اصلا به خاطر استفاده بسیار کمش به طور کلی مسدود کنن.
هرچند deploy کردن QUIC روی Edge Server ها و مرورگرها کاری به مراتب راحت تره، اتفاقا کلاودفلر همین الان از این پروتکل پشتیبانی میکنه. شاید اگه ابرآروان و سایر CDN های ایرانی هم پیش قدم بشن بتونیم امیدوارتر بشیم.
اما خب هیچ کدوم از این تکنولوژیهای جدید «گلوله نقره ای» نیستن، مثلا قبلاهم TLS 1.3 باعث خراب شدن Middleboxها شده. و راههایی هست که کلاینت رو «مجبور کرد» که از TLS 1.2 استفاده کنه که به بهانه اون حتی از ESNI محروم بشیم!