Aqui está uma solução usando o OpenSSH > = 6.7 + socat :
-
OpenSSH > = 6.7 pode usar o encaminhamento de soquete de domínio Unix
Isso significa que o ponto de extremidade do túnel reverso será um soquete de escuta do UNIX em vez de um socket de escuta TCP tradicional. Você pode então gerenciar mais facilmente a flotilha de RPIs com um esquema de nomeação fácil: o nome do soquete será o nome escolhido (e fixo) do RPI, como
OfficeDevice1991
. Pode até ser uma propriedade única do RPI, desde que seja um nome de arquivo válido (desde que os nomes de soquete unix estejam de acordo com as convenções de nome de arquivo). Por exemplo, seu hostname, o endereço MAC de sua placa ethernet ou wifi ...O SSH pode lidar com soquetes unix para túneis, não para se conectar. Ele precisará da ajuda de um
ProxyCommand
para poder funcionar como cliente unix-socket. O socat pode lidar com muitos tipos de conexões, incluindo soquetes unix.UPDATE:
Há também um problema específico a ser tratado: o arquivo de soquete unix não é excluído na saída limpa, nem seria excluído de qualquer maneira, por exemplo, após uma falha. Isso requer a opçãoStreamLocalBindUnlink=yes
. Eu não achei inicialmente que, como o nome talvez sugere, esta opção deve ser definida no nó que cria o soquete unix. Então, no final, é definido no cliente com um encaminhamento local (-L
) ou outro no servidor (emsshd_config
) com um encaminhamento remoto (-R
). OP encontrou lá . Esta solução usa um encaminhamento remoto.Configuração no VPS:
mkdir /rpi-access
(como root) edite o arquivo
sshd_config
(/etc/ssh/sshd_config
). Requer essa opção adicional:StreamLocalBindUnlink yes
Dependendo das opções padrão, também pode exigir
AllowStreamLocalForwarding yes
UPDATE2:
Também defina emsshd_config
os parâmetrosClientAliveInterval
eClientAliveCountMax
, permitindo assim detectar uma desconexão em um tempo razoável, por exemplo:ClientAliveInterval 300 ClientAliveCountMax 2
Conexões ssh obsoletas devem então ser detectadas mais cedo no VPS (~ 10mn com o exemplo), e o processo sshd correspondente irá sair.
Uso no RPI:
ssh -fN -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile useraccount@ip
Em um arquivo de configuração, isso seria semelhante a isto:
Host ip User useraccount RemoteForward /rpi-access/OfficeDevice1991:localhost:22 IdentityFile /privatekeyfile
Repetindo novamente: a opção
StreamLocalBindUnlink yes
definida emsshd
no lado do VPS é importante: o soquete recém-criado não é removido, mesmo após a saída normal. Essa opção garante que o soquete seja removido se existir antes de ser usado, permitindo, dessa forma, ser reutilizado para reconexões adicionais. Isso também significa que não se pode considerar a mera presença do socket como significando que o RPI está conectado (mas veja depois).Agora isso permite fazer no VPS:
ssh -o 'ProxyCommand=socat UNIX:/rpi-access/%h -' rpiuseraccount@OfficeDevice1991
Como arquivo de configuração, considerando, por exemplo, os RPIs têm um nome que começa com OfficeDevice :
Host OfficeDevice* User rpiuseraccount ProxyCommand socat UNIX:/rpi-access/%h -
-
Para manter o link, basta usar um loop
O RPI pode executar um loop reconectando o ssh ao VPS sempre que as conexões terminarem. Para isso, não é necessário usar o modo de segundo plano (sem
-f
). Um mecanismo keepalive também deve ser usado. TCPKeepAlive (nível de sistema) ou ServerAliveInterval (nível de aplicativo) estão disponíveis. Eu acho que o TCPKeepAlive é útil apenas no servidor (o lado que recebe a conexão), então vamos usar o ServerAliveInterval.Seu valor (assim como ServerAliveCountMax) provavelmente deve ser adaptado dependendo de vários critérios: um firewall perdendo conexões inativas após um certo tempo, o atraso de recuperação desejado, não gerando tráfego inútil, ... digamos 300s aqui.
OfficeDevice1991 RPI:
#!/bin/sh while : ; do ssh -N -o ConnectTimeout=30 -o ServerAliveInterval=300 -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile useraccount@ip sleep 5 # avoid flood/DDoS in case of really unexpected issues done
Mesmo que o lado remoto ainda não tenha detectado a falha de conectividade anterior e, por mais algum tempo, a conexão ssh antiga ainda esteja em execução,
StreamLocalBindUnlink yes
atualizará vigorosamente o soquete unix para a nova conexão. -
já foi manipulado por 1.
Não há
customcommandsearch
necessário. Com as configurações corretas definidas em 1. basta usarssh OfficeDevice1991
para se conectar ao OfficeDevice1991.Se necessário no VPS, como
root
user only, este comando:fuser /rpi-access/*
pode mostrar quais RPIs estão atualmente conectados (é claro, exceto aqueles que recentemente perderam a conexão antes da detecção). Ele não mostrará os arquivos obsoletos do soquete unix porque não há nenhum processo vinculado a eles.