Il proxy SSH Socks su richiesta tramite unità utente systemd con attivazione socket non si riavvia come desiderato


14

Per raggiungere una rete isolata io uso un -D .

Per evitare di dover digitare i dettagli ogni volta che li ho aggiunti a ~/.ssh/config:

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

Quindi ho creato un file di definizione dell'unità di servizio :

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

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

[Install]
WantedBy=default.target

Ho lasciato che il demone ricarichi le nuove definizioni di servizio, abiliti il ​​nuovo servizio, lo avvii, ne abbia verificato lo stato e verificato che stia ascoltando:

$ 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

Funziona come previsto. Quindi volevo evitare di dover avviare manualmente il servizio o eseguirlo in modo permanente con , utilizzando l' per la (ri) generazione su richiesta. Non ha funzionato, penso (la mia versione di) non può ricevere descrittori di file socket.ssh

Ho trovato la documentazione ( 1 , 2 ) e un esempio per l'uso di systemd-socket-proxyd-tool per creare 2 servizi "wrapper", un "servizio" e un "socket":

$ 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

Questo sembra funzionare fino a quando non sshmuore o viene ucciso. Quindi non si rigenererà al prossimo tentativo di connessione quando dovrebbe.

Domande:

  1. / Usr / bin / ssh non può davvero accettare socket passati dal sistema? O solo versioni più recenti? Il mio è quello di Debian 8.9 aggiornato .
  2. Solo le unità di root possono usare l' BindTodeviceopzione?
  3. Perché il mio servizio proxy non viene rigenerato correttamente alla prima nuova connessione dopo la morte del vecchio tunnel?
  4. È questo il modo giusto di impostare un "proxy di calze ssh su richiesta"? Se no, come lo fai?

autosshdovrebbe occuparsi di riconnettersi nel caso in cui la connessione fallisca (anche se non è il sistema).
Jakuje,

@Jakuje: Grazie per il commento, ma non voglio che la connessione sia permanente. Voglio che venga generato quando lo uso, e quindi (idealmente dopo un timeout di non invio dati x x minuti) si interrompe automaticamente. Inoltre, è stata utilizzata la mia soluzione precedente autossh.
Alex Stragies,

Risposte:


4
  • / Usr / bin / ssh non può davvero accettare socket passati dal sistema?

Penso che non sia troppo sorprendente, considerando:

  • OpenSSH è un progetto OpenBSD
  • systemd supporta solo il kernel Linux
  • il supporto di systemd dovrebbe essere esplicitamente aggiunto a OpenSSH, come dipendenza opzionale / tempo di costruzione, quindi sarebbe probabilmente una vendita difficile.

  • Solo le unità di root possono usare l' BindTodeviceopzione?

Le istanze di systemd dell'utente sono generalmente piuttosto isolate e, ad esempio, non possono comunicare con l'istanza principale pid-0. Cose come dipendere dalle unità di sistema dai file delle unità utente non sono possibili.

La documentazione per le BindToDevicemenzioni:

Si noti che l'impostazione di questo parametro potrebbe comportare l'aggiunta di ulteriori dipendenze all'unità (vedere sopra).

A causa della limitazione di cui sopra, possiamo implicare che l'opzione non funziona dalle istanze systemd dell'utente.


  • Perché il mio servizio proxy non viene rigenerato correttamente alla prima nuova connessione dopo la morte del vecchio tunnel?

A quanto ho capito, la catena di eventi è la seguente:

  • SocksProxyHelper.socket è iniziato.
  • Un client SOCKS si connette a localhost: 8118.
  • systemd si avvia SocksProxyHelper.service.
  • Come dipendenza di SocksProxyHelper.service, inizia anche systemd SocksProxy.service.
  • systemd-socket-proxydaccetta il socket systemd e inoltra i suoi dati a ssh.
  • ssh muore o viene ucciso.
  • systemd si accorge e si pone SocksProxy.servicein uno stato inattivo, ma non fa nulla.
  • SocksProxyHelper.servicecontinua a funzionare e ad accettare le connessioni, ma non riesce a connettersi ssh, poiché non è più in esecuzione.

La correzione è aggiungere BindsTo=SocksProxy.servicea SocksProxyHelper.service. Citando la sua documentazione (enfasi aggiunta):

Configura le dipendenze dei requisiti, molto simili nello stile a Requires=. Tuttavia, questo tipo di dipendenza è più forte: oltre all'effetto di Requires=esso dichiara che se l'unità vincolata viene fermata, anche questa unità verrà fermata . Ciò significa che anche un'unità vincolata a un'altra unità che entra improvvisamente in stato inattivo verrà arrestata. Le unità possono improvvisamente, inaspettatamente entrare in stato inattivo per diversi motivi: il processo principale di un'unità di servizio potrebbe terminare a sua scelta , il dispositivo di supporto di un'unità di dispositivo potrebbe essere scollegato o il punto di montaggio di un'unità di montaggio potrebbe essere smontato senza il coinvolgimento di il gestore del sistema e dei servizi.

Se usato insieme After=alla stessa unità, il comportamento di BindsTo=è ancora più forte. In questo caso, l'unità vincolata deve essere rigorosamente in stato attivo affinché anche questa unità sia in stato attivo . Questo non solo, un'unità vincolato ad un'altra unità che improvvisamente entra stato inattivo, ma anche uno che è destinato a un'altra unità che viene saltato a causa di una condizione di errore di controllo (ad esempio ConditionPathExists=, ConditionPathIsSymbolicLink=... - vedi sotto) viene interrotto, dovrebbe essere in esecuzione. Quindi, in molti casi è meglio combinare BindsTo=con After=.


  • È questo il modo giusto di impostare un "proxy di calze ssh su richiesta"? Se no, come lo fai?

Probabilmente non esiste un "modo giusto". Questo metodo ha i suoi vantaggi (tutto è "on-demand") e gli svantaggi (dipendenza da systemd, la prima connessione non riesce perché ssh non ha ancora iniziato ad ascoltare). Forse l'implementazione del supporto per l'attivazione del socket di systemd in autossh sarebbe una soluzione migliore.


Ho aggiunto BindsTo=SocksProxy.servicealla sezione Unità del file ~/.config/systemd/user/SocksProxyHelper.service, dopo la After=SocksProxy.serviceriga. Il riavvio manuale del servizio SocksProxy non è più necessario quando SSH muore / gets_killed. C'è un modo per systemd di "trattenere" la connessione iniziale, in modo che non ottenga un reset TCP?
Alex Stragies,

@Vladimir Panteleev un punto che vorrei chiarire: il supporto per l'attivazione di socket di systemd può essere implementato in modo relativamente semplice analizzando $LISTEN_FDSsenza aggiungere una dipendenza sd_listen_fds(), quindi potrebbe essere ancora una vendita difficile, ma non troppo difficile.
Amir,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.