Previous Entry Share Next Entry
Новая редакция протокола Web Sockets
elisitsky
На днях разработчики протокола Web Sockets преподнесли нам небольшой сюрприз под названием редакция 76. Изменения настолько глобальны, что поломана обратная совместимость с редакцией 75. Таким образом, новые клиенты не могут работать со старыми серверами и наоборот. Насколько быстро сломается то, что уже сделано в Web Socket-ном вебе? В принципе уже начало ломаться. Гугловцы обещали, что WebKit, начиная с ревизии r59903, и Chrome, начиная с версии 6.0.414.0 (ревизия r47952), будет использоваться 76 редакция протокола. А это значит, что нам сейчас надо срочно обновлять наши сервера.

Давайте рассмотрим, что именно изменено и ради чего такая спешка, что даже потребовалось ломать рабочие версии.

Основные изменения связаны с безопасностью подключения. Цель: предотвратить или хотя бы максимально осложнить подделку запросов, отправленных с неверных источников. Например, чтобы нельзя было послать из браузера AJAX-запрос максимально похожий на установление веб-сокетного соединения и тем самым атаковать веб-сокет сервер.

Для этого в протокол был добавлен целый ряд заголовков, начинающихся на sec-.
Сравним старый и новый запрос на установление подключения по Web Socket:

Старый запрос:

GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
WebSocket-Protocol: sample


Новый:

GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8
Origin: http://example.com

^n:ds[4U


Заголовок Sec-WebSocket-Protocol указывает какой субпротокол вы планируете использовать. Название - ваше собственное, можно использовать, например, chat или sample или еще какое-нибудь. Данный заголовок позволяет проверить, что и сервер, и клиент поддерживают ваш протокол. Если это не так, то соединение будет сброшено. Это немного упрощает проверку поддержки конкретного протокола или его версии, экономит вам несколько строк кода.
За собственно безопасность отвечают два заголовка-близнеца Sec-WebSocket-Key1 и Sec-WebSocket-Key2. Обрабатываются они одинаково: из полученного мусора символов извлекаются цифры. Мы должны получить такой результат:
Key1: 1868545188
Key2: 1733470270

Одновременно подсчитывается количество пробелов в каждом ключе. В данном случае 12 и 10. Каждое число делится на соответственное количество пробелов. В данном случае мы получим два 32-битных числа:
Key1: 155712099
Key2: 173347027

Но и это еще не все. Дальше идет нечто совершенно безумное, похожее на тело GET-запроса. Страшно писать такие слова...
Два полученных числа представляются как big endian 32-битные целые и затем "слепляются" с образование 8 байт. Затем туда же пристыковываются 8 байт из "тела запроса". Вот эти 16 байт и образуют "секретную" подпись. Теперь задача сервера правильно ответить на такой запрос.

Опять сравним старый ответ:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample


и новый:

HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Location: ws://example.com/
Sec-WebSocket-Protocol: chat

fQJ,fN/4F4!~K~MH


Как мы видим после заголовков ответ сервера содержит еще какие-то данные - это та самая "секретная" подпись, от которой взят md5. Полученные 128 бит записываются как есть, без конвертаций в hex-, dec- или еще куда-то.

Оригинал: Новый протокол Web Sockets

  • 1
О каких рабочих версиях идет речь? О тех, над которыми идет работа? Дык.. они на то и рабочие, чтобы над ними работали, не?
Implementors should be aware that this specification is not stable. 
Implementors who are not taking part in the discussions are likely to find the specification changing out from under them in incompatible ways.
Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation stage should join the aforementioned mailing lists and take part in the discussions.

Все верно, это рабочие версии, которые могут меняться.
Я сообщаю о том, что если кто уже реализовал предыдущую версию и использует, то надо обновиться.
Пожалуй в коммерческую эксплуатацию это запускать рано, но в опытную уже можно.

приветствую вас)

А у вас молоко убежало тело запроса неправильное. Должно быть "Tm[K T2u" вместо "^n:ds[4U". Тогда ответ сервера сгенерится именно такой какой указан.

как такая строка получается?

Не подскажешь, как эта строка закорючек получается? Ведь md5 выглядит не так. А например так c772020a2b9359061747ce4628dd0dd0. Пишу на Delphi. Как правильно ответ сервера составить? Подскажи, плиз. Помогу рублём. Замучался уже.

md5-функция у меня такая:

function Tform1.md5(s: string): string;
begin
Result := '';
with TIdHashMessageDigest5.Create do
try
Result := AnsiLowerCase(AsHex(HashValue(s)));
finally
Free;
end;
end;

Re: как такая строка получается?

Такая строка - "c7720..." - это hex-представление, а нужно просто бинарное. Хеш md5 это же просто очень большое число, по сути.

Дельфей я не знаю, к сожалению, но AsHex явно делать не нужно :) Возможно HashValue уже возвращает бинарную строку? Я вообще на node.js это всё пробовал.

  • 1
?

Log in