پرش به مطلب اصلی

RealityServer

RealityServer tunnel سمت server برای Reality v2 است. هر line ابتدا visitor محسوب و به شاخه destination فرستاده می‌شود و binding واقعی TLS به‌صورت passive استخراج می‌گردد. TLS 1.3 فقط پس از handoff احرازشده request/ack/confirm شاخه visitor را می‌بندد و همان line را به next محافظت‌شده می‌برد؛ TLS 1.2 authorization فوری و profile-aware فعلی را حفظ می‌کند.

سرور TLS مربوط به visitorها را خاتمه نمی‌دهد؛ فقط به اندازه‌ای recordهای شبیه TLS را بررسی می‌کند که تشخیص دهد peer یک Reality client معتبر است یا ترافیک عادی visitor.

جایگاه رایج

TcpListener -> RealityServer -> protected-chain
|
+-> destination visitor branch

نود next ترافیک مجاز Reality را دریافت می‌کند. گزینه destination نام شاخه معمول visitor است که اغلب یک TcpConnector برای سایت واقعی visitor خواهد بود.

نمونه تنظیمات

{
"name": "reality-server",
"type": "RealityServer",
"settings": {
"destination": "visitor-site",
"password": "replace-with-a-strong-secret",
"algorithm": "chacha20-poly1305",
"sniffing-attempts": 8
},
"next": "protected-chain"
}

مقصد visitor:

{
"name": "visitor-site",
"type": "TcpConnector",
"settings": {
"address": "www.example.com",
"port": 443
}
}

فیلدهای اجباری

فیلدنوعتوضیح
typestringباید RealityServer باشد.
nextstringنودی که payload decrypt شده و تاییدشده Reality را می‌گیرد.
settingsobjectباید object غیرخالی باشد.
settings.destinationstringنام نود مربوط به ترافیک visitor. نود باید وجود داشته باشد و نمی‌تواند خود RealityServer یا نود مجاز next باشد.
settings.passwordstringsecret مشترک Reality شامل ۱ تا ۳۲ بایت UTF-8؛ باید با client یکسان باشد.

تنظیمات

گزینهپیش‌فرضتوضیح
destinationاجباریشاخه visitor. تا پیش از authorization، handshake، TLS معمول visitor، probeهای نامعتبر و candidateهای ناموفق Reality به این شاخه فرستاده می‌شوند.
passwordاجباریsecret مشترک شامل ۱ تا ۳۲ بایت UTF-8 برای key derivation.
algorithmchacha20-poly1305یکی از chacha20-poly1305، chacha20poly1305، aes-gcm، aes-256-gcm یا aes256gcm.
methodمثل algorithmalias برای algorithm، وقتی algorithm وجود نداشته باشد.
saltwaterwall-realitysalt برای key derivation. مقدار صریح باید شامل ۱ تا ۳۲ بایت UTF-8 باشد و با client یکی باشد.
kdf-iterations12000تعداد integer roundهای key derivation در بازه 1 تا 1000000؛ عدد اعشاری رد می‌شود.
sniffing-attempts8تعداد integer candidateهای Reality ناموفق پس از allowance یک-recordی پیش از REQUEST در TLS 1.3، قبل از اینکه line به‌صورت دائم visitor فرض شود. بازه معتبر 1 تا 1024 است؛ TLS 1.2 این allowance را ندارد.
sniffing-counterمثل sniffing-attemptsalias integer قدیمی با همان بازه، فقط وقتی sniffing-attempts وجود نداشته باشد.
tls12-gcm-server-nonce-policyautopolicy مربوط به explicit nonce جهت downstream در TLS 1.2 GCM: یکی از auto، sequence، counter یا random.

اگر aes-gcm انتخاب شود اما crypto backend فعال از AES-GCM پشتیبانی نکند، ساخت tunnel شکست می‌خورد.

