Шифрування тунелю WSS закінчується на термінаторі TLS, а не в застосунку
Адреса wss:// доводить наявність TLS на одному переході. Чи має корисне навантаження власне шифрування, залежить від того, що клієнт кладе всередину і хто завершує цей TLS.
Тунель, що передається всередині захищеного WebSocket, має рівно стільки шифрування, скільки клієнт у нього поклав, і не більше. Схема wss:// каже, що TLS захищає одне з'єднання на одному переході. Вона нічого не каже про те, чи байти всередині повідомлень WebSocket захищені окремо, і саме ця різниця вирішує, хто зможе читати ваш трафік, коли щось посередині завершує TLS.
Два шари, що виглядають як один
Захищений WebSocket — це TLS, поверх якого виконується рукостискання WebSocket, як описує RFC 6455 у розділах про з'єднання та безпеку. Рівень TLS автентифікує сервер і шифрує потік, потім рівень WebSocket кадрує те, що застосунок вирішить надіслати.
Це два незалежні рішення, і схема, що малює один замок на всьому шляху, приховує друге. Запитайте, хто завершує з'єднання TLS. Потім запитайте, що клієнт кладе всередину кожного повідомлення. Усе інше про розгортання випливає з цих двох відповідей.
Схема A: транспорт — єдине шифрування
У простішій схемі клієнт бере необроблені IP-пакети й загортає їх у повідомлення WebSocket. Усередині нічого не шифрується, тому компонент, який тримає сеанс TLS, читає навантаження у відкритому вигляді. Коли цей компонент — ваш власний сервер тунелю, це і є передбачена кінцева точка, і схема узгоджена, бо сервер усе одно бачив би трафік.
Це стає іншим розкладом, коли на шляху стоїть проксі перевірки й завершує TLS сертифікатом, якому клієнт довіряє. Тепер цей проксі тримає той самий відкритий текст, який тримав би сервер, і жодна кількість кадрування WebSocket цього не змінює. Сховище довіри клієнта вирішило цей результат задовго до відкриття тунелю, бо обрало прийняти цей сертифікат для цього імені. Проксі також бачить запитаний хост і розмір кожного повідомлення, чого достатньо, щоб зняти відбиток багатьох дій, нічого більше не розшифровуючи.
Схема B: навантаження несе власні ключі
У другій схемі клієнт шифрує та автентифікує свої пакети протоколом VPN, який має власну ідентичність партнера й обмін ключами, а потім несе результат усередині повідомлень WebSocket. Завершення зовнішнього TLS тут відкриває шифротекст, а не трафік. Проксі бачить розміри й час повідомлень, і нічого більше в навантаженні. Це значно менша експозиція, і все ж це метадані, які варто назвати в огляді, а не відмахнутися від них.
Власні кінцеві точки внутрішнього протоколу досі бачать відкритий текст, у цьому сенс розкладу і водночас його межа. Якщо компонент на кінцевій точці уповноважений читати дані до шифрування або після розшифрування, додатковий рівень його не обмежує. Ключі та програмне забезпечення, яке ними керує, залишаються межею, що має значення.
Мітка VPN, знайома іконка клієнта або маркетингова сторінка не є доказом існування цієї схеми. Читання формату навантаження — є.
Простежте, де насправді з'являється відкритий текст
Схема URL дає вам один факт, тож решту візьміть з інтерфейсів. Виконайте наведені нижче перевірки по порядку, бо кожна звужує наступну:
ss -tnp | grep -E ':(443|8443)\b' ip -br link show type tun openssl s_client -connect vpn.example.net:443 -servername vpn.example.net -brief tcpdump -ni tun0 -c 5 -X
Почніть із зовнішнього з'єднання. Один довготривалий сеанс TCP до порту TLS — так виглядає носій WebSocket, а другий сеанс до не пов'язаного хоста заслуговує на пояснення, перш ніж дивитися глибше. Потім знайдіть інтерфейс тунелю на клієнті, бо пристрій tun або tap каже, що клієнт обробляє IP-пакети, а не проксіює один потік застосунку.
Захоплення на інтерфейсі тунелю зазвичай вирішує питання навантаження. Читабельні заголовки там означають, що внутрішні пакети ніколи не шифрувалися окремо, а навантаження з високою ентропією означають, що шифрувалися. Повторіть захоплення на зовнішньому інтерфейсі й порівняйте обидва: якщо обидва виглядають випадковими, внутрішній рівень робить роботу, яку зовнішній не може скасувати.
Перегляньте довіру, яку ви справді надали
Встановлений корпоративний кореневий сертифікат — це факт про сховище довіри клієнта, а не твердження про те, що якийсь проксі реєструє чи перевіряє. Встановіть розгорнуту політику й реальний шлях з'єднання замість того, щоб виводити поведінку з наявності CA.
На керованому обладнанні запитайте адміністратора, який компонент завершує TLS, чи клієнт перевіряє закріплений сертифікат чи публічний, і який формат навантаження. Ці три відповіді дають висновок, який ви зможете захистити пізніше.
Запишіть результат як межу, а не як вирок. "TLS завершується на проксі перевірки, а внутрішнє навантаження окремо зашифроване ключами, які мають лише кінцеві точки" — це перевірне твердження, яке переживе зміну постачальника. "WebSockets безпечні" — ні.