Після того як Beast прочитає заголовок відповіді CONNECT від проксі, перевірте і статус відповіді, і динамічний буфер. Операція читання може захопити байти за межами кінця заголовка і зберегти їх у наданому буфері. Якщо запустити TLS перевантаженням, яке читає лише сокет, ці збережені байти залишаться поза шляхом вводу TLS.

Для потоку WebSocket, наступним шаром якого є потік SSL, використовуйте буферизоване перевантаження рукостискання. У наявній сесії yield_context, утримуючи buffer живим протягом усіх операцій:

http::response_parser<http::empty_body> response;
http::async_read_header(
    beast::get_lowest_layer(ws), buffer, response, yield[ec]);
if (ec) return;

auto status = response.get().result_int();
if (status < 200 || status >= 300) return;

std::size_t used = ws.next_layer().async_handshake(
    ssl::stream_base::client, buffer.data(), yield[ec]);
if (ec) return;
buffer.consume(used);

Ранні повернення — це виходи сесії при збої; долучіть там звичайне звітування про помилки та очищення. Тунель встановлює лише успішна відповідь CONNECT. Сторінка відмови не повинна ставати входом TLS.

Буферизоване перевантаження завершується з кодом помилки та кількістю байтів. Це число описує, скільки байтів воно витратило з наданих буферів. Після завершення видаліть рівно цей префікс за допомогою consume(used). Не очищайте буфер до початку операції, не змінюйте його сховище, поки рукостискання очікує, і не припускайте, що операція витратила кожен наданий байт.

За звичайного TLS, запущеного клієнтом одразу після CONNECT, буфер може бути порожнім. Перевантаження обробляє і цей випадок. Його мета — зберігати межі потоку; воно не робить довільні подальші дані проксі допустимим TLS. Зберігайте перевірку імені цільового хоста та налаштування SNI на рівні SSL до рукостискання і починайте оновлення до WebSocket лише після успішного TLS.

Схожі статті