Serwer proxy SSH Socks na żądanie za pośrednictwem systemowych jednostek użytkownika z aktywacją gniazda nie uruchamia się ponownie zgodnie z życzeniem


14

Aby połączyć się z izolowaną siecią, używam -D .

Aby uniknąć konieczności wpisywania szczegółów za każdym razem, gdy dodawałem je do ~/.ssh/config:

$ awk '/Host socks-proxy/' RS= ~/.ssh/config
Host socks-proxy
  Hostname pcit
  BatchMode yes
  RequestTTY no
  Compression yes
  DynamicForward localhost:9118

Następnie utworzyłem plik definicji jednostki serwisowej :

$ cat ~/.config/systemd/user/SocksProxy.service 
[Unit]
Description=SocksProxy Over Bridge Host

[Service]
ExecStart=/usr/bin/ssh -Nk socks-proxy

[Install]
WantedBy=default.target

Pozwoliłem demonowi ponownie załadować nowe definicje usługi, włączyłem nową usługę, uruchomiłem ją, sprawdziłem jej status i zweryfikowałem, że nasłuchuje:

$ systemctl --user daemon-reload
$ systemctl --user list-unit-files | grep SocksP
SocksProxy.service   disabled

$ systemctl --user enable SocksProxy.service
Created symlink from ~/.config/systemd/user/default.target.wants/SocksProxy.service to ~/.config/systemd/user/SocksProxy.service.

$ systemctl --user start SocksProxy.service 
$ systemctl --user status SocksProxy.service 
● SocksProxy.service - SocksProxy Over Bridge Host
   Loaded: loaded (/home/alex/.config/systemd/user/SocksProxy.service; enabled)
   Active: active (running) since Thu 2017-08-03 10:45:29 CEST; 2s ago
 Main PID: 26490 (ssh)
   CGroup: /user.slice/user-1000.slice/user@1000.service/SocksProxy.service
           └─26490 /usr/bin/ssh -Nk socks-proxy

$ netstat -tnlp | grep 118
tcp     0    0 127.0.0.1:9118        0.0.0.0:*             LISTEN     
tcp6    0    0 ::1:9118              :::*                  LISTEN

Działa to zgodnie z przeznaczeniem. Następnie chciałem uniknąć konieczności ręcznego uruchamiania usługi lub ciągłego uruchamiania jej z , używając do (ponownego) odradzania na żądanie. To nie działało, myślę, że (moja wersja) sshnie może odbierać deskryptorów plików gniazd.

Znalazłem dokumentację ( 1 , 2 ) i przykład użycia systemd-socket-proxyd-tool do utworzenia 2 usług „otoki”, „usługi” i „gniazda”:

$ cat ~/.config/systemd/user/SocksProxyHelper.socket 
[Unit]
Description=On Demand Socks proxy into Work

[Socket]
ListenStream=8118
#BindToDevice=lo
#Accept=yes

[Install]
WantedBy=sockets.target

$ cat ~/.config/systemd/user/SocksProxyHelper.service 
[Unit]
Description=On demand Work Socks tunnel
After=network.target SocksProxyHelper.socket
Requires=SocksProxyHelper.socket SocksProxy.service
After=SocksProxy.service

[Service]
#Type=simple
#Accept=false
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:9118
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

$ systemctl --user daemon-reload

To wydaje się działać, dopóki nie sshumrze lub nie zostanie zabity. Wtedy nie odrodzi się przy kolejnej próbie połączenia, kiedy powinna.

Pytania:

  1. Czy / usr / bin / ssh naprawdę nie akceptuje gniazd przekazywanych przez system? Czy tylko nowsze wersje? Mój jest tym z wersji Debian 8.9 .
  2. Czy tylko jednostki root mogą korzystać z tej BindTodeviceopcji?
  3. Dlaczego moja usługa proxy nie odradza się poprawnie przy pierwszym nowym połączeniu po śmierci starego tunelu?
  4. Czy to właściwy sposób na skonfigurowanie „proxy proxy socks na żądanie”? Jeśli nie, jak to robisz?

autosshpowinien zająć się ponownym połączeniem w przypadku awarii połączenia (choć nie jest to sposób systemowy).
Jakuje

@Jakuje: Dziękuję za komentarz, ale nie chcę, aby połączenie było trwałe. Chcę, aby został odrodzony, gdy go używam, a następnie (najlepiej po upływie limitu czasu braku danych wysłanych w ciągu x minut) sam się zakończy. Użyłem również mojego poprzedniego rozwiązania autossh.
Alex Stragies

Odpowiedzi:


4
  • Czy / usr / bin / ssh naprawdę nie akceptuje gniazd przekazywanych przez system?

