Доступ к ssh серверу через очень зарегулированное подключение

Эта статья является результатом посещения мной автосервиса. В ожидании машины я подключил свой ноутбук к гостевой wifi-сети и читал новости. К своему удивлению я обнаружил, что некоторые сайты я посетить не могу. Зная про sshuttle (и будучи большим поклонником этого проекта) я попытался установить sshuttle сессию со своим сервером, но не тут-то было. Порт 22 был наглухо заблокирован. При этом nginx на порту 443 отвечал нормально. К следующему посещению автосервиса я установил на сервер мультиплексор sslh. Сервер работает под управлением gentoo и я добавил следующую строчку в файл /etc/conf.d/sslh:

DAEMON_OPTS="-p 0.0.0.0:443 --ssl 127.0.0.1:8443 --ssh 127.0.0.1:22 --user nobody"

В зависимости от типа коннекта, соединения на порт 443 либо пробрасываются на локальный порт:


Но при попытке установить ssh соединение с сервером меня опять постигла неудача. Видимо фильтрация осуществлялась не просто по портам, но также использовался deep packet investigation. Таким образом задача усложняется. Ssh трафик надо обернуть в https. К счастью это не сложно благодаря проекту websocat. На странице проекта вы можете найти много собранных бинарников. Если по какой-то причине вы хотите собрать бинарник самостоятельно из исходников это тоже не очень сложно. Я делаю это при помощи packer от hashicorp при помощи вот такой конфигурации:

{
  "min_packer_version": "1.6.5",
  "builders": [
    {
      "type": "docker",
      "image": "ubuntu:20.04",
      "privileged": true,
      "discard": true,
      "volumes": {
        "{{pwd}}": "/output"
      }
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "skip_clean": true,
      "environment_vars": [
        "DEBIAN_FRONTEND=noninteractive"
      ],
      "inline": [
        "apt-get update && apt-get install -y git curl gcc libssl-dev pkg-config gcc-arm-linux-gnueabihf",
        "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs >/tmp/rustup.sh && chmod +x /tmp/rustup.sh && /tmp/rustup.sh -y",
        "git clone https://github.com/vi/websocat.git && cd websocat/",
        ". $HOME/.cargo/env && cargo build --release --features=ssl",
        "printf '[target.armv7-unknown-linux-gnueabihf]\nlinker = \"arm-linux-gnueabihf-gcc\"\n' >$HOME/.cargo/config",
        "rustup target add armv7-unknown-linux-gnueabihf",
        "cargo build --target=armv7-unknown-linux-gnueabihf --release",
        "strip target/release/websocat",
        "tar czf /output/websocat.tgz target/armv7-unknown-linux-gnueabihf/release/websocat target/release/websocat",
        "chown --reference=/output /output/websocat.tgz"
      ]
    }
  ]
}

Клиентская сторона у меня на ubuntu 20.04, сервер работает на nvidia tegra jetson tk1, так что для него я делаю кросс-сборку под платформу armv7. Обратите внимание, что серверная сборка делается без поддержки ssl, так как ssl termination у меня осуществляет nginx, который обрабатывает входящие соединения. Конфигурация nginx выглядит вот так:

