SSH внутри HTTP/HTTPS
В последнее время правила становятся все жёстче, провайдеры лютуют, режут трафик. Вот и столкнулся на днях с ситуацией когда, админ зарезал исходящий трафик оставив только веб. Замена ssh порта с 22 на 443 на удаленном сервере не помогла, видимо стоит какой DPI-фильтр.
В такой ситуации нам поможет websocat. Интересная приблуда, судя по описанию это: "Netcat, curl and socat for WebSockets." Можно собрать с исходников, есть готовые сборки под разные системы ссылка.
В большинстве случаев нам подойдет websocat.x86_64-unknown-linux-musl
Рассмотрим ситуацию когда у нас есть сервер А который находится за жёстким фаерволом корпоративной сети (доступен только исходящий веб-трафик), и на него нужно получить доступ из вне по SSH c сервера B где-то в интернете.
Первоначально нам нужно получить websocat и поднять на сервере B nginx c простейшей конфигурацией.
mkdir -p ~/commands && cd ~/commands
wget https://github.com/vi/websocat/releases/download/v1.10.0/websocat.x86_64-unknown-linux-musl
mv ./websocat.x86_64-unknown-linux-musl ./websocat
dnf install nginx -y
server {
listen 123.123.123.123:80;
server_name 123.123.123.123;
location /wstunnel/ {
proxy_pass http://127.0.0.1:33333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
Где 123.123.123.123 - это внешний IP-адрес сервера B (который будет принимать http/https соединения)
Далее поднимаем websocat в фоне, либо можно в screen-е.
$HOME/commands/websocat -E --binary ws-l:127.0.0.1:33333 tcp:127.0.0.1:22 &
Переходим к настройке на стороне сервера А. Таким же образом получаем на сервер websock и запускаем туннель.
ssh -f -N -R 2233:127.0.0.1:22 -o ProxyCommand='~/commands/websocat --binary ws://123.123.123.123/wstunnel/' root@123.123.123.123
Что тут происходит: сервер А через http сокет подключается на web-сервер B (123.123.123.123), где Nginx принимает входное соединение и проксирует его на websocat, который в свою очередь соединяет c SSH сервером. Далее организовывается туннель, на сервере B поднимается порт 127.0.0.1:2233, при подключении на который мы выходим на SSH на сервере A.
Если необходим туннель по HTTPS, то потребуется реальный домен, чтоб поднять сертификаты (certbot в помощь), и в соединении меняем ws на wss