محدودیت credential برحسب بایت UTF-8 سنجیده می‌شود، نه تعداد character، و همان طولی است که به BLAKE2s داده می‌شود. مقدار پیش‌فرض فقط وقتی اعمال می‌شود که key اختیاری وجود نداشته باشد؛ key موجود با نوع JSON اشتباه خطای startup است. فیلد primary حتی وقتی نامعتبر باشد بر alias اولویت دارد: method نمی‌تواند algorithm نامعتبر را نجات دهد و sniffing-counter نیز نمی‌تواند sniffing-attempts نامعتبر را نجات دهد.

شاخه Visitor و Protected

در upstream Init، RealityServer state مربوط به line را مقداردهی اولیه می‌کند و بی‌درنگ شاخه destination را آماده می‌سازد. chain محافظت‌شده next در این مرحله هنوز initialize نشده است.

تا قبل از authorization:

  1. یک streaming parser محدود، پیام‌های ClientHello و ServerHello تکه‌تکه‌شده و در TLS 1.2، epoch مربوط به protected record در هر جهت را در حالی مشاهده می‌کند که بایت‌ها همچنان به شاخه visitor فرستاده می‌شوند
  2. extension مربوط به TLS 1.3 supported_versions رعایت می‌شود و HelloRetryRequest تا رسیدن ServerHello نهایی نادیده گرفته می‌شود
  3. handshake نامعتبر یا پشتیبانی‌نشده، line را به رفتار عادی visitor منتقل می‌کند
  4. پیش از آماده شدن هر دو hello، recordهایی که شبیه application-data هستند همچنان ترافیک visitor محسوب می‌شوند و هرگز با root key آزمایش نمی‌شوند
  5. پس از مشتق‌کردن keyهای هر جهت در v2، از candidate recordها کپی گرفته می‌شود و احراز اصالت با sequence دقیق بعدی client-to-server انجام می‌گیرد
  6. اگر احراز اصالت در حالت pending شکست بخورد، record اصلی به destination فرستاده می‌شود و هیچ trial decrypt مربوط به v1 انجام نمی‌شود
  7. در TLS 1.2 authorization فوری حفظ می‌شود؛ در TLS 1.3 فقط HANDOFF_REQUEST با sequence صفر می‌تواند handoff را آغاز کند

پس از مشتق‌شدن session keyهای TLS 1.3، server یک allowance داخلی، غیرقابل reset و یک-recordی پیش از REQUEST برای Finished رمز‌شده واقعی client در نظر می‌گیرد. candidate ناموفقی که این allowance را مصرف می‌کند بدون تغییر و byte-for-byte به destination فرستاده می‌شود، بدون اینکه sniffing-attempts افزایش یابد یا Reality sequence جلو برود. این allowance نمی‌تواند client را authorize کند، پس از احراز HANDOFF_REQUEST کنار گذاشته می‌شود و در TLS 1.2 کاربرد ندارد. candidateهای ناموفق بعدی budget تنظیم‌شده را به شکل عادی مصرف می‌کنند.

پس از احراز REQUEST در TLS 1.3، server فقط record TLS مقصدی را که قبلاً شروع شده تا boundary کامل ادامه می‌دهد. tracker streaming در اولین boundary امن split می‌کند، همه bytes بعدی downstream مقصد را سرکوب می‌کند و HANDOFF_ACK را با sequence صفر server-to-client می‌فرستد. protocol output واقعی TLS که client پیش از پردازش ACK ساخته هنوز می‌تواند upstream به مقصد برسد. trial ناموفق HANDOFF_CONFIRM record و sequence را حفظ می‌کند ولی از نظر تعداد record و bytes محدود است. CONFIRM با sequence یک client-to-server، جهت باقی‌مانده مقصد را یک‌بار می‌بندد، next محافظت‌شده را یک‌بار init می‌کند و رفتار سخت‌گیرانه Authorized را فعال می‌سازد. application record در TLS 1.3 به‌تنهایی authorize نمی‌کند.

بعد از authorization:

