O seu dispositivo está atrás do NAT de uma operadora, consegue abrir ligações de saída e corre um servidor SSH que ninguém alcança. O pedido que chega costuma ser formulado como "dê-lhe uma VPN", que é uma resposta entre várias. Antes de o aceitar, decida se precisa de uma única porta TCP administrativa ou de um caminho roteado para uma sub-rede inteira, porque são projetos diferentes com exposição diferente.

Um túnel reverso responde bem à versão estreita. O dispositivo liga ao seu hub, pede ao hub para escutar numa porta loopback e reencaminha essa porta para o seu próprio serviço SSH. Depois, os administradores chegam ao listener através do hub, não através da internet pública.

Três condições que decidem a escolha

Anote-as antes de qualquer configuração. São a fronteira entre uma entrada de gestão limitada e uma extensão de rede, e misturá-las é como um túnel de cinco linhas se torna uma rede plana sem dono.

ConditionReverse tunnel fitsSomething else is needed
How many services must be reachable?One, or a small fixed set on loopbackAnything that needs many ports or dynamic discovery
Who connects, and how are they authenticated?Named administrators with their own hub accountsThird parties, or anything needing per-flow audit you do not control
Does the device's own LAN need to be reachable?NoYes, so a routed VPN or a managed platform is the honest answer

A terceira linha é a que as pessoas discutem. Um túnel para a porta SSH de um dispositivo não põe os seus vizinhos na sua rede, e não deve parecer que o faz através de uma cadeia de reencaminhamentos adicionais. Se o requisito é mesmo a LAN, diga-o e conceba essa em vez disso.

Lado do hub: uma conta de repetidor limitada

Dê a cada dispositivo a sua própria conta de repetidor com autenticação por chave pública e sem sessão interativa. Match bloco limitado a essa conta mantém a permissão pequena, e a chave privada fica no dispositivo onde pertence.

Match User relay-dev-7
    AuthenticationMethods publickey
    PubkeyAuthentication yes
    AllowTcpForwarding remote
    PermitListen 127.0.0.1:21022
    GatewayPorts no
    MaxSessions 0
    PermitTTY no
    X11Forwarding no
    AllowAgentForwarding no

MaxSessions 0 é a linha interessante. Nega sessões de shell e de subsistemas enquanto continua a permitir o reencaminhamento de que o dispositivo precisa, por isso uma chave roubada não pode ser transformada num início de sessão interativo. PermitListen fixa o endereço e a porta do listener do lado do hub, e GatewayPorts no mantém-no em loopback em vez de o abrir à rede onde o hub está.

Teste a configuração efetiva antes de recarregar, e mantenha uma segunda sessão aberta enquanto o faz. Match bloco que se aplica acidentalmente a todos, ou um erro de escrita no nome de uma opção, é a forma clássica de se trancar fora da máquina que está a endurecer. Despeje a configuração em execução e releia as opções em vez de confiar no ficheiro que acabou de escrever. Note que o suporte de opções difere entre compilações, pelo que uma linha aceite num servidor mais recente pode ser simplesmente ignorada por um mais antigo.

Lado do dispositivo: reencaminhamento que falha ruidosamente

O dispositivo abre a ligação e pede o listener. Os dois endereços no argumento -R significam coisas diferentes, e lê-los da esquerda para a direita é a forma mais rápida de memorizar qual é qual.

ssh -NT \
    -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=30 \
    -o ServerAliveCountMax=3 \
    -R 127.0.0.1:21022:127.0.0.1:22 \
    [email protected]

O par esquerdo é onde o hub deve escutar. O par direito é aquilo a que o dispositivo se liga quando chega um pedido, resolvido do próprio lado do dispositivo. Trocá-los produz um túnel que sobe limpo e reencaminha para o local errado, o que é pior do que uma falha.

ExitOnForwardFailure=yes faz o comando sair quando o listener pedido não pode ser estabelecido, por isso um ciclo de reinício diz-lhe a verdade em vez de deixar uma sessão a meio funcionar. Não diz nada sobre se o serviço SSH local está saudável mais tarde, por isso combine-o com um gestor de processos e um teste de ligação real ocasional.

Nunca substitua o endereço de escuta loopback por um curinga para evitar um salto extra. Essa única alteração é a diferença entre um caminho de gestão e uma porta acessível publicamente, e normalmente acontece durante a depuração e depois fica. Se um colega não chega à porta através do hub, corrija a configuração do salto em vez de alargar o bind. O loopback é todo o argumento de segurança deste desenho.

Acesso de administrador através do hub

Um administrador com uma conta normal no hub pode saltar através dele até à porta reencaminhada. A conta de repetidor não é usada para isto, e é justamente esse o ponto de as manter separadas.

ssh -J [email protected] -o HostKeyAlias=device-7 \
    -p 21022 [email protected]

Verifique a chave de anfitrião do dispositivo sob o alias que escolheu, porque essa chave identifica o dispositivo no fim da cadeia e o túnel é apenas transporte. O início de sessão de ponta a ponta continua a autenticar ambas as pontas; um túnel que termina num hub partilhado não o torna por si só um caminho de confiança.

Assuma o ciclo de vida

Execute o comando do dispositivo sob um gestor de processos com exatamente uma instância ativa e uma política de reinício que tenha escolhido deliberadamente. As opções de keepalive detetam um par morto; não ressuscitam um processo que saiu.

Depois escreva o procedimento de desativação. Cada dispositivo tem o seu próprio listener e a sua própria chave, por isso desativar significa revogar essa conta e remover essa chave, não rodar um segredo partilhado por toda a frota.

Por fim, lembre-se do que o loopback lhe dá. Limita a exposição de rede e não faz nada quanto a outros utilizadores locais num hub partilhado, por isso a política de acesso do próprio hub tem de continuar correta. Referência de sshd_config documenta cada uma das opções usadas acima, e vale a pena ler as secções de reencaminhamento por completo antes de alargar qualquer uma delas.

Artigos relacionados