LINUX.ORG.RU
ФорумAdmin

Как сделать SSH туннель сервисом systemd?

 , , , ,


0

3

Пытаюсь вывести домашний сервер в сеть, одним из решений является удаленный проброс порта. В качестве промежуточного сервера выбор пал на Serveo. При запуске напрямую из консоли все работает:

$ ssh -R test.serveo.net:80:localhost:80 serveo.net
Forwarding HTTP traffic from https://test.serveo.net

Но нужно чтобы туннель работал фоном и начиная со старта системы, что можно реализовать в качестве сервиса systemd. Файл сервиса:

[Unit]
Description=Serveo
After=network.target

[Service]
ExecStart=/usr/bin/ssh -R test.serveo.net:80:localhost:80 serveo.net
Restart=on-failure
RestartSec=5
StandardInput=tty-force

[Install]
WantedBy=default.target

Но в таком случае перенаправление не работает. Вывод systemctl status:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-03-13 12:00:00 +07; 15min ago
   Main PID: 7223 (ssh)
      Tasks: 1 (limit: 2313)
     Memory: 1.1M
        CPU: 21ms
     CGroup: /system.slice/serveo.service
             └─7223 /usr/bin/ssh -R test.serveo.net:80:localhost:80 serveo.net

мар 13 12:00:00 server systemd[1]: Started serveo.service - Serveo.

Что не так и как исправить? Или же может есть кардинально другие решения вопроса?

★★★

Последнее исправление: GREAT-DNG (всего исправлений: 1)

Ответ на: комментарий от intelfx

Тогда всё падает:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Wed 2024-03-13 12:00:00 +07; 5s ago
    Process: 8401 ExecStart=/usr/bin/ssh -fN -R test.serveo.net:80:localhost:80 serveo.net (code=exited, status=255/EXCEPTION)
   Main PID: 8401 (code=exited, status=255/EXCEPTION)
        CPU: 22ms

мар 13 12:00:00 server systemd[1]: serveo.service: Failed with result 'exit-code'.

Есть упоминание что конкретно для Serveo нужен интерактивный шелл.

Upd: с Type=forking, то же самое, только без последней строки.

GREAT-DNG ★★★
() автор топика
Последнее исправление: GREAT-DNG (всего исправлений: 1)
Ответ на: комментарий от intelfx
#!/usr/bin/env expect -f

spawn -noecho /usr/bin/ssh -fN -R test.serveo.net:80:localhost:80 serveo.net
catch wait status
exit [lindex $status 3]

Верно?

При запуске (вручную, без systemd) пишет:

/usr/bin/env: «expect -f»: Нет такого файла или каталога
/usr/bin/env: используйте -[v]S для передачи параметров в строках #!

Я сам bash скриптах не разбираюсь особо, как можно исправить?

Debian 12 если что

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от ValdikSS

Уже пробовал, не заработало, аналогично:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: active (running) since Wed 2024-03-13 12:00:00 +07; 10s ago
   Main PID: 18238 (autossh)
      Tasks: 2 (limit: 2313)
     Memory: 1.3M
        CPU: 47ms
     CGroup: /system.slice/serveo.service
             ├─18238 /usr/lib/autossh/autossh -R test.serveo.net:80:localhost:80 serveo.net
             └─18250 /usr/bin/ssh -L 50087:127.0.0.1:50087 -R 50087:127.0.0.1:50088 -R test.serveo.net:80:localhost:80 serveo.net

мар 13 12:00:00 server systemd[1]: Started serveo.service - Serveo.
мар 13 12:00:00 server autossh[18238]: starting ssh (count 1)
мар 13 12:00:00 server autossh[18238]: ssh child pid is 18250
GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от GREAT-DNG

Да, там шебанг неправильный. Linux разбивает шебанг максимум на два аргумента, поэтому приходится использовать костыли.

#!/usr/bin/env -S expect -f попробуй. Или найди полный путь до expect (which expect) и впиши #!/путь/до/expect -f.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Ой, expect просто установлен не был =)

С Type=forking при systemctl restart:

Job for serveo.service failed because a timeout was exceeded.
See "systemctl status serveo.service" and "journalctl -xeu serveo.service" for details.

В journalctl пусто, systemctl status:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: activating (start) since Wed 2024-03-13 12:00:00 +07; 15s ago
  Cntrl PID: 22378 (serveo)
      Tasks: 2 (limit: 2313)
     Memory: 2.0M
        CPU: 33ms
     CGroup: /system.slice/serveo.service
             ├─22378 /usr/bin/expect -f /usr/bin/serveo
             └─22379 /usr/bin/ssh -fN -R test.serveo.net:80:localhost:80 serveo.net