جهترفتار
Upstream payloadباید Reality record معتبر باشد؛ پس از احراز اصالت و رمزگشایی، cleartext به next می‌رود.
Downstream payloadcleartext مربوط به next رمزنگاری می‌شود و در قالب TLS-like application-data record به نود قبلی برمی‌گردد.

اگر بعد از authorization upstream نامعتبر باشد، TLS record غیر Reality برسد، یا authentication شکست بخورد، server در صورت writable بودن wire حداکثر یک fatal bad_record_mac احرازشده می‌فرستد و سپس هر دو جهت را می‌بندد.

server پس از authorization مالک shutdown عادی Reality است. Finish سمت protected دقیقاً یک close_notify می‌فرستد و سپس بدون انتظار سمت wire را می‌بندد. RealityClient آن را بدون پاسخ مصرف می‌کند. fatal alert دریافتی پاسخ ندارد و raw wire Finish قابل پاسخ نیست. حالت Pending، Visitor و هر دو مرحله handoff در TLS 1.3 بدون alert مصنوعی Reality بسته می‌شوند، چون client ممکن است هنوز downstream را cover TLS بداند.

قوانین Visitor Fallback

line در یکی از این حالت‌ها به ترافیک visitor تبدیل می‌شود:

  • bytes pending یک TLS record محتمل نباشند
  • پس از allowance محدود پیش از REQUEST در TLS 1.3 (در صورت کاربرد)، تعداد Reality candidateهای ناموفق به sniffing-attempts برسد

prefix عمومی TLS record بدون مصرف‌شدن به‌صورت تدریجی طبقه‌بندی می‌شود: content type پشتیبانی‌نشده پس از byte اول، major نامعتبر legacy version پس از byte دوم و minor بزرگ‌تر از 0x04 پس از byte سوم نتیجه را قطعی می‌کنند. prefix محتمل یک تا چهار byte تا وقتی connection باز است در حالت Pending می‌ماند. اگر در حالت Pending از upstream یک Finish برسد، همان byteهای bufferشده بدون تغییر و پیش از Finish مقصد به destination منتقل می‌شوند.

بعد از visitor شدن، upstream به destination می‌رود و downstream همان شاخه به نود قبلی برمی‌گردد. chain محافظت‌شده next برای آن line init نمی‌شود.

شکست در حالت Pending یا Visitor هرگز alert مخصوص Reality تولید نمی‌کند. candidate ناموفق Pending به‌صورت byte-for-byte در مالکیت destination باقی می‌ماند؛ بنابراین هر پاسخ احتمالی متعلق به cover endpoint واقعی است و oracle مخصوص Reality ایجاد نمی‌شود.

قالب Record

cover مذاکره‌شدهbody قابل‌مشاهده Reality
TLS 1.3Reality-AEAD(payload + encrypted inner type 0x17) + 16-byte tag؛ بدون nonce/prefix قابل‌مشاهده، با طول body برابر P + 17 و حداکثر 16401.
TLS 1.2 ChaCha20-Poly1305Reality-AEAD(payload) + 16-byte tag؛ بدون nonce/prefix قابل‌مشاهده، با طول body برابر P + 16 و حداکثر 16400.
TLS 1.2 AES-GCM8-byte explicit nonce + Reality ciphertext + 16-byte tag؛ حداکثر body برابر 16408.
TLS 1.2 AES-CBC/SHA-116-byte random explicit IV + block-aligned opaque body؛ حداکثر body برابر 16432.

طول public در CBC با فرمول TLS MAC و minimum padding هماهنگ است، ولی Reality عملیات CBC encryption انجام نمی‌دهد.

header شبیه TLS از این مقادیر استفاده می‌کند:

فیلدمقدار
Content type0x17 application data
Version0x0303
Lengthvisible prefix پروفایل انتخاب‌شده به‌علاوه opaque body احرازشده

visible prefix احرازشده است اما Reality AEAD nonce نیست. Reality replay sequence و TLS facade sequence مستقل هستند و profile ID و طول prefix نیز در associated data قرار می‌گیرند.

