Para llegar a una red aislada, uso un proxy ssh -D
socks .
Para evitar tener que escribir los detalles cada vez que los agregué a ~/.ssh/config
:
$ awk '/Host socks-proxy/' RS= ~/.ssh/config
Host socks-proxy
Hostname pcit
BatchMode yes
RequestTTY no
Compression yes
DynamicForward localhost:9118
Luego creé un archivo de definición de unidad de servicio systemd-user :
$ cat ~/.config/systemd/user/SocksProxy.service
[Unit]
Description=SocksProxy Over Bridge Host
[Service]
ExecStart=/usr/bin/ssh -Nk socks-proxy
[Install]
WantedBy=default.target
Dejé que el demonio volviera a cargar las nuevas definiciones de servicio, habilité el nuevo servicio, lo inicié, verifiqué su estado y verifiqué que está escuchando:
$ 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/[email protected]/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
Esto funciona según lo previsto. Luego, quería evitar tener que iniciar manualmente el servicio, o ejecutarlo permanentemente con autossh , mediante la activación del socket systemd para el (rea) desove bajo demanda. Eso no funcionó, creo que (mi versión de) no puede recibir descriptores de archivos de socket.ssh
Encontré la documentación ( 1 , 2 ) y un ejemplo para usar la systemd-socket-proxyd
herramienta -tool para crear 2 servicios "wrapper", un "servicio" y 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
Esto parece funcionar, hasta que ssh
muere o muere. Entonces no volverá a aparecer en el siguiente intento de conexión cuando debería.
Preguntas:
- ¿Puede / usr / bin / ssh realmente no aceptar sockets pasados por systemd? ¿O solo versiones más nuevas? El mío es el de up2date Debian 8.9 .
- ¿Solo las unidades de raíz pueden usar la
BindTodevice
opción? - ¿Por qué mi servicio proxy no se reaparece correctamente en la primera conexión nueva después de que el túnel viejo muere?
- ¿Es esta la forma correcta de configurar un "proxy de calcetines ssh a pedido"? Si no, ¿cómo lo haces?
autossh
debe ocuparse de reconectarse en caso de que falle la conexión (aunque no es el sistema).autossh
.Respuestas:
Creo que eso no es demasiado sorprendente, teniendo en cuenta:
Las instancias de systemd de usuario generalmente están bastante aisladas y, por ejemplo, no pueden comunicarse con la instancia principal de pid-0. Cosas como depender de las unidades del sistema de los archivos de la unidad del usuario no son posibles.
La documentación para las
BindToDevice
menciones:Debido a la restricción mencionada anteriormente, podemos implicar que la opción no funciona desde instancias systemd de usuario.
Según tengo entendido, la cadena de eventos es la siguiente:
SocksProxyHelper.socket
Está empezado.SocksProxyHelper.service
.SocksProxyHelper.service
, systemd también se iniciaSocksProxy.service
.systemd-socket-proxyd
acepta el socket systemd y reenvía sus datos assh
.ssh
muere o es asesinado.SocksProxy.service
en un estado inactivo, pero no hace nada.SocksProxyHelper.service
sigue ejecutándose y aceptando conexiones, pero no puede conectarsessh
, ya que ya no se está ejecutando.La solución es agregar
BindsTo=SocksProxy.service
aSocksProxyHelper.service
. Citando su documentación (énfasis agregado):Probablemente no haya una "forma correcta". Este método tiene sus ventajas (todo es "a pedido") y desventajas (dependencia de systemd, la primera conexión no funciona porque ssh aún no ha comenzado a escuchar). Quizás la implementación de soporte de activación de socket systemd en autossh sería una mejor solución.
fuente
BindsTo=SocksProxy.service
a la sección Unidad del archivo~/.config/systemd/user/SocksProxyHelper.service
, después de laAfter=SocksProxy.service
línea. Ahora ya no es necesario reiniciar manualmente el servicio SocksProxy, cuando SSH muere / se mata. ¿Hay alguna forma para que systemd "retenga" la conexión inicial, para que no se restablezca TCP?$LISTEN_FDS
sin agregar una dependenciasd_listen_fds()
, por lo que aún puede ser difícil de vender, pero no demasiado difícil.