Реализация поддержки websocket для прокси-серверов HTTP / 2

#websocket #proxy #http2

#websocket #прокси #http2

Вопрос:

Я разрабатываю прокси-сервер https http / 2, как упоминалось здесь: https://chromium.googlesource.com/chromium/src / /HEAD/net/docs/proxy.md#HTTPS-proxy-scheme Там упоминается, что

Прокси HTTPS, использующие HTTP / 2, могут обеспечить лучшую производительность в Chrome, чем обычный HTTP-прокси, из-за более высоких ограничений на подключение (прокси HTTP / 1.1 в Chrome ограничены 32 одновременными подключениями во всех доменах).

Но когда пользователи пытаются перейти на веб-сайт, который использует websocket, через необработанное http-соединение, ответ содержит http-заголовок «Обновить», который запрещено использовать в http / 2, поскольку для HTTP / 2 нет websockets. https://daniel.haxx.se/blog/2016/06/15/no-websockets-over-http2/#:~:text=There is no websockets for HTTP/2.amp;text=That spec details how a,connection into a websockets connection.Проблема возникает из-за того, что когда трафик http1.1 проходит через прокси-сервер https, который реализует http / 2, заголовки должны быть переданы с http1.1 на http / 2. Конечно, когда веб-страница использует TLS, такой проблемы не возникает, поскольку весь трафик проходит через соединение, созданное методом http ‘CONNECT’. Проблема возникает, когда веб-сайт не использует TLS. Если нет решения этой проблемы, это означает, что прокси HTTPS не должны реализовывать протокол HTTP / 2.

Ответ №1:

Поскольку для HTTP / 2 нет веб-сокетов

Размещенная вами ссылка устарела, и с тех пор WebSocket через HTTP / 2 был указан в RFC 8441.

Поведение прокси-сервера HTTP / 2 указано в RFC 7540, раздел 8.3.

Когда клиент обменивается данными с прокси-сервером, используя безопасный HTTP / 2, каждый поток HTTP / 2 является «туннелем» к серверу.

Клиент и прокси обмениваются данными, используя безопасный HTTP / 2, и происходит «туннелирование», потому что каждый поток HTTP / 2 становится «бесконечным» запросом с «бесконечным» ответом, то есть «бесконечной» серией кадров HTTP / 2 DATA в обоих направлениях, которые несут непрозрачную полезную нагрузку массива байтов.

Задача прокси-сервера состоит в том, чтобы разворачивать DATA фреймы, полученные клиентом, и пересылать полезную нагрузку массива байтов на сервер, возможно, повторно оборачивая ее в фрейм HTTP / 2 DATA , если связь между прокси-сервером и сервером также HTTP / 2 (возможно, можно оптимизировать процесс разворачивания и повторного-перенос, но это может быть сложно — например, нумерация потоков может отличаться).

Когда клиент пытается выполнить WebSocket через HTTP / 2, браузер будет выполнять действия, указанные в RFC 8441, и прокси-сервер получит CONNECT запрос с :protocol псевдо-заголовком, и прокси-сервер должен будет знать, что делать в этом случае, в зависимости от того, какой протокол он использует для связи с сервером.

То, что выше, описывает, что ваш прокси-сервер должен поддерживать, когда связь с клиентом осуществляется по протоколу HTTP / 2.

Если ваш прокси-сервер должен поддерживать клиентов, которые говорят на HTTP / 1.1, тогда вам нужно реализовать то, что требуется для прокси-сервера для поддержки HTTP / 1.1 и прокси-сервера WebSocket, и это обычно не сложно: первое — это просто переадресация HTTP / 1.1 или CONNECT «туннелирование» HTTP, второе — обновление HTTP WebSocketпереадресация запроса с последующим подключением «туннеля» или даже полноценным прокси-сервером WebSocket.

Отказ от ответственности, я реализовал все вышеперечисленное в проекте Jetty. Вы можете использовать Jetty 10 или более позднюю версию для реализации HTTP / 1.1, HTTP / 2 или WebSocket, как клиента, так и сервера (и, следовательно, прокси). WebSocket через HTTP / 2 также поддерживается.

Наконец, чтобы ответить на ваш последний вопрос, вполне возможно, чтобы защищенные прокси поддерживали HTTP / 2 даже при наличии WebSocket.

Например, открытое текстовое соединение WebSocket с сервером начинается с запроса на обновление HTTP; этот запрос будет отправлен в зашифрованном виде прокси-серверу, который расшифрует его и перешлет на сервер (используя любой протокол, поддерживаемый сервером — может быть даже WebSocket по защищенному HTTP / 2);сервер ответит 101 и обновит соединение до WebSocket; прокси-сервер получит 101 от сервера и обновится до «туннельного» или прокси-сервера WebSocket; прокси-сервер шифрует ответ 101 и пересылает его клиенту; клиент расшифровывает его и обновляет соединение до WebSocket. На этом этапе клиент передает веб-сокет с открытым текстом на сервер через защищенное соединение с прокси-сервером (прокси-сервер видит сообщение веб-сокета с открытым текстом).

Наоборот, безопасное подключение WebSocket к серверу начинается с установления HTTP CONNECT -туннеля через прокси-сервер к серверу; затем клиент установит безопасную связь с сервером; затем он отправит обновление HTTP до WebSocket на сервер (через прокси-туннель). На этом этапе клиент передает защищенный WebSocket на сервер через защищенное соединение с прокси-сервером (прокси-сервер не может видеть сообщение WebSocket).

Варианты HTTP / 2 аналогичны, просто учитывают специфические для HTTP / 2 способы «туннелирования» и транспортировки WebSocket.

Комментарии:

1. При использовании прокси-сервера HTTP / 2 метод CONNECT используется браузерами только тогда, когда целевой сайт использует «https». Но когда целевым сайтом является «http», google Chrome и firefox не используют метод CONNECT, вместо этого они переводят некоторые заголовки HTTP1 в HTTP / 2. Конечно, большинство веб-сайтов в настоящее время используют HTTPS, и при просмотре этих веб-сайтов с использованием прокси HTTP / 2 проблем не возникнет.