alertهای احرازشده شکل public سازگار با BoringSSL دارند:

cover مذاکره‌شدهheader و body مربوط به alert
TLS 1.3outer type برابر 0x17 و body برابر 19 بایت با inner alert type رمز‌شده 0x15.
TLS 1.2 AES-GCMouter type برابر 0x15 و body برابر 26 بایت با ادامه policy مربوط به explicit nonce.
TLS 1.2 AES-CBC/SHA-1outer type برابر 0x15 و body برابر 48 بایت با IV تازه 16 بایتی.
TLS 1.2 ChaCha20-Poly1305outer type برابر 0x15 و body برابر 18 بایت.

semantic رمز‌شده 01 00 برای close_notify و 02 14 برای fatal bad_record_mac است. alert و data در هر جهت sequence مشترک دارند و record kind و نسخه TLS نیز در associated data قرار می‌گیرند. این‌ها recordهای camouflage محافظت‌شده با Reality AEAD هستند، نه TLS closure واقعی یا alert رمز‌شده با keyهای TLS.

HANDOFF_REQUEST، HANDOFF_ACK و HANDOFF_CONFIRM در TLS 1.3 outer/inner type مربوط به application-data دارند. plaintext نسخه‌دار آن‌ها control code مورد انتظار و padding احرازشده CSPRNG بر اساس policy مشترک طول عمومی را حمل می‌کند. طول body در TLS به‌طور یکنواخت از بازه 22..1172 byte نمونه‌برداری می‌شود (3..1153 byte padding)؛ این بازه در مسیرهای post-handshake تحت پوشش BoringSSL مشاهده شده است. controlها داخل tunnel مصرف می‌شوند، sequence عادی Reality را مصرف می‌کنند و طول قابل تنظیم JSON ندارند. الگوی timing و توزیع طول آن‌ها همچنان بخشی از بازبینی camouflage روی wire است.

برای TLS 1.2 GCM، حالت auto در صورت مطابقت sampleهای cover با TLS sequence، حالت sequence را انتخاب می‌کند؛ اگر حداقل دو sample افزایشی باشند counter و در غیر این صورت random انتخاب می‌شود. حالت دستی counter به یک nonce مشاهده‌شده نیاز دارد. یک sample غیر-sequence برای تشخیص قطعی counter از random کافی نیست؛ در صورت شناخت رفتار cover server می‌توان policy را صریح تنظیم کرد.

هر جهت فقط sequence دقیق بعدی خود را می‌پذیرد؛ بنابراین recordهای تکراری، حذف‌شده، جابه‌جاشده، بازتاب‌یافته یا متعلق به connection دیگر شکست می‌خورند. شکست authentication پس از authorization خطای نهایی است و counterها پیش از امکان استفاده از UINT64_MAX بسته می‌شوند.

نکته‌های Buffer و Lifecycle

  • RealityServer به‌ازای هر line state نگه می‌دارد که شامل parser محدود hello، TLS binding، session ID، keyها و IVها و counterهای هر جهت، mode فعلی و state مربوط به انتقال میان شاخه‌ها است.
  • این نود line معمولی را نه ایجاد می‌کند و نه از بین می‌برد و فقط state خودش را پیش از فرستادن callbackهای Finish پاک می‌کند.
  • این نود 21 بایت required left padding اعلام می‌کند: 5 بایت header و حداکثر 16 بایت explicit IV مربوط به CBC.
  • bufferهای خالی payload در جهت downstream از chain محافظت‌شده، بدون فرستادن Reality record به pool برگردانده می‌شوند.
  • حداکثر plaintext هر fragment به‌صورت خودکار برابر limit بومی TLS یعنی 16384 بایت است. callbackهای بزرگ‌تر فوراً split می‌شوند؛ 32768 بایت دقیقاً دو record کامل می‌سازد و buffering بین callbackها وجود ندارد.
  • هنگام انتقال به حالت authorized، callbackهای downstream ناشی از بستن شاخه visitor نادیده گرفته می‌شوند تا به سمتی که در حال تغییر مسیر است بازتاب پیدا نکنند.
  • alert نهایی پیش از Finish منتقل می‌شود؛ guardهای terminal بازتاب synchronous مربوط به Pause/Resume/Payload/Est را متوقف می‌کنند و مرگ line هنگام send یا نخستین finish باعث توقف فوری teardown می‌شود.