systemctl status без Type=forking:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: active (running) since Wed 2024-03-13 12:00:00 +07; 5s ago
   Main PID: 23313 (serveo)
      Tasks: 2 (limit: 2313)
     Memory: 2.0M
        CPU: 33ms
     CGroup: /system.slice/serveo.service
             ├─23313 /usr/bin/expect -f /usr/bin/serveo
             └─23315 /usr/bin/ssh -fN -R test.serveo.net:80:localhost:80 serveo.net

мар 13 12:00:00 server systemd[1]: Started serveo.service - Serveo.
GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от GREAT-DNG

Тут без forking, естественно. И без -fN, всё как было у тебя раньше (хотя -N можешь попробовать оставить ради корректности, но не знаю, как это твоё serveo к нему отнесётся).

И я не думаю, что expect зеркалирует вывод в stdout. Проверь, работает ли по факту.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от anonymous

Насколько мне известно, все кто обслуживают дом - продают белый IP, а покупать не хочется.

Если я правильно понял о чем ты.

GREAT-DNG ★★★
() автор топика
Последнее исправление: GREAT-DNG (всего исправлений: 1)
Ответ на: комментарий от GREAT-DNG

https://github.com/jnovack/autossh

поставь докер композ и докер, создай файл docker-compose.yml, скопируй нужный код, запусти:

docker-compose up -d

И не надо сидеть системд эти писать. Хватит шизофренией страдать. Докероненавистники - это отдельный диагноз типа противников системды, слушать их - себя не уважать

Ну и главный плюс дрокера, что там копипастом можно этих тоннелей сделать хоть миллиард, разом их запустить или убить

rtxtxtrx
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)

Зачем так сложно. Простой баш скрипт, который при старте проверяет наличие туннеля и поднимает его в бесконечном цикле если его нет.

Скрипт в кронтаб на @reboot.

У меня такое уже лет 5 работает.

ya-betmen ★★★★★
()
Ответ на: комментарий от GREAT-DNG

Может оказаться, что продают именно статический адрес, а динамический и так выдают белый. К тому же, считается нормальным (ну, мне так показалось) при отсутствии белого IPv4 предоставлять IPv6. А костыли вроде SSH-туннелей на васянских серверах — путь боли и страданий.

anonymous
()