http {
    server {
        listen 0.0.0.0:8443 ssl;
        server_name your.host.com;
        ssl_certificate /etc/letsencrypt/live/your.host.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your.host.com/privkey.pem;
        location /wstunnel/ {
            proxy_pass http://127.0.0.1:8022;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }
    }
}

Websocat я запускаю из крона своего юзера:

* * * * * netstat -lnt|grep -q :8022 || $HOME/bin/websocat -E --binary ws-l:127.0.0.1:8022 tcp:127.0.0.1:22|logger -t websocat &

Теперь вы можете соединиться с вашим сервером вот так:

ssh -o ProxyCommand='websocat --binary wss://your.host.com/wstunnel/' your.host.com

Насколько заворачивание в https снижает пропускную способность? Для того, чтобы это проверить я использовал вот такую команду:

ssh -o ProxyCommand='websocat --binary wss://your.host.com/wstunnel/' your.host.com 'dd if=/dev/zero count=32768 bs=8192' >/dev/null

В моих экспериментах я получил снижение пропускной способности в 2 раза. При использовании протокола ws://, т.е. http, пропускная способность соединения идентична необернутому ssh.

А вот так можно установить сессию sshuttle:

sshuttle -e 'ssh -o ProxyCommand="websocat --binary wss://your.host.com/wstunnel/"' -r your.host.com 0/0 -x $(dig +short your.host.com)/32

При очередном визите в автосервис я убедился, что все работает как надо. В качестве приятного бонуса резко упало количество попыток залогиниться на сервер через ssh с левых адресов.
@kt97679
07.12.2020 06:07 UTC
Первоисточник

Комментарии

@Softer
07.12.2020 01:26 UTC
0
Websocat я запускаю из крона своего юзера:
* * * * * netstat -lnt|grep -q :8022 || $HOME/bin/websocat -E --binary ws-l:127.0.0.1:8022 tcp:127.0.0.1:22|logger -t websocat &

Если совсем влом писать init или unit —
@reboot $HOME/bin/websocat -E --binary ws-l:127.0.0.1:8022 tcp:127.0.0.1:22|logger -t websocat &
@kt97679
07.12.2020 01:44 UTC
0
Согласен, но мне хотелось автоматического рестарта особенно в процессе наладки.
09.12.2020 19:21 UTC
0

так-то получше, чем ежеминутный крон?


while(1); do $HOME/bin/websocat .... ; done

Ну а в systemd есть Restart=. Для наколеночных скриптов он довольно удобен оказался.

09.12.2020 19:38 UTC
0
Я не хотел выносить websocat в системный сервис. В моей ситуации я посчитал cron оптимальным решением. Безусловно возможны другие решения, которые для кого-то окажутся предпочтительнее. На этом сервере используется openrc, systemd там нет.
@Daniyar94
07.12.2020 05:41 UTC
+1

Когда со мной такое произошло, я использовал OpenVPN и stunnel который мимикрирует соединение под HTTPS/443 SSL трафик. После подключения ssh по внутреннему адресу.

@alexyr
07.12.2020 06:34 UTC
+1
Ещё есть shadowsocks… он у меня вместе с VPN поднят, чтобы был выбор
@
07.12.2020 06:36 UTC
0
НЛО прилетело и опубликовало эту надпись здесь
@KEKSOV
07.12.2020 07:37 UTC
0
Ну, через мобильник то каждый может, да и статья не про это… ))
07.12.2020 08:02 UTC
-1
Сначала мы создаём себе трудности, а потом героически преодолеваем их, да.
@VolCh
07.12.2020 08:34 UTC
+1

Мобильный трафик экономить

@IgorGIV
07.12.2020 08:53 UTC
0
Бывают ситуации, когда сотовый в конкретном месте либо ловит очень плохо, либо не ловит вообще.
@vlad49
07.12.2020 08:57 UTC
0
Автосервис с таким вайфаем — большая редкость, но вот во всяких режимных заведениях или больших корпорациях — вполне может быть. Вкупе с очень плохим сигналом сотовой сети. Попадал несколько раз, но к счастью DPI на 443-м порту там не было. Статья хорошая, чтобы подготовиться на всякий случай.
@kt97679
07.12.2020 18:48 UTC
0
Причина очень простая: когда я занимался этой задачей я использовал план pay-as-you-go, который вообще не поддерживал данных.
@Fullmoon
07.12.2020 08:57 UTC
0

Вместо websocat не пробовали corkscrew? Он, правда, пару лет не обновлялся, но его не нужно ставить на сервер.

@kt97679
07.12.2020 18:46 UTC
0
Если я правильно понял corkscrew нужен при установлении ssh соединения через прокси. Или я что-то не так понял? В моем случае прокси не было.
07.12.2020 20:29 UTC
0

А, да, действительно. Невнимательно читал, пардон.