مدل تهدید و محدودیت‌های امنیتی

مدل تهدید بررسی‌شده برای camouflage یک ناظر در مسیر است که TLS را terminate نمی‌کند. این ناظر می‌تواند stream کامل دوطرفه را capture و reassemble کند؛ type، version، length، direction، ordering و timing مربوط به TLS recordها، nonce/IVهای قابل‌مشاهده و رفتار close را ببیند؛ bytes را دست‌کاری کند؛ و با آگاهی از implementation اتصال probe ایجاد کند. فرض می‌شود ناظر password مربوط به Reality یا traffic secretهای TLS واقعی را نمی‌داند، TLS را terminate نمی‌کند و cover destination تنظیم‌شده را کنترل نمی‌کند یا با آن تبانی ندارد. همچنین نمی‌تواند handshake کامل‌شده را بدون شکست TLS Finished verification تغییر دهد.

تازگی material هر نشست Reality به client random و server random تازه در handshake واقعی TLS وابسته است. Reality هیچ server challenge مستقل مخصوص تازگی نشست ندارد. بنابراین محافظت در برابر replay میان connectionها فرض می‌کند ناظر نمی‌تواند هر دو handshake random را پیش‌بینی یا کنترل کند. cover destination مخرب یا همدستی که عمداً به بازسازی binding یک handshake قبلی کمک کند خارج از این مدل است؛ دفاع در برابر چنین مدل قوی‌تری به server challenge مستقل و احرازشده نیاز دارد.

camouflage در Reality فقط ویژگی‌های public انتخاب‌شده TLS را بازسازی می‌کند؛ از جمله شکل و طول record متناسب با suite، nonce/IV صریح، controlها، alertها و رفتار close. با این حال، پس از takeover، recordها ciphertext مربوط به Reality-AEAD را حمل می‌کنند، نه ciphertext واقعی ساخته‌شده با TLS traffic keyهای اتصال cover. Reality ادعا نمی‌کند در برابر TLS termination پنهان می‌ماند یا همه timing distributionها، write sizeها، burst patternها و semanticهای application در Chrome را بازسازی می‌کند. ناظری که TLS را terminate کند می‌تواند traffic keyهای واقعی را روی recordهای بعدی آزمایش کند و خارج از محدوده camouflage بررسی‌شده است.

نکته‌های عملیاتی

  • destination برای ترافیک عادی visitor است و بهتر است همان visitor domain مربوط به RealityClient.settings.sni را سرو یا proxy کند.
  • next فقط برای ترافیک مجاز واتروال است.
  • password، salt، kdf-iterations و algorithm باید با RealityClient یکی باشند.
  • handoff احرازشده TLS 1.3 جای cutover منتشرنشده قبلی در پایان handshake اصلی را می‌گیرد. هر دو peer را هم‌زمان ارتقا دهید؛ layout و counterهای TLS 1.2 تغییر نکرده‌اند، fallback به v1 یا layout قدیمی وجود ندارد و setting منسوخ max-frame-size در startup رد می‌شود.
  • مقدار مشتق‌شده از password یک root key برای material مستقل هر جهت در هر نشست TLS است. چرخش password نشست‌های آینده را نامعتبر می‌کند و به replay database در سمت server نیازی نیست.
  • این نود یک stream tunnel است، نه packet tunnel.

مشخصات نود

ویژگیمقدار
جایگاهMiddle stream tunnel با visitor branch
نیاز به nextبله
نیاز به destinationبله
Previous layerAnything
Next layerAnything
Per-line stateدارد
ایجاد lineخیر
از بین بردن lineخیر
Required left padding21