Туннелирование TCP через web-прокси

Век живи - век учись... Сколько раз говорю себе, а также окружающим и - со страниц газеты - всему прогрессивному человечеству: читайте свежую документацию, интересуйтесь стандартами, изучайте тонкости (в том числе и малодокументированные) популярных протоколов. Нет... Все равно в определенный момент наступает ситуация "и на старуху бывает проруха". Намедни случись со мной такая вот проруха, о которой в назидание и хочу рассказать вам, дорогие читатели.

 

Лажу я, значит, по каталогу шаре- и фриварного софта www.davecentral.com в наиболее любимом мной разделе Windows | Connectivity | Winsock Tools, и задерживается мой взгляд на таком вот ревью к одной из утилит: "HTTPort является полезным решением, если вы находитесь в корпоративной Internet-среде, которая блокирована от внешнего мира прокси/файерволлом, который не позволяет вам использовать никакие интернет-сервисы кроме веба (HTTP), а вам их таки нужно (или очень хочется;) использовать. Продукт также позволяет вам увеличить вашу анонимность при работе в Сети..."

Теперь стыдно признаться, но тогда я восприняла это как стремную рекламную листовку. Однако продукт скачала. По диагонали пробежав документацию, запускаю я это чудо, нацеливаю на первый попавшийся под руку открытый и соответствующий определенным условиям (об условиях - ниже) веб-проксик и, пустив слезу умиления, вылажу на Dalnet IRC.

Кроме меня слезу умиления пускают и окружающие, в том числе и на IRC. Первый пункт обещаний "рекламной листовки" оказался явью. Далее был произведен эксперимент с увеличением анонимности. Анонимность увеличивается радикально - администратор вашего прокси-сервера, призванный следить за тем, чтобы ваши ползанья по вебу ограничивались рамками служебной необходимости, а не всякими там ххх, yyy и т. д., видит, что целый божий рабочий день вы самозабвенно устанавливаете соединение с неким "бесцветным", неопасным хостом. Правда, не по 80-му порту, но это уже вопрос для многих администраторов десятый, несущественный, в общем, вопрос.

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

ход мысли

Протокол HTTP знают все? Все, я думаю. Многие даже читали спецификации версий 1.0 и 1.1. Кстати, для справки: HTTP 1.1 имеет две спецификации - RFC 2616 и устаревший RFC 2068. Версия 1.0 описывается документом RFC 1945. Выпишем себе на промокашку методы, описанные для каждой версии в каждом из RFC:

RFC 1945 (HTTP 1.0) - GET, HEAD, POST
RFC 2068 (HTTP 1.1) - OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE
RFC 2616 (HTTP 1.1) - OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT

Стоп! Вот то, что нам нужно. Читаем: "Спецификация резервирует имя метода CONNECT для использования с прокси, которые могут динамически переключаться на работу в качестве туннеля (например, туннелирование SSL)." Далее следует кривая ссылка на документ "Tunneling TCP based protocols through Web proxy servers", который мне все-таки удалось отыскать. Перед тем, как приступить к изложению сути технологии, кратко опишу историю этого документа, ибо это есть поучительно.

Автором означенного документа является некто Ари Луотонен. Систематически ведя исследования в данной области, Ари публикует результаты в качестве Internet-Drafts. Интересно то, что все предшествующие материалы были объединены в серию draft-luotonen-ssl-tunneling-XX.txt и, как видно из названия, описывали проблему исключительно с позиции тунелирования SSL. Соответственно все ссылались на разработку Луотонена как на "туннелирование SSL" (SSL tunneling). И только в 1998 году Луотонен открывает новую серию, поименованную draft-luotonen-web-proxy-tunneling-XX.txt. Прикол-то в том, что по большому счету новый документ практически ничего не привносит в последнюю спецификацию из SSL-серии, однако дает понять, что технология применима к любым протоколам уровня приложений, базирующимся на TCP.

А по жизни происходит вот что: производители прокси-серверов включают поддержку метода СONNECT для туннелирования SSL, указывая в документации и release notes что-то типа "SSL proxy support (https)" либо умалчивая об экспериментальной фиче вовсе. Итого имеем: поддержку https в WinProxy 1.4 c 1996 года (см. release notes), строку вида https://irc.dal. net:6667/ в логах все того же WinProxy и лицо вида Ж8-() у сетевого администратора. Приехали, в общем ;).

собственно технология