А я три дня назад написал как пробросить порт аж тремя способами. (=

И первым же замечанием про ssh было то, что автозапуск придётся изобретать (подразумевая что это будет больно). (=

mord0d ★★★★★
()
Ответ на: комментарий от ya-betmen

Да, это будет работать… ровно до тех пор, пока тебе не понадобится что-то чуть сложнее или пока не появится что-то что может конфликтовать, и ты задолбаешься это дебажить, если забудешь что у тебя где раскидано.

Вообще, использовать для подобной задачи cron — надевание штанов через голову (иногда даже через голову соседа).

mord0d ★★★★★
()
Ответ на: комментарий от GREAT-DNG

Ну, разумеется, нужно еще принять сертификат сервера пользователем, от имени которого вы запускаете ssh, либо отключить эту опцию.

SSH запускать без выделения TTY и без запуска команд, я делаю вот так:

-o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o StrictHostKeyChecking=accept-new -TN

А самому autossh желательно указывать -M 0.

ValdikSS ★★★★★
()
Последнее исправление: ValdikSS (всего исправлений: 3)
Ответ на: комментарий от mord0d

Да, это будет работать… ровно до тех пор, пока тебе не понадобится что-то чуть сложнее

И продолжит работать после

пока не появится что-то что может конфликтовать

Как и при любом другом способе

и ты задолбаешься это дебажить

Человек уже задолбался а результата так и нет

Вообще, использовать для подобной задачи cron

Простой и логичный способ

ya-betmen ★★★★★
()
Ответ на: комментарий от intelfx

Всё так же не работает, весь вывод что есть в systemctl status:

...
     CGroup: /system.slice/serveo.service
             ├─6268 /usr/bin/expect -f /usr/bin/serveo
             └─6271 /usr/bin/ssh -R test.serveo.net:80:localhost:80 serveo.net

мар 14 12:00:00 server systemd[1]: Started serveo.service - Serveo.

С -N то же самое.

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от rtxtxtrx

Попробую если не получится сделать сервисом. Фобией докера не страдаю, все веб приложения в нем и запущены, просто помимо собственно задачи хочу разобраться с сервисами systemd.

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от anonymous

Может оказаться, что продают именно статический адрес, а динамический и так выдают белый.

Текущий провайдер выдает все же серый IP, насколько я помню по давним экспериментам.

К тому же, считается нормальным (ну, мне так показалось) при отсутствии белого IPv4 предоставлять IPv6.

А как проверить его наличие?

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от ValdikSS
мар 14 12:00:00 server systemd[1]: serveo.service: Main process exited, code=exited, status=1/FAILURE
мар 14 12:00:00 server systemd[1]: serveo.service: Failed with result 'exit-code'.

С -M 0, но аналогично не работает:

● serveo.service - Serveo
     Loaded: loaded (/etc/systemd/system/serveo.service; enabled; preset: enabled)
     Active: active (running) since Thu 2024-03-14 11:54:55 +07; 2s ago
   Main PID: 14773 (autossh)
      Tasks: 2 (limit: 2313)
     Memory: 1.3M
        CPU: 31ms
     CGroup: /system.slice/serveo.service
             ├─14773 /usr/lib/autossh/autossh -M 0 -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o StrictHostKeyChecking=accept-new -TN -R test.serveo.net:80:localhost:80 serveo.net
             └─14774 /usr/bin/ssh -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o StrictHostKeyChecking=accept-new -TN -R test.serveo.net:80:localhost:80 serveo.net

мар 14 12:00:00 server systemd[1]: Started serveo.service - Serveo.
мар 14 12:00:00 server autossh[14773]: port set to 0, monitoring disabled
мар 14 12:00:00 server autossh[14773]: starting ssh (count 1)
мар 14 12:00:00 server autossh[14773]: ssh child pid is 14774
GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от ya-betmen

Тоже вариант. Но в вашем решении есть недостаток, если скрипт упадет, то хана до ребута, а если доступа к девайсу нэма, то большая печалька. Но в целом направление мысли правильное, у меня по крону (не на ребуте) проверяются наличия тоннелей и если кто-то упал, то его переподнимаем.

anc ★★★★★
()
Ответ на: комментарий от GREAT-DNG

Профиль редактировать мне @maxcom запретил. ☺ Использованный для регистрации адрес электронной почты на сервере, который был внесён в блэклист, так что при попытке сохранить изменения ЛОР ругается что у меня "неправильный" адрес электронной почты.

В любом случае это тебе ничего не даст: я рассматривал проброс порта (host1→host2), а тебе нужен обратный проброс (host1←host2). В общем, там ssh -L, а не ssh -R. И про автозапуск написано только что его придётся изобретать самостоятельно.

Хотя, если у тебя есть полный доступ к удалённой машине, можешь через openvpn/wireguard/strongswan/whatever создать туннель и пробросить порт любым другим способом: haproxy/nginx/файерволл/whatever. А через ssh это для непостоянного использования.

mord0d ★★★★★
()
Ответ на: комментарий от ya-betmen

Можно засунуть на каждую минуту в крон. Раньше так было, но падений самого скрипта так и не было замечено, поэтому отказался от такого.

«не было замечено» != «такого никогда не произойдет». Причем «упасть» может в том числе и из-за «ваших шаловливых ручек».
ЗЫ А вот минута это имхо перебор, за минуту может и не подняться и начнется «гонка».

anc ★★★★★
()
Ответ на: комментарий от ValdikSS
[Unit]
Description=Serveo
After=network.target

[Service]
ExecStart=/usr/lib/autossh/autossh -v -M 0 -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o StrictHostKeyChecking=accept-new -TN -R test.serveo.net:80:localhost:80 serveo.net
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

Так же?

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от ya-betmen

надо отдельно с cron разбираться.

В том то и прикол, что не надо.

Я не про потенциальную проблему, а про собственно реализацию, пока что не знаю как это делается в cron.

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от mord0d

Хотя, если у тебя есть полный доступ к удалённой машине, можешь через openvpn/wireguard/strongswan/whatever создать туннель и пробросить порт любым другим способом: haproxy/nginx/файерволл/whatever.

Проблема в том что где-то нужно достать бесплатный сервер и домен.

GREAT-DNG ★★★
() автор топика
Ответ на: комментарий от GREAT-DNG

Я не про потенциальную проблему, а про собственно реализацию, пока что не знаю как это делается в cron.

$man crontab
#crontab -e
Add line such as
*/5 * * * * /path-to-you-script/scriptname
Здесь первое поле */5 означает выполнение каждые 5 минут.

anc ★★★★★
()
Последнее исправление: anc (всего исправлений: 1)