Начало
Все началось с идеи, как и всегда. Кто-то при мне упомянул про удаленный доступ без покупки белого IP и я вспомнил, как хотел осуществить подобное когда-то, но руки так и не дошли.
Но, благодаря этому, я, так же, вспомнил, как когда-то давно, я наткнулся на статью про ngrok. Ссылки на нее, к сожалению, я не сохранил и, благополучно забыл. Но теперь, с пылающей идеей в голове, я устремился на поиски самого ценного ресурса, для осуществления задуманного — информации.
ngrok — это сервис, который позволяет открыть доступ к внутренним ресурсам машины, на которой он запущен, из внешней сети, путем создания публичного адреса, все запросы на который будут переброшены на локальный адрес и заданный порт.
Кстати, о железе. Мой сервер, это крохотный raspberry pi 4 c 8-ю гигами оперативной памяти под управлением 21 Ubuntu, на котором у меня постоянно крутятся мои разработки.
Установка ngrok
Для начала, регистрируемся на сайте и получаем токен.
Далее выполняем:
snap install ngrok
Далее нужно добавить полученный токен командой:
ngrok authtoken <ваш токен>
И все, установка завершена.
Туннель в небе
Теперь остается только открыть туннель для вашего ресурса. Это мог бы быть сайт, или еще какой проект, или, вообще, БД.
Мы же открываем удаленный доступ. Значит, ssh. Значит 22 порт по умолчанию.
ngrok tcp 22
На экране появится что-то вроде:
Туннель открыт. Главное здесь это поле Forwarding, которе имеет примерно такое содержимое: tcp://0.tcp.eu.ngrok.io:12345.
Теперь все запросы по этому адресу будут транслироваться на localhost:22 где их ожидает ssh.
Что бы подключиться удаленно выполним:
ssh 0.tcp.eu.ngrok.io -p 12345
Введя имя пользователя и пароль, попадаем на устройство. Готово! Поздравляю!
А если перезагрузится?
Ну, а правда, если по какой-то причине, сервер перезагрузится, туннель же закроется. Непорядок.
Но я уже работал с systemctl, так что эта проблема — вопрос нескольких минут.
Очень советую ознакомится с этой крутой штукой.
systemd — подсистема инициализации и управления службами в Linux, фактически вытеснившая в 2010-е годы традиционную подсистему init. Основная особенность — интенсивное распараллеливание запуска служб в процессе загрузки системы, что позволяет существенно ускорить запуск операционной системы. Основная единица управления — модуль, одним из типов модулей являются «службы» — аналог демонов — наборы процессов, запускаемые и управляемые средствами подсистемы и изолируемые контрольными группами.
Пишем файл ngrok.service и помещаем его в /etc/systemd/system/ (требуются рут права)
Содержимое файла:
[Unit]
Description=ngrok
After=network.target
After=syslog.target
[Service]
Type=simple
ExecStart=/snap/bin/ngrok tcp 22
Restart=always
RestartSec=1
WorkingDirectory=/home/vladimir/prog/python/projects/ngrok
User=vladimir
Group=vladimir
StartLimitBurst=99999
StartLimitInterval=999999
[Install]
WantedBy=multi-user.target
Активируем сервис:
sudo systemctl enable ngrok.service
И запускаем:
sudo systemctl start ngrok.service
Теперь, даже, если сервер перезагрузится, этот сервис запусится автоматически.
Ngrok API
При каждом открытии туннеля ngrok, адрес подключения будет разным.
Как тогда удаленно узнать новый адрес? Это несложно. У ngrok есть собстенный API
И есть там требуемый роут /tunnels.
Однако, для начала, нужно получить API токен. На сайте сервиса.
Подобный запрос:
curl --location --request GET 'https://api.ngrok.com/tunnels' --header 'Authorization: Bearer <ваш API токен>' --header 'Ngrok-Version: 2'
Даст такой результат, если не открыто ни одного туннеля:
{
"tunnels": [],
"uri": "https://api.ngrok.com/tunnels",
"next_page_uri": null
}
И если есть:
{
"tunnels": [
{
"id": "<privat>",
"public_url": "tcp://0.tcp.eu.ngrok.io:12345",
"started_at": "2099-06-15T10:46:13Z",
"metadata": "",
"proto": "tcp",
"region": "eu",
"tunnel_session": {
"id": "<privat>",
"uri": "https://api.ngrok.com/tunnel_sessions/<privat>
},
"endpoint": {
"id": "<privat>",
"uri": "https://api.ngrok.com/endpoints/<privat>"
},
"forwards_to": "localhost:22"
}
],
"uri": "https://api.ngrok.com/tunnels",
"next_page_uri": null
}
Как видите, вся необходимая информация, для подключения есть в поле "public_url". Можно подключаться.
Еще немножко автоматизации
Как говорил один великий: "Я человек простой: вижу то, что можно автоматизировать — автоматизирую".
Каждый раз курлить или залезать в постман ради нового адреса туннеля — не дело.
Пишем скрипт.
В баше я не особо силен, но написанного хватает с головой:
#!/bin/bash
res=$(curl --location --request GET 'https://api.ngrok.com/tunnels' \
--header 'Authorization: Bearer <ваш API токен>' \
--header 'Ngrok-Version: 2' | awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "public_url") {print $4}}')
if [ -z "$res" ]
then
echo "No tunnels"
exit
fi
ip_port=$(echo ${res:6})
arr=($(echo $ip_port | tr ":" "\n"))
ip=$(echo ${arr[0]})
port=$(echo ${arr[1]})
ssh $ip -p $port
Так как в бесплатном аккаунте, можно открывать только один туннель, проблем с выбором у скрипта не возникнет.
Итоги
В этой статье был описан способ организации удаленного доступа по протоколу ssh к серверу под управлением Ubuntu.
Будте осторожны. Помните, вы открываете туннель не только для себя, но и для всего мира. Озаботьтесь безопасностью.
У меня управление туннелями выведено в свой telegram бот. И оповещения о попытках ssh подключении приходят туда же. Если кому будет интересно, расскажу, как это сделал, но уже в другой статье.
Комментарии (20)
cepera_ang
29.06.2022 15:06-1В стопятьсотмиллионный раз посоветую http://tailscale.com/ всем зашедшим на огонёк огранизации удалённого доступа (с белым айпи или нет — пофиг вообще). Перефразируя слова из статьи: можете не быть осторожны, помните, вы организуете совершенно безопасный доступ для себя и только для себя. И бонусом — требуется 0 конфигурации.
litos
29.06.2022 15:08+3Тоже что-то платное? https://tailscale.com/contact/sales/
Что мешает купить свой VPS за 3 доллара в месяц и настроить VPN с клиентов и проброс портов через него?
cepera_ang
29.06.2022 15:11Нет, бесплатный вариант для домашнего или небольшого профессионального использования будет за глаза. А гитхаб план вообще 95% потребностей закроет даже для мелких компаний.
Разница между покупкой VPS за 3 доллара и настройкой всяких портов и прочей вознёй и работающей просто из коробки всегда надёжно системой — гораздо больше чем может показаться на первый взгляд. Попробовав второе уже навсегда становится непонятно «зачем?» нужен первый вариант :)
bepim
29.06.2022 15:57+1Разница между покупкой VPS за 3 доллара и настройкой всяких портов и
прочей вознёй и работающей просто из коробки всегда надёжно системойhttps://github.com/angristan/openvpn-install/
всё ставится одной строчкой, работает годами
cepera_ang
29.06.2022 16:21Также легко одной строчкой ставится на телефон, планшет, распбери, виндовый компьютер и микроволновку. А ещё пробивает почти любые наты, не обрывает соединение при смене сети, автоматически выбирает самый короткий маршрут, ротирует ключи/сертификаты периодически. А, ещё позволяет легко пошарить любую из машинок с кем-нибудь, с возможностью в один клик отозвать доступ. Да?
bepim
29.06.2022 16:39+1На телефон, планшет, малинку и виндовый комп ставится импортированием .ovpn файла, то есть в два клика. Сам файл создаётся одной строчкой.
Проблем с NAT за годы использования в разных странах и у разных провайдеров/опсосов замечено не было, при смене сети переподключается автоматом средствами ОС (всякие ssh этого не замечают, а кроме него мне нигде бесшовная сессия не нужна).
Пошарить машинку - одной строчкой даётся и отзывается доступ.
По поводу ротации ключей/сертификатов и длины маршрутов предлагаю вам самому ознакомиться: я не шарю, просто пользуюсь в своё удовольствие, нареканий не имею.
HackcatDev
30.06.2022 15:06+3У коробочного решения всегда есть ровно один недостаток, делающий всё решение бесполезным для большинства применений. Суть его в том, что за пределами рекомендуемого сценария использования никогда ничего не работает без костылей, и ты будешь плеваться, вставляя очередной костыль, пока не сделаешь свое решение, которое будет работать хорошо именно для твоей ситуации. Проще всего его построить как раз из опенсорсных скриптов, наподобие упомянутых выше
cepera_ang
30.06.2022 15:20Вы очевидно не посмотрели на предложенное решение, или посмотрели краем глаза. С таким же успехом можно сказать, что у интернета, как коробочного решения, есть рекомендуемый сценарий использования, за пределами которого придётся плеваться, вставляя очередной костыль.
Впрочем, я звучу как евангелист какой-то, и не нахожу понимания, рассказывая о том, что VPN решение может просто работать, людям, травмированным постоянным геморроем и костылингом «именно для своей ситуации».
HackcatDev
01.07.2022 15:04у интернета, как коробочного решения, есть рекомендуемый сценарий использования
Сценарий использования -- как раз "городить любой огород", потому что интернет -- это не "тыкни вот эту кнопочку, чтобы купить Windows", а "у тебя есть возможность установить соединение между вот этими узлами, делай что хочешь".
И вот если пытаться делать что-то за пределами передачи информации по уже придуманным и общепринятым протоколам -- да, могут быть проблемы. Только до использования сети настолько не по назначению врад-ли доходил кто-либо из присутствующих
jstbot
29.06.2022 15:57не для того что бы во внешний мир открыть какой то доступ, а получить доступ до любого устройства из многих своих(хоть с телефона), до сих пор использую ZeroTier
idruzhitskiy
29.06.2022 15:57+1Еще вариант - настроить ddns (например duckdns.org), обновление записи поставить по крону. И не придется ходить через сторонние серверы.
turbidit
29.06.2022 16:25Как ddns поможет с серым ip?
idruzhitskiy
29.06.2022 17:14Скрипт каждые n минут обновляет ip на ddns сервере. В итоге к машине можно подключаться через выбранный ddns адрес.
turbidit
29.06.2022 17:38+4Как вы подключитесь извне к серому адресу? Думаю, вы путаете серый и белый динамический.
FSA
30.06.2022 15:02+1Самый надёжный и простой вариант - дешёвый VPS с Wireguard. Минимум настроек. Прокинуть на клиентов можно что угодно. При желании можно использовать для починки сети из-за блокировок РКН.
litos
Но ведь это коммерческое решение судя по сайту https://ngrok.com/pricing с «чужим» сервером?