Упомянутый выше документ (который draft-luotonen-web-proxy-tunneling-00.txt) описывает расширение протокола HTTP 1.x (важно: не только HTTP 1.1, как вам могло показаться, но и старого доброго HTTP 1.0) для организации туннелирования TCP на прокси-серверах (веб-прокси). Это расширение может использоваться при взаимодействии как клиент-прокси, так и прокси-прокси (в случае каскадирования оных). Поскольку спецификация действительно изначально разрабатывалась для SSL, в ней делается небольшое лирическое отступление, которое я также считаю нужным привести в этой статье. Суть отступления в следующем: следует иметь в виду, что протокол HTTPS, который по сути является реализацией HTTP поверх SSL, может обрабатываться прокси и иным образом, как обычный маппинг, использующийся в различных реализациях прокси для поддержки большинства протоколов - Telnet, FTP и др. В таком варианте имеем следующего рода взаимодействие: прокси устанавливает безопасное (secure) соединение с удаленным HTTPS-сервером и осуществляет транзакции от имени клиента. Полученные в ходе взаимодействия данные дешифруются проксью и по нормальному (unsecure, опасному, в общем) HTTP отдаются клиенту. Минусы такого варианта очевидны.

Итак, что нам предлагает г-н Луотонен.

Клиент соединяется с прокси-сервером и использует метод CONNECT для задания имени хоста и номера TCP-порта, к которым ему вздумалось подключиться. Имя хоста и номер порта разделяются двоеточием (:), причем оба эти параметра должны быть заданы явно (никаких дефолтов). Сочетание host:port дополняется строкой с указанием версии HTTP и символом перевода строки. Далее идет пустая строка и опять же символ перевода строки. В принципе сразу же после этого могут следовать данные, которые относятся к туннелирующемуся протоколу.

Однако считается, что туннель образуется только после того, как сервер пошлет стандартный (см. пример) утвердительный ответ - мол, все в порядке, метод поддерживаем, а вы имеете полное право сюда лезть. Потом сервер открывает соединение с указанными в запросе хостом:портом и начинает прозрачно, не вдаваясь в суть дела, передавать данные между сокетами со стороны клиента и со стороны сервера - туда и обратно. Вот с большего и все.

Приведем пример диалога, результатом которого станет работа с IRC через веб-туннель:

клиент:
CONNECT irc.dal.net:6667 HTTP/1.0
<пустая строка>
сервер:
HTTP/1.0 200 Connection established
Proxy-agent: WinRoute Pro/4.1
<пустая строка>
<далее начинается туннелирование данных, относящихся к IRC>

Знатоки протокола HTTP наверняка обратили внимание на отсутствие в ответе сервера поля Content-Type, которое является обязательным в обычном HTTP/1.x. Действительно, текущей спецификацией не предусмотрена "обязательность" наличия этого поля, поскольку на данный момент не существует стандартного типа данных MIME, ассоциирующегося с туннелем. Автор спецификации не исключает, что в будущих версиях он предложит ввести стандартный тип данных, например "application/tunnel". Поэтому для будущей совместимости при реализации поле Content-Type должно быть разрешено, но для совместимости с ранними версиями поле это не должно быть обязательным.

Процедура создания туннеля может свободно модифицироваться использованием стандартных заголовков HTTP 1.x. В качестве дежурного примера возьмем механизм прокси-аутентификации. Чтобы заставить клиента пройти аутентификацию, прокси просто должен послать в качестве ответа код 407 и стандартный заголовок Proxy-authenticate. Клиент должен доложить о себе в поле Proxy-authorization. Таким образом, диалог клиента с сервером в случае необходимости аутентификации будет выглядеть вот так:

клиент:
CONNECT irc.dal.net:6667 HTTP/1.0
<пустая строка>
сервер:
HTTP/1.0 407 Proxy auth required
Proxy-agent: WinRoute Pro/4.1
Proxy-authenticate:...
<пустая строка>
клиент:
CONNECT irc.dal.net:6667 HTTP/1.0
Proxy-authorization:...
<пустая строка>
сервер:
HTTP/1.0 200 Connection established
Proxy-agent: WinRoute Pro/4.1
<пустая строка>
<далее начинается туннелирование данных, относящихся к IRC>

