I. Обзор
Предыдущая статья《Анализ HTTP-запроса«Мы проанализировали, как выполняется простой HTTP-запрос, и проанализировали структуру данных протокола HTTP, как подключиться, как отключиться и как мультиплексировать. Итак, сегодня поговорим о другом протоколе, WebSockets. Так как содержимое протокола WebSocket очень велико, в этой статье будет приведена только верхушка айсберга для краткого описания, и она не будет подробно раскрываться.
2. Что такое веб-сокет
2.1 Предыстория генерации WebSocket
До появления протокола WebSocket создание веб-приложения с двухканальной связью с сервером требовало использования протокола HTTP для непрерывного опроса, что вызывало некоторые проблемы:
-
Сервер вынужден поддерживать большое количество различных подключений от каждого клиента
-
Большое количество запросов опроса приведет к высоким накладным расходам, таким как дополнительные заголовки, что приводит к бесполезной передаче данных.
Поэтому, чтобы решить эти проблемы, вступил в протокол WebStocket.
2.2 Определение веб-сокета
WebSocket — это протокол для полнодуплексной связи по одному TCP-соединению. WebSocket упрощает обмен данными между клиентом и сервером, позволяя серверу активно передавать данные клиенту.
В API WebSocket браузеру и серверу нужно только выполнить рукопожатие, и постоянное соединение может быть создано непосредственно между ними. И двусторонняя передача данных. (Википедия)
3. Анализ базовой структуры фрейма WebSocket
На картинке ниже моя ссылкаRFC6455Диаграмма структуры данных базового фрейма веб-сокета, нарисованная в главе 5.2, далее мы сосредоточимся на анализе диаграммы структуры данных.
FIN: Занимает 1 бит, указывая, что это последний фрагмент сообщения. Также возможно, что первый фрагмент является последним фрагментом.
RSV1, RSV2, RSV3: по 1 биту каждый
Должен быть установлен в 0, если не расширено значение ненулевого значения. Если получено ненулевое значение без расширения какого-либо ненулевого значения, принимающая конечная точка ДОЛЖНА отключить соединение WebSocket.
Код операции: 4 бита, код операции, если получен неизвестный код операции, принимающий терминал должен отключить соединение WebSocket.
%x0 означает устойчивый кадр
%x1 представляет текстовый фрейм
% X2 представляет собой двоичный кадр
% X3-7 зарезервировано для не контрольных кадров
%x8 представляет собой пакет закрытия соединения
%x9 представляет пакет ping
%xA представляет пакет pong
%xB-F зарезервировано для будущих управляющих кадров
Маска: 1 бит, бит флага маски, определяет, добавлять ли маску к «полезным данным». Если установлено значение 1, то значение ключа маски существует в Masking-Key.
Длина полезной нагрузки: 7 БИТ, 7 + 16 БИТ, ИЛИ 7 + 64 бит, с длиной «данных полезной нагрузки» в байтах.
Маскирующий ключ: 0 или 4 байта,
Все фреймы данных, отправляемые клиентом на сервер, были рассчитаны с использованием 32-битной маски, содержащейся в этом фрейме. Если бит флага маски (1 бит) равен 1, то это поле существует, если бит флага равен 0, то этого поля не существует. Примечание. Длина данных полезной нагрузки, исключая длину ключа маски. .
Данные полезной нагрузки: Данные полезной нагрузки
Зачем тебе маска?
В целях безопасности, не для предотвращения утечки данных, а для предотвращения таких проблем, как атаки с отравлением кеша прокси, которые существовали в более ранних версиях протокола.
4. Анализ захвата пакетов
4.1 Демонстрация и анализ
Я написал DMEMO для перехвата пакетов и анализа websocket, исходный код будет размещен по ссылке в конце статьи. Эффект DEMO выглядит следующим образом:
Страница предоставляет функции подключения и отключения, введите свое имя для отправки, сервер возвращает Привет, имя! Функция очень простая, давайте сначала посмотрим на запрос и ответ страницы.
просить:
отклик:
Запрос и ответ здесь отражают рукопожатие WebSocket, Мы можем просто абстрагироваться от формата запроса и ответа WebSocket в соответствии с рисунком выше: Формат запроса рукопожатия клиента:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Ответ сервера на рукопожатие:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Наши результаты выделяют следующее поле запроса:
Upgrade: указывает, что протокол HTTP обновлен до webSocket.
connection:UpgradeЗапросить обновление.
Sec-WebSocket-ключ:Он используется для проверки подлинности на стороне сервера для создания глобального уникального идентификатора и GUID.
Sec-WebSocket-версия:Версия
Sec-WebSocket-Protocol:Запросите сервер использовать указанный подпротокол. Если это поле указано, сервер должен содержать это же поле и выбирать значение из подпротокола в качестве ответа на установление соединения.
Sec-WebSocket-Extensions:Расширение для WebSocket.
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Сгенерированный глобально уникальный идентификатор, GUID.
Алгоритм генерации GUID
Идея алгоритма: передается через Sec-WebSocket-Key Значение, dGhlIHNhbXBsZSBub25jZQ==, строка, сгенерированная сервером соединений, формат объединения следующий
dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11
, Затем используйте хэш-алгоритм SHA-1, а затем используйте кодировку base64 для создания окончательного Значение Sec-WebSocket-Accept, сгенерированное значение равно
s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
(Обратите внимание, что результат, сгенерированный хеш-алгоритмом SHA1, здесь должен быть двоичным результатом хеширования, например
Код Python
h = hashlib.sha1("dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
.digest()
,Если он генерируется онлайн-инструментом обработки, сгенерированный хэш является шестнадцатеричным хэшем, и Base64 будет генерировать неверный результат).
4.2 Захват пакетов
Мой рабочий процесс в DEMO выглядит следующим образом:
- Подключить веб-сокет
- Отправить "luozhou"
- Отключить
Используйте Wireshark для захвата пакетов следующим образом:
Мы объединили скриншоты браузера и скриншоты захвата пакетов и обнаружили, что перед фактическим открытием веб-сокета браузер будет иметь два http-запроса, а именно:A请求 GET /gs-guide-websocket/info?t=1551252237372 HTTP/1.1
B请求 GET /gs-guide-websocket/690/pdsz5x1q/websocket HTTP/1.1
Согласно протоколу RFC6455, для завершения WebSocket требуется только одно рукопожатие, поэтому нам нужно проанализировать только второй HTTP-запрос рукопожатия, а запрос A должен быть реализован на используемом уровне фреймворка.
Из снимка экрана мы можем знать, что ответ, соответствующий запросу B, представляет собой данные с серийным номером 192, а код возврата — 101. Согласно коду возврата HTTP, мы можем знать, что сервер понял запрос клиента и будет уведомить клиента через заголовок сообщения об обновлении, чтобы он принял другой протокол для выполнения этого запроса. После отправки пустой строки в конце этого ответа сервер переключится на те протоколы, которые указаны в заголовке Upgrade, что означает обновление до протокола WebSocket. Итак, пакет 193 стал протоколом WebSocket.На этом этапе рукопожатие WebSocket завершено..
Далее мы анализируем процесс отправки сообщения. Здесь все определенно отправят сообщение, почему будет так много пакетов WebSocket? Фактически, избыточный пакет здесь является рамки, такой как регистрация оформления подписки и публикации. Так что действительно сделайте наши пакеты только имели соответствующие пакеты, которые отключены и отправляют пакет Luozhou »
По приведенному выше рисунку мы обнаружили, что пакет с серийным номером 229 является пакетом текстового типа,opcode:1
, а затем используется обработка по маске, и это последний обрабатываемый пакет одновременно. Мы тщательно выяснили, что все пакеты, отправляемые клиентом на сервер, будут иметь пометку [MASKED], и сервер ее не вернет, а это значит, что при отправке данных от клиента на сервер данные нужно маскировать; от сервера к клиенту Когда конечная точка отправляет данные, ей не нужно маскировать данные.
V. Резюме
-
WebSocket — это протокол для двухканальной связи в веб-приложениях.По сравнению с методом опроса HTTP-запросов, WebSocket имеет преимущества экономии ресурсов сервера и высокой эффективности.
-
Маска в WebSocket настроена для предотвращения таких проблем, как атаки с загрязнением промежуточного кеша в более ранних версиях.Клиент должен отправлять данные на сервер, а сервер не должен отправлять данные клиенту.
-
Алгоритм генерации SEC-Websocket-Key в Webbocket является объединение строк, сгенерированных сервером и клиентом, выполните хеш-алгоритм SHA1, а затем кодировать с помощью Base64.
-
Рукопожатие протокола WebSocket основано на протоколе HTTP и на ответе HTTP 101 для преобразования обновления протокола.
6. Ссылка
[1]RFC6455
[2]Документ RFC протокола WebSocket (полный китайский перевод)