SSH/HTTPS/OpenVPN/Telegram и всё на одном порту?! Что?!
— Да!
- Хотите скрыть наличее у вас некоторых сервисов?
- В публичной wi-fi сети блокируется всё кроме 443 (https) порта?
- Настроили Telegram Proxy/OpenVPN и не хотите его «светить» ?
- SSH подключение к своему серверу из стран с цензурой?
На все эти вопросы ответ один — Мультиплексирование SSL/TLS соединений, или SSLH.
В посте мы рассмотрим как в 1 команду спрятать кучу сервисов за 1 портом.
Почему?
С недавним выходом Telegram Proxy который почти полностью выглядит как SSL трафик появился интересный вопрос в комментариях к посту:
Newton:
У меня довольно нубский вопрос — а завести это вместе с sslh не реально?После беглой проверки возможностей приложения sslh мне показалось, что «завести» не удастся, но меня очень заинтересовало это приложение, и, как оказалось,
Как?
Приложение SSLH — мултиплексор, другими словами, оно анализируя трафик (фактически выполняя работу mini-DPI) и в зависимости от типа трафика, направляет его в локальный порт 8443/999/991 или любой другой…
Что позволяет нам
Задача
Для примера использования SSLH поставим задачу:
На сервере установлены следующие приложения — Telegram Proxy, Apache, SSH и все эти сервисы мы хотим пускать в мир через 443 порт.
Сервер в нашем примере — Ubuntu 16.04.4 LTS, Apache2 + LetsEncrypt,SSH,Telegram Proxy в Docker.
На данный момент, на нем работает, как и положено, Apache.
Установка & Настройка
Установим SSLH:
sudo apt-get install --no-install-recommends sslh
При установке будет задан вопрос о режиме использования, их два:
- стабильный но более ресурсозатратный
- быстрый, но с потерей соединений при падении процесса
Я за второй вариант, вы, конечно же, можете выбрать другой.
Проверим, работает ли наше чудо следующей командой:
sudo sslh-select -f --listen IP:8443 --tls 127.0.0.1:443 --ssh 127.0.0.1:22 --anyprot 127.0.0.1:9443
IP — внешний IP сервера
8443 — порт на котором будет запущен наш мултиплексор
443 — там где живет Apache
Обратите внимание на опцию anyprot — именно там будет жить наш Telegram Proxy, другими словами, если трафик не подошел ни под какой тип — отправить туда.
Внимание! Если в вашей конфигурации отсутствует Telegram или SSH — уберите лишние ключи запуска.
Проверим?
Откройте браузер по адресу вашего сервера с портом 8443 — вы должны увидеть ответ от Apache, далее попробуйте подключить по SSH или через Telegram Proxy.
Перенос Apache на другой порт
Для переноса Apache со стандартного порта (443) на другой, например на 7443, посетите следующие файлы:
sudo nano /etc/apache2/ports.conf
sudo nano /etc/apache2/sites-enabled/000-default-le-ssl.conf
В примере Apache+SSL/HTTPS был установлен с использованием LetsEncrypt при другом сертификате конфигурационные файлы могут быть по другим путям.
Автозапуск
Настало время настроить автозапуск.
Отредактируем файл:
sudo nano /etc/default/sslh
В поле DAEMON_OPTS= добавьте атрибуты при запуске команды sslh-select, установите RUN в =yes.
Запустим:
sudo systemctl start sslh
Убедимся, что всё хорошо:
sudo systemctl status sslh
Что в итоге?
После прохождения данного туториала у вас должен был появится сервер, у которого через единый порт доступны сразу несколько служб (какие — на ваш выбор).
А как дела с OpenVPN? какие протоколы еще умеет приложение?
На момент написания поста, sslh умеет определять и мультиплексировать следующие протоколы:
[--ssh <addr>]
[--openvpn <addr>]
[--tinc <addr>]
[--xmpp <addr>]
[--http <addr>]
[--ssl <addr>]
[--tls <addr>]
[--anyprot <addr>]
Перед использованием, лучше убедиться, какие протоколы поддерживает ваша версия, (вдруг она новее) используя:
sslh-select -h
Ссылки
Разработка SSLH происходит на github, вот в этом репозитории: github.com/yrutschle/sslh
Docker
Собрать рабочий вариант sslh в докере вместе со всеми другими службами у меня не получилось, на мой взгляд будет интересен docker-compose файл который сможет поднять на 443 порту:
- Apache + LetsEncrypt
- Telegram Proxy
- OpenVPN (опционально)
- Использовать локальный SSH
Если у кого то это получится — пишите в комментариях — добавим в статью, на мой взгляд, это будет полезно.
Вам также может быть интересно
Комментарии (86)
alexgreat7
31.05.2018 10:17-1После беглой проверки возможностей приложения sslh мне показалось, что «завести» не удастся, но меня очень заинтересовало это приложение, и, как оказалось, скрестить ужа с ежом все-таки можно.
shifttstas Автор
31.05.2018 10:17?
alexgreat7
31.05.2018 10:19Ну посмотрите, что у Вас написано)
shifttstas Автор
31.05.2018 10:27+1Посмотрел, писал поздно вечером, сейчас еще раз перечитываю и в упор пока не могу понять в чем конкретно проблема =)
PS Лучше в личку о таком писать.
vesper-bot
31.05.2018 10:46Не вижу проблем в построении этой фразы. Что в ней не так, по вашему мнению?
shifttstas Автор
31.05.2018 10:48Были предложения по добавлению «И», я его добавил, так правда чуть по лучше.
istepan
31.05.2018 10:38В итоге весь неопознанный трафик будет идти в телегу.
shifttstas Автор
31.05.2018 10:39да, и пусть, там он будет дропатся если ключ не подходит, опционально можно еще добавить ключ --http и указать порт apache --> большинство ботов и сканеров пойдут в Apache
vesper-bot
31.05.2018 10:48+1А добавить openvpn в этот конфиг можно? Или его трафик тоже попадает под anyprot и возникает конфликт настроек? И ещё, есть ли в ней возможность непонятный трафик (anyprot) с одного хоста раскидывать по round-robin принципу (или типа сразу всем, а потом если хоть один не дропнул, оставлять соединение)? Например, за sslh спрятались openvpn и mtproto-proxy, пришел запрос непонятной сигнатуры на 443 порт. Можно ли дублировать syn/ack handshake, входящие пакеты тоже дублировать, а исходящие, если пока ещё RST не прилетел, откладывать в очередь на отправку, и если одно из приложений послало по соединению RST, его пакеты не посылать, а посылать только от того, которое RST не послало, ну и запомнить, которое это, чтобы потом не мучить другие приложения трафиком не для них?
shifttstas Автор
31.05.2018 10:50+1Можно! добавляете ключ --openvpn с требуемым портом
PS вот все протоколы которые распознает приложение: (Добавил в пост)
[--ssh ]
[--openvpn ]
[--tinc ]
[--xmpp ]
[--http ]
[--ssl ]
[--tls ]
[--anyprot ]
Расширенного варианта настроек я не нашел, roud-robin можно попробовать реализовать через IPtables или сделать доработку предложив PR на githubF0iL
31.05.2018 12:15Подождите-подождите, а проброс OpenVPN работает и с tls-auth, и с tls-crypt?
shifttstas Автор
31.05.2018 12:39не могу сказать, я ушел с openvpn надо тестировать
dmitryredkin
31.05.2018 14:31Насколько я помню, OpenVPN сам умеет «мультиплексировать» ssl. Так что его можно поставить впереди, а все остальное разруливать уже через sslh.
F0iL
31.05.2018 15:47Автор sslh пишет в документации:
OpenVPN clients connecting to OpenVPN running with -port-share reportedly take more than one second between the time the TCP connection is established and the time they send the first data packet.
и поэтому советует ставить на фронт именно sslh.dmitryredkin
31.05.2018 16:06Ну, в любом случае, если вдруг с sslh впереди не заработает, то 1 секунда на старте клиента — не сильно большая плата.
shifttstas Автор
31.05.2018 17:51Тогда еще удлинится цепочка
OpenVpn --> sslh --> SSH
Зачем если первый элемент можно поставить ниже убрав целый сетевой hop
Chugumoto
31.05.2018 11:00а стабильный ресурсозатратный вариант насколько ресурсозатратный? не проводили сравнение?
shifttstas Автор
31.05.2018 11:02Из документации с официального репозитория:
The Makefile produces two different executables: sslh-fork and sslh-select:
sslh-fork forks a new process for each incoming connection. It is well-tested and very reliable, but incurs the overhead of many processes.
If you are going to use sslh for a «small» setup (less than a dozen ssh connections and a low-traffic https server) then sslh-fork is probably more suited for you.
sslh-select uses only one thread, which monitors all connections at once. It is more recent and less tested, but only incurs a 16 byte overhead per connection. Also, if it stops, you'll lose all connections, which means you can't upgrade it remotely.
If you are going to use sslh on a «medium» setup (a few thousand ssh connections, and another few thousand ssl connections), sslh-select will be better.vesper-bot
31.05.2018 11:22Странно, зачем форкать ради поддержки соединения. Я, когда был молодой и глупый, форкал свой sqlserver, потому что не умел работать с больше чем одним источником запросов в коде, но это когда было… Сейчас я бы просто сокет передавал. (Тогда, кстати, распоряжаться трафиком для многих назначений anyprot теоретически можно — согласно этой информации, sslh работает как tcp-прокси, и соединения терминирует на себе вместо маршрутизации пакетов. Это и хорошо и плохо, но это фишка архитектуры, не более)
SellerOfSmiles
31.05.2018 12:39В общем, не густо. Но все ровно прикольно. Мученики флешей и сильверлайтов в свое время оценили бы. :)
shifttstas Автор
31.05.2018 12:40почему не густо? чего не хватает?
SellerOfSmiles
31.05.2018 12:46Ну, отдельный процесс на каждое соединение это конечно жесть, но и запихивать все в один поток не лучшая идея. Даже если полностью не использовать синхронное чтение/запись этот поток станет узким местом. На ssh может и не заметно, но если там будут разные протоколы с разной степенью загруженности и реалтаймовости, то хорошего будет мало.
Нужен вариант с количеством потоков пропорциональным количеству ядер. Это было бы оптимально, как мне кажется.DistortNeo
31.05.2018 12:54Многопоточность здесь не нужна, т.к. нагрузки на CPU здесь нет. Доказано nginx.
Просто вместо `select` нужно использовать `epoll`, и тогда хоть 10к соединений в одном потоке можно гонять.SellerOfSmiles
31.05.2018 13:25-1Вот мне однажды Nginx и не подошел из-за того что грузил процессор на 100%. Представьте что вам нужно передавать что-то реалтаймовое в рамках одного соединения. Т.е. есть данные, их на самом деле очень мало, они идут, например, от сервера к клиенту, с паузами, но должны доставляться моментально. Чтобы пропустить такой поток через Nginx нужно отключить ему буферизацию. И привет… А COMET реализован не везде, да и привносит свои задержки.
Впрочем да, вы правы. Мало ли на свете извращенцев. :)DistortNeo
31.05.2018 13:43+1100% — это был именно user time или user + system? Если больше system, то претензии уже не к nginx.
Но вообще, это не является типичным сценарием для пользователя sslh.SellerOfSmiles
31.05.2018 16:37Действительно. Nginx — это же святое! Как я мог?..
Но даже его воркер можно распараллелить по нескольким процессам и потокам.DistortNeo
31.05.2018 16:49Да, можно, но конкретно в этом случае смысла не вижу. Ведь задача воркера — это принять пакет из одного сокета и тут же его засунуть в другой сокет без всякой обработки (кроме определения типа протокола в самом начале).
Конечно, если вам нужно обрабатывать хотя быть 100 новых соединений в секунду, а скорость передачи данных превышает 10 гбит/сек, тогда да, нужно заморачиваться с многопоточностью. В противном случае разницы никакой не будет, за исключением того, что однопоточный код проще и меньше подвержен ошибкам.
buldo
31.05.2018 12:41Если кому-то не понравится приведённое в статье решение, то можно использовать HAProxy и разруливать всё доменами. Например, считать, что то, что идёт на ovpn.home.home должно быть спроксировано OpenVPN серверу.
shifttstas Автор
31.05.2018 12:46а вы уверены, что тот же openvpn/telegram в заголовках передает домен?
buldo
31.05.2018 12:50Я делал настройку на основе разбора SNI. У меня за 443 портом жили web-сервер и SoftetherVPN(Который также работает как OpenVPN). OpenVPN клиенты нормально подключались.
shifttstas Автор
31.05.2018 12:52Опять же, я не уверен, что все сервисы передают SNI а не делают nsslokup на стороне клиента и уже по IP всё шлют
past
31.05.2018 13:51У меня через SNI ~ 50 доменов разруливались.
shifttstas Автор
31.05.2018 13:58Какая связка ПО?
past
31.05.2018 14:214 haproxy в параллели.
Ходить по SNI не умел только каллбек из яндекс денег.shifttstas Автор
31.05.2018 14:37+2Мне кажется многим бы был интересен ваш опыт в качестве поста и сравнение с утилитой из этого поста
F0iL
31.05.2018 15:49Есть неплохое описание разных подходов от авторов OpenConnect:
github.com/openconnect/recipes/blob/master/ocserv-multihost.md
gpyra
01.06.2018 09:33OpenVPN до сих пор не умеет в SNI. Возможно у вас на него fallback правило было (ну т.е. нет правила для конкретного домена — перенаправляем на OpenVPN). В составе Softether у меня по SNI корректно работают только сам Softether и SSTP.
schors
31.05.2018 14:24А HAProxy в MTProto-proxy прозрачно будет кидать, или телега будет думать, что всё на одном IP сидят?
saaivs
31.05.2018 13:45+1использовать технологию DPI во благо
т.е. получается и «взрослый» DPI на строне провайдера это может делать с тем же успехом и блокировать весь канал по этому признаку… верно?pda0
31.05.2018 14:06Ну, и да и нет. Ваш сервер знает что это за трафик и для чего он, а DPI провайдера — нет. Что касается анализа протоколов, те, что не являются https можно обернуть в stunnel, после чего мультиплексировать на стороне сервера по sni через haproxy или даже nginx (только сборку надо брать официальную, там нужные модули собраны).
В принципе haproxy вообще может заменить sshl (который неизвестно как нагрузку держит), только конфиг для него сложнее написать.schors
31.05.2018 14:23Угу. И в mtproto-proxy всё будет влетать с одного IP, да?
rogoz
31.05.2018 14:33On Linux and FreeBSD you can use the --transparent option to request transparent proxying. This means services behind sslh (Apache, sshd and so on) will see the external IP and ports as if the external world connected directly to them. This simplifies IP-based access control (or makes it possible at all).
DistortNeo
31.05.2018 14:45DPI провайдера может резать соединения и по косвенным признакам, например, по паттернам передачи данных по соединению. Кажется, так делают в Китае.
schors
31.05.2018 14:48Я очень хочу посмотреть на такие DPI в деле. И на законодательную базу к ним.
DistortNeo
31.05.2018 15:14Приезжайте в Китай и смотрите. Со стороны это выглядит так: поднимаешь VPN до сервера — всё работает. Первые пару мегабайт всё хорошо, а дальше начинается лагодром вплоть до полной невозможности использования VPN, причём остальной трафик не режется.
Во время прошлой поездки в Китай решал проблему, используя международную дата-симку одного из рекламировавшихся здесь операторов — она определялась как гонконгская, и файрвол на неё не распространялся.schors
31.05.2018 15:16Да причем тут Китай? Тут. GFW? Okey — пилите
DistortNeo
31.05.2018 15:24+1То есть возможность деградацию интернета по китайскому сценарию вы даже не рассматриваете?
VolCh
31.05.2018 20:46А что с законодательной базой может быть не так, если она предусматривает блокировки в принципе? Расшифровки не происходит, просто более глубокий анализ пакетов, чем это делает «тупой» роутер, умеющий блокировать по IP типа iptables.
F0iL
31.05.2018 15:54А как именно отличаются статистические «слепки» Web-серфинга через HTTPS и точно такого же Web-серфинга через HTTPS через VPN?
Долгое соединение с одним web-сервером в реальной жизни довольно часто бывает, наврядли это будет расценено подозрительно.
Оверхед на каждый запрос немного пожирнее, чем обычно, но скорее всего тоже в пределах погрешности.
Что еще?DistortNeo
31.05.2018 16:16+1Ну так речь о том, чтобы отличить обычное HTTPS-соединение от соединения с Telegram-сервером over VPN, а не с HTTPS over VPN. Размер и частота пакетов в этом случае будет отличаться.
Я бы это реализовал так:
При активности на соединении по 443 порту более 15 минут и нехарактерном паттерне пакетов соединение помечается как подозрительное.
Как только соединение определяется как подозрительное, оборудование провайдера переходит к активному анализу — подключается к 443 порту и пытается понять, если ли там чо (OpenVPN, SSH, HTTPS и т.д.)
- Если нашлось что-нибудь интересное, кроме HTTPS, то тупо блочим по IP, иначе думаем дальше.
Вариант противодействия есть — это VPN over HTTPS. При запросе определённой секретной страницы происходит переключение на VPN протокол.
shifttstas Автор
31.05.2018 17:53Вы сейчас описали как работает Китайских фаервол в режиме «Опережающего подключения»
shifttstas Автор
31.05.2018 17:55Но есть и хорошая новость, в случае с Telegram Proxy — без знания ключа ничего не будет работать, openssl подключится без какого либо продолжения т.е сервис раскрыт не будет
DistortNeo
31.05.2018 14:40Да, может, но пока не делает так. Обход блокировок — это игра в кошки-мышки. Провайдер блокирует — люди находят новые способы для обхода.
lehnh
31.05.2018 16:18Если мультиплексировать трафик через openvpn share port, то в логах веб сервера адресом источника будет локалхост. У sslh такое же поведение?
F0iL
31.05.2018 16:24+1On Linux and FreeBSD you can use the --transparent option to request transparent proxying. This means services behind sslh (Apache, sshd and so on) will see the external IP and ports as if the external world connected directly to them.
lehnh
31.05.2018 17:14Не завелся транспарент( На гитхабе описано как такое работает и для очень частных случаев только можно применять. А жаль.
intet
31.05.2018 19:01Я новичок в стеке vpn/proxy, поэтому возможно немного глупый вопрос. Если есть vpn сервер расположенный в цивилизованной стране не блокирующей трафик и сервер
арендованный на деньги работодателярасположенный на мощностях ростелекома, то нужен ли SSLH чтобы развернуть реверс прокси и стучаться в удаленный сайт через впн просто подключаясь к Ростелекомовскому серверу.shifttstas Автор
31.05.2018 19:23Можно всё, цель непонятна.
intet
31.05.2018 19:34Цель в том, чтобы без настроек на стороне клиента заходить на сервер, который уже будет поднимать тунели/проксировать до сайта. Хочется настроить один раз и использовать на любой машине.
shifttstas Автор
31.05.2018 19:35+3вот это на самом деле уже не понятно:
без настроек на стороне клиента заходить на сервер
куда заходить? как? чем?
Если вы сможете по лучше объяснить цель, я смогу помочь с решением
intet
31.05.2018 19:52Заранеее спасибо за ответ.
Есть виртуальный сервер с публичным ip (centos, nginx) расположеный в России и vpn сервер расположенный за границей. Хочеться как-то настроить эту связку, так чтобы заходить на ip первого сервера, а уже сервер через тунель стучался к конкретному сайту (rutracker.org например). Сейчас же приходиться на каждом клиенте поднимать vpn соеденениеshifttstas Автор
31.05.2018 19:55+1гм, два nginx transparent proxy, российский смотрит на зарубежный, зарубежный смотрит на сайты, домены разместить в формате rutracker.ваш_домен.com, при обращении он должен отправлять запрос к истинному сайту. в случае с Apache, это настраивается через proxypass в две строки.
ProxyPass / http://0.0.0.0:8080/ ProxyPassReverse / http://0.0.0.0:8080/
www.digitalocean.com/community/tutorials/how-to-use-apache-http-server-as-reverse-proxy-using-mod_proxy-extension
PS А зачем в схеме вообще российский сервер?, он не несет никакой смысловой нагрузкиF0iL
31.05.2018 19:58+1Нужно так же отметить, что желательно все-таки на первом nginx/apache (на российском) установить фильтр по IP или какой-нибудь HTTP Auth, иначе есть риск, что рано или поздно он тоже влетит в список блокировок как зеркало.
shifttstas Автор
31.05.2018 20:08и еще эти методы не будут работать для https сайтов, выход — пропись IP сервера в HOSTS, но это еще менее удобно чем VPN, имхо тогда уж лучше просто прокси поднять да в браузер прописать во второй который для хождения по заблокированным ресурсам
intet
31.05.2018 20:11+1А зачем в схеме вообще российский сервер
Просто что Российский сервер, что акаунт VPN достались по наследству и совершенно бесплатны. Поэтому и хотелось обойтись чисто ими.
shifttstas Автор
31.05.2018 20:14я намекаю, что он лишнее звено в пищевой цепочке и его можно исключить.
intet
31.05.2018 20:19Это очевидно, что если есть заграничный сервер то прокси можно настраивать прямо на заграничном. Но в то-то и дело, что есть только Российский сервер и акаунт на vpn сервере. К самому зарубежному серваку доступа нет. Вот и думал, можно ли обойтись без полноценного сервера зарубежом или стоит не парить себе голову взять за 5$/месяц от DO.
shifttstas Автор
31.05.2018 20:24+1Вот теперь я вас наконец-то понял, заграничный у вас не сервер а просто арендованный VPN аккаунт.
Обойтись можно — на сервер подключаем VPN и настраиваем маршрутизацию аналогично как написано выше.
Но это все сложнее чем купить сервер или у DO за 5 евро или у arubacloud за 1 евро
inkvizitor68sl
01.06.2018 14:40+1Самое важное, что эта штука умеет не только в localhost.
VPN-сервер может находиться где угодно, а сам sslh может туда ходить по ipv6.
ErgoZru
01.06.2018 16:12К теме докера. Вы написали что у вас не получилось объединить с другими службами, я так понимаю у вас возникли проблемы с сетевыми интерфейсами? Если так, то не пробовали sshl запускать в контейнере с параметром --net host? Тогда по сути он будет работать в контейнере но в сетевом окружении хостовой машины. Или проблема была в другом?
shifttstas Автор
01.06.2018 16:18Проблема была в том, что при установке он выдаёт меня выбора в GUI какой тип использовать, докер естественно не может выбрать нужный.
ErgoZru
01.06.2018 16:30а у него нет варианта работы в не-интерактивном виде без dialog? Может проще собрать из исходников внутри контейнера? И чтобы занимало меньше места попробовать использовать build step'ы… Надо будет покопаться)
shifttstas Автор
01.06.2018 16:32К сожалению я не нашел, если у вас получится — я думаю ваш докер файл стоило бы приложить в основной репозиторий проекта
ErgoZru
01.06.2018 21:14Ну контейнер я сделал, собрал. Вроде всё ок.
Лежит на Docker HUB
Буду рад если кто-нибудь сможет протестировать, у меня пока возможности отладить до конца нет. За любой фидбек в личку буду благодарен :)
Если всё нормально работает, то можно и в пост upd добавить будет :)
ErgoZru
01.06.2018 21:56upd.
Протестировал. Всё работает замечательно. Вот например с телеграмом. Так что можете пользоваться. Пример использования есть на докер хабе. :)
sslh-select v1.19c-6-g552723c-dirty started anyprot:connection from ***-***-***.***:57994 to sslh:7443 forwarded from sslh:54486 to 172.17.0.2:https anyprot:connection from ***-***-***.***:57995 to sslh:7443 forwarded from sslh:54496 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45175 to sslh:7443 forwarded from sslh:54516 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45177 to sslh:7443 forwarded from sslh:54518 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45182 to sslh:7443 forwarded from sslh:54520 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45190 to sslh:7443 forwarded from sslh:54522 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45549 to sslh:7443 forwarded from sslh:54528 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45550 to sslh:7443 forwarded from sslh:54530 to 172.17.0.2:https anyprot:connection from ***-***-***.***:45551 to sslh:7443 forwarded from sslh:54532 to 172.17.0.2:https
achekalin
Я так смотрю, какие-то три
дурацкиебуквы вызвали такой невиданный рост внедрений и проксирования, и ipv6, плюс более глубокого понимания протоколов, что парням этим нужно не только занеосиливаниенедовыполнение «заданий Партии и Правительства» цацку и повышение давать, и но премию по линии министерства народного образования!