В самом конце документа есть такой вот интересный пункт: Security Considerations. В нем автор намекает, что придуманная им технология дает почву для разного рода злоупотреблений, о которых вы, мои читатели, по идее уже догадались ;) Поэтому Ари Луотонен настоятельно рекомендует (цитирую): "...конфигурация прокси должна явно ограничивать возможность соединения стандартными (well-known) портами". А далее делается оговорка, что даже за известными портами в некоторых случаях надо "последить". Вот, в частности, как вам перспектива туннелирования SMTP для рассылки спама? ;)

Однако автор ограничивается лишь напоминанием о потенциальной проблеме, не давая конкретных рекомендаций разработчикам прокси-серверов относительно того, каким образом грамотнее всего это ограничение организовать. Мои эксперименты с WinRoute Pro 4.1 и WinProxy 1.4 (чешским) показывают, что ни по дефолту, ни вручную ничегошеньки там не ограничивается;) А вот squid - совсем другое дело. Юниксовый софт вообще всегда радовал исключительной конфигурабельностью и нелюбовью к дефолтам. Уважают разработчики нужды и чаянья сисадминов. В squid'е запросто можно ограничить использование метода CONNECT, например свести его только к SSL-туннелированию. Вот вам пример участков конфигурационного файла squid.conf (к версии 2.1), где прописывается такое ограничение.

acl CONNECT method CONNECT
acl SSL_ports port 443 563
http_access deny CONNECT!SSL_ports

Кстати, о портах и протоколах: факт, что не все базирующиеся на TCP протоколы будут работать через туннель. Наверняка их найдется по крайней мере штук 5, но очевиден мне пока один - FTP. Ну вы сами догадываетесь, почему ;) Не догадываетесь - пробегитесь по спецификации FTP, пусть это будет вам эдаким заданием для самостоятельной работы ;) И вот еще что... Сессия NetBIOS у нас, если мне мемори не изменяет, по TCP работает, а вот разрешение имен NetBIOS - увы, по UDP. В принципе, запасшись терпением, документацией, генератором пакетов или умением программировать под Windows Sockets, добавив минимум социально-инженерных навыков (для альтернативного разрешения имен ;), можно организовать непрошенное туннелирование NetBIOS'а, что может оказаться весьма интересным занятием. У вашей покорной слуги как-то пока не получилось - явно терпения не хватает ;)

вместо рекламы

Раз уж так получилось, что на ознакомление с технологией туннелирования TCP-протоколов через веб-прокси меня натолкнула упомянутая выше программка HTTPort, считаю нужным сказать о ней пару слов. Сразу предупреждаю: продукт сий бесплатный, с автором его я ни лично, ни виртуально не знакома, посему - никакого подвоха, все честно ;) Кстати, насколько мне удалось понять из краткого мануала к программе, ее автор просто искал выход из неуютной ситуации в рамках файерволла своей сети. В частности, неуютным было отсутствие поддержки SOCKS-прокси.

Задача HTTPort - сделать возможной работу с туннелем для "неподготовленного" клиентского ПО, коим большинство интернет-клиентов и является. Софтина устроена просто как грабельки и состоит, условно говоря, из двух модулей. Первый модуль работает как прокси-клиент, организующий туннель с нужным прокси-сервером, а вторая открывает на клиентской станции слушающие (listening) сокеты, по одному на каждый потенциальный туннель. Таким образом, "неподготовленное" ПО соединяется с неким локальным сокетом, смотрящим (замапленным) на определенный туннель. В нашем случае с IRC имеет место такая пара: локальный сокет 127.0.0.1:6667 смотрит в туннель на irc.dal.net:6667. IRC-клиент настроен таким образом, что если вы хотите попасть на DALNet через веб-прокси, он соединялся с "сервером" 127.0.0.1 по порту 6667. Аналогично настраивается и "нелегальное каскадирование" прокси для увеличения анонимности веб-серфинга, где в качестве "той стороны туннеля" выступает некий публичный прокси-сервер. Вообще-то программа очень удобна в конфигурировании и, повторяюсь, проста как грабли, из-за чего занимает чрезвычайно мало места, что не может не радовать. Интерфейсик, правда, немного чудаковатый, но и программа ведь для себя, любимого, писалась, а не для избалованного мирового сообщества.

Кстати (или некстати), программа made in Russia (или made by russian ;), автора зовут Dmitry Dvoinikov. Все, для кого тема этого материала стала откровением, хором скажем Дмитрию спасибо!

Anonymous D. Saemon,anonymous@nestor.minsk.by
обсуждение статьи



Сетевые решения. Статья была опубликована в номере 06 за 2000 год в рубрике RFC