Eu tenho vários raspberry pi executando o Arch Linux (sem GUI) nos quais preciso acessar. Esses pis estão atrás de firewalls em cada local exclusivo. Atualmente eu uso o openvpn para me conectar a eles, mas os custos desse sistema são caros por licença. Eu uso o servidor de acesso deles.
Como resultado, estou tentando projetar e configurar um sistema que me permita fazer login no meu servidor VPN (vps) e executar um comando para procurar um nome específico (OfficeDevice1991), como: customcommandsearch "OfficeDevice1991"
e, em seguida, retorna o IP endereço da máquina ou algo que eu possa usar para fazer SSH. Também estou procurando a capacidade de executar um comando para listar todos os dispositivos conectados ativos. Ele lista o IP, o nome e talvez há quanto tempo está ativo.
Para esse objetivo, é claro que preciso criar algo que inclua o nome do dispositivo (neste caso, OfficeDevice1991) e, em seguida, esse pi poderá se conectar ao meu servidor público vps. No servidor público, posso fazer login e pesquisar todos os dispositivos conectados a ele e retornar as informações necessárias para o ssh.
Tenho procurado o SSH reverso e, até agora, consegui conectar um dos meus pi de teste e acessá-lo a partir do meu vps usando os seguintes comandos:
IP:
ssh -fN -R 12345:localhost:22 -i /publickeyfile useraccount@ip //Pi's command to connect to vpn
VPS:
ssh -p 12345 useraccount@localhost //command for vpn to connect to pi
Isso funciona muito bem, mas usando esse método, se eu fosse implementá-lo, teria alguns problemas:
- Eu precisaria configurar portas únicas não utilizadas
- Alguma maneira de manter essas portas / túneis abertos
- Preciso criar um sistema para identificar cada dispositivo. Posso registrar cada porta em um nome como um arquivo de texto localmente? Seria benéfico poder incluir isso na configuração do ssh para cada dispositivo, se possível. Eu ainda precisaria ter certeza de que as portas que uso não estão sendo usadas por nenhum outro programa ou dispositivo já existente.
O que eu não quero ter que fazer
Verifique quais portas estão livres para usar para cada RPI
Tem que editar manualmente
.ssh/config
para adicionar um nome para representar cada porta atribuída ao RPI da parte 1 acima.
Estou escrevendo isso para obter informações / assistência sobre o que fazer para atingir meu objetivo.
Alguém poderia me fornecer uma solução adequada?
Aqui está uma solução usando OpenSSH >= 6.7 + socat :
OpenSSH >= 6.7 pode usar encaminhamento de soquete de domínio Unix
Isso significa que o ponto final do túnel reverso será um soquete de escuta UNIX em vez de um soquete de escuta TCP tradicional. Você pode então gerenciar mais facilmente a flotilha de RPIs com um esquema de nomenclatura fácil: o nome do soquete será o nome escolhido (e fixo) do RPI, como
OfficeDevice1991
. Pode até ser uma propriedade exclusiva do RPI, desde que seja um nome de arquivo válido (já que os nomes de soquete unix aderem às convenções de nome de arquivo). Por exemplo, seu nome de host, o endereço MAC de sua placa ethernet ou wi-fi ...O SSH pode lidar com soquetes unix para túneis, não para se conectar. Necessitará da ajuda de um
ProxyCommand
para poder funcionar como cliente unix-socket. socat pode lidar com muitos tipos de conexões, incluindo soquetes unix.ATUALIZAÇÃO:
Há também um problema específico a ser resolvido: o arquivo de soquete unix não é excluído na saída limpa, nem teria sido excluído de qualquer maneira, por exemplo, após uma falha. Isso requer a opção
StreamLocalBindUnlink=yes
. Não achei inicialmente que, como o nome talvez implique, essa 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 então no servidor (emsshd_config
) com um encaminhamento remoto (-R
). OP encontrou lá . Esta solução usa um encaminhamento remoto.Configuração no VPS:
(como root) edite o
sshd_config
arquivo (/etc/ssh/sshd_config
). Requer esta opção adicional:Dependendo das opções padrão, também pode exigir
AllowStreamLocalForwarding yes
UPDATE2:
Também definido nos
sshd_config
parâmetrosClientAliveInterval
eClientAliveCountMax
, permitindo detectar uma desconexão em um tempo razoável, por exemplo:As conexões ssh obsoletas devem ser detectadas anteriormente no VPS (~ 10mn com o exemplo) e o processo sshd correspondente será encerrado.
Uso no RPI:
Em um arquivo de configuração, isso seria semelhante a isto:
Repetindo novamente: a opção
StreamLocalBindUnlink yes
ligadasshd
no lado VPS é importante: o soquete recém-criado não é removido, mesmo na saída normal. Esta opção garante que o soquete seja removido se existir antes do uso, permitindo assim que seja reutilizado para novas religações. Isso também significa que não se pode considerar a mera presença do soquete como significando que o RPI está conectado (mas veja mais adiante).Agora isso permite fazer no VPS:
Como um arquivo de configuração, considerando, por exemplo, que os RPIs tenham um nome começando com OfficeDevice :
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 deve utilizar o modo background (não
-f
). Um mecanismo de manutenção de atividade também deve ser usado. TCPKeepAlive (nível do sistema) ou ServerAliveInterval (nível do 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 derrubando 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:
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á de qualquer maneira o soquete unix para a nova conexão.já é tratado por 1.
Não há
customcommandsearch
necessidade. Com as configurações corretas definidas em 1. apenas usandossh OfficeDevice1991
irá se conectar ao OfficeDevice1991.Se necessário no VPS,
root
apenas como usuário, este comando:pode mostrar quais RPIs estão conectados no momento (claro, exceto aqueles que recentemente perderam a conexão antes da detecção). Ele não mostrará os arquivos de soquete unix obsoletos porque não há nenhum processo vinculado a eles.
Este é um par de abordagens diferentes sobre a situação. Omiti alguns detalhes aqui porque não há nada que o impeça de fazer uma pergunta adicional para obter detalhes se você tentar qualquer uma dessas rotas.
1. Substitua o servidor de acesso OpenVPN
Se o custo do OpenVPN Access Server for um problema proibitivo, considere implantar seu próprio servidor OpenVPN. O software é de uso gratuito; você só precisaria de um endpoint de servidor (um VPS ou equivalente, se não tiver nada localmente) e o conjunto de habilidades para configurá-lo. Muitos tutoriais estão disponíveis para isso, então você não precisa começar do zero.
Depois de configurar isso, você pode usar o DNS ou
/etc/hosts
definir nomes de host, como o seu,OfficeDevice1991
para apontar para o endereço de terminal VPN apropriado em seu servidor.2. Use
autossh
em vez de OpenVPNDepois de ter seu próprio endpoint, você pode usar algo como
autossh
em cada um dos sistemas Pissh
para um endpoint "conhecido" na inicialização (um VPS ou equivalente, se você não tiver nada localmente).Carregue um túnel reverso (
ssh -R
) em cada um, de modo que cada Pi apresente um número de porta diferente do seu servidor que mapeia de volta para sua própriassh
porta 22.O uso criterioso de entradas em
~/.ssh/config
pode permitir que você executessh OfficeDevice1991
e mapeie automaticamente para algo comossh -p 12345 localhost
, que por sua vez corresponderia a umassh
conexão normal com o Pi representando OfficeDevice1991.Respondendo ao seu conjunto de perguntas que você adicionou em sua edição,
who
oufinger
daria a você o tempo conectado de cada RPi.autossh
faze
for x ... do ... done
loop curto pode gerar automaticamente o arquivo para você. Eu também não gostaria de criar 1.000 entradas manualmente.