Ключевые слова:ssh, ssl, tunnel, squid, proxy, (найти похожие документы)
Date: 3 Sep 2002
From: Игорь Чубин
Subject: Использование SSH поверх прокси (через SSL CONNECT в squid)
SSH поверх прокси (SSL CONNECT в squid)
Идея
Причиной, которая заставила меня написать эти рекомендации была
необходимость. Необходимость в полноценном доступе к Интернету, когда
под рукой есть только прокси-сервер. Такая проблема сейчас встает
очень часто: существует локальная сеть, подключенная к Интернету через
Squid или другой подбобный ему сервер. Компьютеры сети используют
внутренние адреса: 10.x.x.x, 172.16.x.x или 192.168.x.x. Очевидно,
прямой доступ к серверам Интернета они получить не могут. Выходом мог
бы быть маскарадинг, но он выполняется не всегда: причины могут быть
самые разные -- от соображений безопасности, до элементарной лени.
Обиднее всего, что где-то там, за брандмауэром, есть компьютер,
которому ты не безразличен и вы жаждете соединиться. Что же делать?
Неужто нет никакого выхода? Выход есть, его не может не быть. С
детства известно, настоящая любовь (к полноценному коннекту)
преодолеет любые преграды.
Все прокси поддерживают обработку HTTP-запросов. Это, конечно,
хорошо, но это еще не все. Обычно прокси поддерживает еще и SSL и это
его роковая ошибка :)
Здесь и далее, говоря прокси, мы имеем в виду традиционное
толкование этого термина, т.е. кэширующий прокси-сервер типа Squid,
а не более общее: сервер-посредник, который предоставляет доступ к
какому-лиюо сервису
Конфигурационный файл Squid по умолчанию разрешает соединение с
портами 443 и 563 на которых работает HTTP over SSL и NNTP over SSL.
Фрагмент типового squid.conf файла конфигурации Squid:
acl SSL_ports port 443 563
# Deny CONNECT to other than SSL ports
http_access deny CONNECT !SSL_ports
По большому счету нам все равно, какой из этих портов использовать.
Поскольку обычно все прокси-серверы поддерживают защищенное соединение
https, соединение по порту 443 должно обеспечиваться.
Замечание
Если бы Squid разрешал CONNECT по любому порту:
http_access allow CONNECT all
то можно было бы осуществлять любое исходящее соединение вообще без
всяких проблем. Например, transconnect
(http://transconnect.sourceforge.net/), используя технику подстановки
функций, при помощи замены библиотек позволяет добиться прекрасных
результатов!
Поскольку мы не можем обращаться к любому порту любого сервера
напрямую, нам нужно иметь в Интернете машину, которая будет выполнять
прослушивание этого порта и обрабатывать наши запросы. Схема выглядит
так:
+------- + +-------+ +---------+ /
| Client |-----| Proxy |-----| S-Proxy |(--
+--------+ +-------+ +---------+ \
Мы (client) устанавливаем соединение с нашим компьютером в Интернете
(s-proxy) при помощи доступного прокси-сервера (proxy). Соединение,
как мы уже договорились, происходит по https. Приложение на s-proxy, с
которым мы устанавливаем связь, может быть каким угодно. Нужно
добиться как-то, чтобы S-Proxy расшифровывал SSL-трафик, приходящий на
порт 443, и отправлял его интересующему нас приложению. Это
достигается с использование программы stunnel, которая позволяет
делать все что-угодно с каналами SSL.
Какой сервис лучше всего сделать доступным? Добъемся например доступа
к ssh. Для этого есть несколько причин : (самая главная: меня это
сейчас интересует больше всего ;)
* Необходимость. Обычно во внутренней сети все наиболее популярные
службы, как то: e-mail, www, ftp уже доступны. Удаленный же доступ
к компьютерам за пределами сети нередко запрещается или попросту
отсутствует. При этом зачастую он бывает важнее всех остальных
сервисов вместе взятых.
* Универсальность. ssh за счет своей огромнейшей гибкости позволяет
выполнять самые разнообразые вещи, далеко выходящие за рамки
безопасной оболчки, установленные его названием. Фактически, если
у нас есть доступ к удаленной машине по ssh, у нас есть все.
Подсказка
При желании мы можем заставить вообще весь трафик ходить по
SSL-тунелю. Это не проблема, только нужно ли?
Серверная часть
Итак, мы договорились, что данные из внутренней сети во внешнюю и
назад, у нас будут передаваться по SSL-каналу. Все что остается - это
создать его и подключить его к нужным службам.
На s-proxy поднимаем stunnel:
# stunnel -p stunnel.pem -r 22 -d https
Ключ -p указывает на файл сертификата. Он обязательно нужен при
использовании stunnel в режиме сервера. Узнать имя файла можно при
помощи ключа -V.
Ключ -r задает порт, на который будет направлен поток, принятый
программой извне. Это как раз и есть данные передающиеся по
SSL-каналу, они расшифровываются и направляются на порт 22, где ведет
прослушивание демон sshd.
Ключ -d определяет порт на котором, сам stunnel выполняет
прослушивание. Мы решили, что будем ходить через https, потому что
скорее всего наш прокси-сервер его обслуживает.
Клиентская часть
Теперь мы долны заняться клиентской частью. Здесь все почти также
просто. Но есть одно небольшое НО. Соединение должно быть установлено
через прокси-сервер, а stunnel, к сожалению, поддерживает только
прямые SSL-соединения.
На www.stunnel.org можно найти небольшой патч к stunnel, который
позволяет использовать прокси-серверы. Патч находится по адресу:
http://www.stunnel.org/patches/desc/proxy_sweeheng.html . Он
разрабатывался для stunnel 3.14, поэтому на stunnel 3.x он
накладывается практически без проблем. Те трудности, которые могут
возникнуть при небольшом несовпадении некоторых строк в файлах версий
>3.14 - не в счет - они легко устраняются ручным вмешательством.
Итак, выполняем сборку stunnel с поддержкой прокси (файлы
proxy_sweeheng.patch.txt и stunnel-3.14-proxy.tar.bz2 находятся в
текущем каталоге, в который у пользователя есть право на запись):
$ tar xvfj stunnel-3.14-proxy.tar.bz2
$ cd stunnel-3.14
$ patch -p0 < ../proxy_sweeheng.patch.txt
$ ./configure
$ make
# make install
Последняя команда должна выполняться от имени суперпользователя root.
Теперь клиентский stunnel с поддержкой прокси у нас есть. Нам осталось
проложить канал на сервер, а дальше преспокойно пользоваться им:
# stunnel -c -d 2222 -Z s-proxy:https -r proxy:https
Команда устанавливает SSL-туннель с текущего хоста на хост s-proxy,
используя хост proxy, как промежуточный (ключ -Z поддерживается только
пропатченным stunnel'ем). Локально тунель доступен по порту 2222.
Этим тунеллированием мы добились того, что все что поступает на порт
2222 локального хоста в результате оказывается на порту 22 хоста
s-proxy. И наоборот, что s-proxy отправляет с порта 22 -- доступно по
локальному порту 2222.
Осталось только воспользоваться плодами своего труда и запустить ssh:
$ ssh user@localhost -p 2222
Мы заставляем обратиться ssh к порту 2222 локального компьютера. Он
наивно полагает, что он общается с локальным сервером и только мы
знаем, что он общается с stunnel, который передает данные по
SSL-тунелю на s-proxy. Понятно, что имя пользователь соответствует не
локальному пользователю, а удаленному, на хосте s-proxy.
Для того чтобы предельно облегчить себе жизнь, можно отключить
аутентификацию по открытым ключам, которую ssh проводит при обращении
к localhost. Для этого в ~/.ssh/config нужно добавить:
Host localhost
PubkeyAuthentication no
Теперь, даже в том случае, если мы используем несколько разных тунелей
с разными хостами или, если, мы любим заходить к себе локально по ssh,
проблем с аутентификацией хоста не возникнет.
Предостережение
Настоятельно не рекомендается отключать проверку подлинности открытыми
ключами с компьютерами, отличными от localhost.
Несколько криво это всё работает. А на OS отличных от Linux/BSD оно без напильника даже не собирается. Кроме того этот патч ТОЛЬКО для stunnel-3.14.
Более универсальное решение для тунелирования ssh прпотокола - использовать программу Corkscrew (http://www.agroman.net/corkscrew/), которая специально заточена для этого.
У меня практически работала совсем другая схема.
I. Обеспечить выход в мир через connect в squid или аналоге (в частности, в последние использования это был MS ISA сервер). Для этого или:
1) Вписать порт 22 в список разрешённых SSL-портов
или:
2) Сделать на серверной стороне приём коннектов SSH на другой порт (например, 443). Требуется или отдельный SSH-демон, или функциональность аналогичная ipfw fwd во FreeBSD - завернуть соединение на другой порт. Например:
ipfw add NNN fwd main_ip,22 tcp to aux_ip
В этом варианте SSH будет отвечать на __всех__ портах
;)))
II. Собственно обеспечить проброс. В портах есть corkscrew. К ней надо добавить посылку авторизации (одна строчка в Си;)). Я про неё тогда не знал и сделал самопальный аналог. После этого вызов corkscrew/аналога записывается в ProxyCommand в ~/.ssh/config для данного соединения. Также надо переопределить при этом UserKnownHostsFile (в какой-то отдельный файл) и HostName (в 127.0.0.1, чтобы не морочило голову DNS).
Рецепт как описан неполный в том смысле, что код для авторизации тут не давал. Дойдут руки - дополню.
поставил cygwin, попарился с настройками и компиляцией corkscrew, когда уже всё было готово, возник вопрос: "каким клиентом коннектится на сервак?"
Оказывается, всё намного проще! Я всегда использовал putty для подключения из винды на BSD. Этот клиент сам по себе поддерживает работу через прокси. Остается только настроить сервер на порт 443 или сделать форвардинг пакетов с 443 на 22 порт.
У меня построено так: putty через прокси уходит на мой виндовый сервак с установленным порт маппером (в netview от killsoft). Маппер делает из инет:443 локалBSD:22
Всё. Коннект установлен.
кстати, где то видел, что с corkscrew можно проходить через не только http-proxy Но и через httpS-proxy
однако что то у меня не вышо - может у кого то выходило??
>кстати, где то видел, что с corkscrew можно проходить через не только
>http-proxy Но и через httpS-proxy
>однако что то у меня не вышо - может у кого то
>выходило??
зачем прокидывать через https, если данные уже идут внутри ssh ?
Я когда поднимаю тунель на стороне клиента к серверу то соединение создается успешно. Однако когда я пытаюсь вопользоваться тунелем Firefox'ом то никаких ошибок не возникает (типа тунель есть и работает), однако все сайты открываются пустыми страницами (контент не передается почему то..) Никто не в курсе в какую сторону копать?
Спасибо!
Vidimo u vas SSH ne podderzhivaet HTTP proxy - ispolzuite SOCKS. dlya firefox est' addon foxyproxy - on pozvolit ispolzovat' SOCKS dlya vseh protokolov. Udachi!