Myślę, że nie jest to zbyt zaskakujące, biorąc pod uwagę:

  • OpenSSH to projekt OpenBSD
  • systemd obsługuje tylko jądro Linuksa
  • obsługa systemowa musiałaby zostać wyraźnie dodana do OpenSSH, jako opcjonalna zależność / czas kompilacji, więc prawdopodobnie byłaby to trudna sprzedaż.

  • Czy tylko jednostki root mogą korzystać z tej BindTodeviceopcji?

Wystąpienia systemowe użytkownika są na ogół dość odizolowane i np. Nie mogą komunikować się z głównym wystąpieniem pid-0. Rzeczy takie jak zależność od jednostek systemowych z plików jednostek użytkownika nie są możliwe.

Dokumentacja dla BindToDevicewzmianek:

Zauważ, że ustawienie tego parametru może spowodować dodanie dodatkowych zależności do jednostki (patrz wyżej).

Z powodu wyżej wspomnianego ograniczenia możemy sugerować, że opcja nie działa z wystąpień systemowych użytkownika.


  • Dlaczego moja usługa proxy nie odradza się poprawnie przy pierwszym nowym połączeniu po śmierci starego tunelu?

Jak rozumiem, łańcuch wydarzeń jest następujący:

  • SocksProxyHelper.socket jest rozpoczęty.
  • Klient SOCKS łączy się z hostem lokalnym: 8118.
  • uruchamia się systemd SocksProxyHelper.service.
  • Jako zależność SocksProxyHelper.serviceuruchamia się także systemd SocksProxy.service.
  • systemd-socket-proxydakceptuje gniazdo systemowe i przesyła dane do ssh.
  • ssh umiera lub zostaje zabity.
  • systemd zauważa i wprowadza SocksProxy.servicew stan nieaktywny, ale nic nie robi.
  • SocksProxyHelper.servicenadal działa i akceptuje połączenia, ale nie nawiązuje połączenia ssh, ponieważ nie jest już uruchomiony.

Poprawka polega na dodaniu BindsTo=SocksProxy.servicedo SocksProxyHelper.service. Cytując swoją dokumentację (wyróżnienie dodane):

Konfiguruje zależności wymagań, bardzo podobne do stylu Requires=. Jednak ten typ zależności jest silniejszy: oprócz efektu Requires=deklaruje, że jeśli jednostka powiązana jest zatrzymana, jednostka ta również zostanie zatrzymana . Oznacza to, że jednostka powiązana z inną jednostką, która nagle przejdzie w stan nieaktywny, również zostanie zatrzymana. Jednostki mogą nagle, nieoczekiwanie przejść w stan nieaktywny z różnych powodów: główny proces jednostki usługowej może zakończyć się według własnego wyboru , urządzenie wspierające jednostki urządzenia może zostać odłączone lub punkt montażu jednostki montażu może zostać odmontowany bez udziału kierownik systemu i serwisu.

W połączeniu z After=tym samym urządzeniem zachowanie BindsTo=jest jeszcze silniejsze. W takim przypadku jednostka ściśle związana musi być w stanie aktywnym, aby ta jednostka mogła być również w stanie aktywnym . Oznacza to nie tylko zespół związany z inną jednostką, która nagle przechodzi w stan nieaktywny, ale także taki, który jest związany z inną jednostką, która dostaje pomijane ze względu na czeku nie powiodło się stan (takich jak ConditionPathExists=, ConditionPathIsSymbolicLink=... - patrz poniżej) zostanie zatrzymany, powinien on biegać. Stąd w wielu przypadkach jest to najlepiej połączyć BindsTo=z After=.


  • Czy to właściwy sposób na skonfigurowanie „proxy proxy socks na żądanie”? Jeśli nie, jak to robisz?

Prawdopodobnie nie ma „właściwej drogi”. Ta metoda ma swoje zalety (wszystkie są „na żądanie”) i wady (zależność od systemd, pierwsze połączenie nie przechodzi, ponieważ ssh jeszcze nie zaczął nasłuchiwać). Być może lepszym rozwiązaniem byłoby wdrożenie obsługi aktywacji gniazd systemowych w autossh.


Dodałem BindsTo=SocksProxy.servicedo sekcji Unit pliku ~/.config/systemd/user/SocksProxyHelper.service, po After=SocksProxy.servicewierszu. Ręczne ponowne uruchomienie usługi SocksProxy nie jest już wymagane, gdy SSH umrze / zostanie zabity. Czy istnieje sposób, aby systemd „wstrzymał” połączenie początkowe, aby nie otrzymał resetowania TCP?
Alex Stragies,

@Vladimir Panteleev jeden punkt Chciałbym wyjaśnić: wsparcie dla aktywacji systemowego gniazda można wdrożyć stosunkowo łatwo przez parsowanie $LISTEN_FDSbez dodawania zależności sd_listen_fds(), więc może to być trudna sprzedaż, ale niezbyt trudna.
Amir
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.