@haryaalcar
07.12.2020 13:24 UTC
0
Дополнение от автора websocat:
Рекомендовано использовать опции Nginx «proxy_read_timeout» и «proxy_send_timeout» с относительно большими значениями (хотя бы час), чтобы подключение не отваливалось от неактивности.

Пример фрагмента Nginx есть в документации (https://github.com/vi/websocat/blob/master/doc.md#unix-listen). Наверное, его следует сделать более видимым, ближе к README.
@KpblcuK
07.12.2020 18:48 UTC
0
Можете подробнее написать, для чего это? Вроде SSTP давно изобрели.
@kt97679
07.12.2020 18:51 UTC
0
Если я правильно понимаю SSTP это все же не https, а мне было интересно спрятать ssh в https.
08.12.2020 10:00 UTC
0
Соединение идет именно по HTTPS и внутри HTTPS:
habr.com/ru/post/196134
@rogoz
07.12.2020 19:09 UTC
0
Вроде бы более мейнстримово это делается с помощью stunnel.
@sleirsgoevy
08.12.2020 08:56 UTC
+1
stunnel палится при попытке «попинговать» сервер обычным HTTP-клиентом. В случае с туннелем через nginx можно
а) держать на той же машине еще и обычный веб-сервер и
б) отрицать существование туннеля, поскольку, чтобы доказать обратное, нужно знать конкретный endpoint URL, который из зашифрованного трафика получить нереально.
08.12.2020 12:57 UTC
0
Или stunnel держать за SSLH, а дифференцировать по SNI. Так можно держать и обычный сервер, и «палевный» openvpn на том же 443 порту.
Правда замечание б) не убирается, SNI передаётся в открытом виде. Хотя в принципе можно сделать HTTPS трафик без SNI на stunnel, со SNI на веб-сервер.
@janatem
08.12.2020 00:52 UTC
0
dd if=/dev/zero

Для оценки скорости лучше использовать нетривиальные данные (например, брать из /dev/urandom). Иначе придется проследить, что компрессия отключена (а это зависит не только от наличия опции -C, но и от ssh_config и sshd_config).
@kt97679
08.12.2020 01:13 UTC
0
Вы безусловно правы, в свое оправдание могу только сказать, что /dev/urandom работает существенно медленее, чем /dev/zero:

kvt@joy:~$ time dd if=/dev/urandom count=32768 bs=8192 >/dev/null && time dd if=/dev/zero count=32768 bs=8192 >/dev/null
32768+0 records in
32768+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 6.27352 s, 42.8 MB/s

real 0m6.278s
user 0m0.016s
sys 0m6.262s
32768+0 records in
32768+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 0.0423418 s, 6.3 GB/s

real 0m0.044s
user 0m0.016s
sys 0m0.028s
kvt@joy:~$
08.12.2020 22:29 UTC
0
Да, действительно, слишком медленно. Придется в файл сохранять, чтоб по-взрослому было.
09.12.2020 19:24 UTC
0
42.8

Что-то медленно. Это малинка? И всё равно быстрее вайфая.

09.12.2020 19:40 UTC
0
t470s, процессор: Intel® Core(TM) i7-7600U CPU @ 2.80GHz

я тестировал на проводном подключении.
10.12.2020 08:15 UTC
0

Ох уж эти мобильные процессоры. У меня тут под рукой есть тёплый ламповый Athlon 64 X2 2006 года разработки, так у него urandom выдаёт 73,0 MB/s.

@9660
08.12.2020 02:38 UTC
0
Видимо фильтрация осуществлялась не просто по портам, но также использовался deep packet investigation.

Любопытно знать для чего кто-то так сильно заморочился.
Ладно бы действительно режимное предприятие… но автосервис?
@kt97679
08.12.2020 02:47 UTC
0
Не представляю :). С другой стороны я даже рад, что они это сделали. Таким образом я мог проверять разные подходы в условиях максимально похожих на суровую реальность.
@baldr
08.12.2020 16:39 UTC
+2

А всего-то надо было зайти на админку роутера и ввести дефолтный пароль чтобы добавить себя в whitelist (и поменять пароль на более защищенный чтобы защитить от хакеров (-: ).