Acessando computadores remotos protegidos por NAT ou firewall com túnel SSH reverso direcionado por DNS dinâmico
Com esse artigo pretendo mostrar uma maneira prática de acessar computadores protegidos por uma firewall ou NAT. Isso é muito útil nos casos em que não é possível - ou não se tem o controle para - efetuar um direcionamento de portas para a máquina desejada. É apresentado ainda um script que, utilizando DNS dinâmico, permite estabelecer essa conexão de qualquer lugar.
Parte 3: Configuração do servidor
1. Como usuário root, crie o arquivo ssh-tunnel.sh em /usr/local/bin. Ele deverá conter o seguinte:
Repare que em COMMAND utilizei a porta 26 porque minhas máquinas cliente costumam estar com a porta 22 bloqueada pela operadora de banda larga. Adapte essa porta para aquela que você utiliza para acessar o SSH em sua máquina cliente. A opção "C" pode ser colocada para habilitar a compressão do ssh, útil caso o link de internet seja lento.
A chave -nNT diz para o ssh não aceitar entrada de stdin, não executar comandos remotos e não alocar um terminal. Fazemos isso porque queremos apenas estabelecer o túnel para permitir conexões pela outra ponta, e não estabelecer uma sessão interativa com a máquina cliente.
A chave -R informa ao cliente para mapear a porta especificada (argumento $1 do script) para a porta 22 do servidor, conforme já explicado na seção "teórica". Se seu servidor também estiver em um link com portas bloqueadas, pode ser preciso rodar o daemon do SSH em outra porta, caso em que será necessário alterar também essa porta. O hostname a ser utilizado na conexão corresponde ao informado no argumento $2 do script.
2. Crie um usuário responsável por estabelecer o túnel SSH reverso e gere para ele uma chave ssh *sem passphrase* (isso é muito importante para que a coisa funcione de forma automática):
# adduser tunnel
# su tunnel
$ ssh-keygen -t dsa
3. Ainda logado como usuário tunnel, crie uma "cron job" para o servidor tentar conexão ao cliente de 1 em 1 minuto:
crontab -e
Na tela que se abrirá no editor "vi" (suponho que você saiba como utilizá-lo), entre com a seguinte linha:
Note que a porta 9000 e o nome "hostname" devem ser substituídos pela porta escolhida por você e o hostname que você criou no serviço de DNS dinâmico.
Salve o arquivo (comando :wq) e reinicie o cron daemon:
# killall crond
# crond
#!/bin/sh
# Remove o arquivo known_hosts para que o SSH não pare informando
# que a identificação do host mudou (isso acontecerá se você apontar
# o hostname no DNS para uma máquina diferente)
if [ -f /home/tunnel/.ssh/known_hosts ]; then
rm /home/tunnel/.ssh/known_hosts
fi
# Comando responsável por estabelecer o túnel SSH reverso
COMMAND="ssh -Cp 26 -o StrictHostKeyChecking=no -nNT -R $1:localhost:22 tunnel@$2"
# Comando para verificar se o túnel já se encontra estabelecido
CHECK_TUNNEL=`ps ax | grep "$COMMAND" | grep -v grep`
# Verifica se o túnel está criado. Se não estiver, executa comando para criá-lo
if [ -z "$CHECK_TUNNEL" ] ; then
$COMMAND
fi
# Remove o arquivo known_hosts para que o SSH não pare informando
# que a identificação do host mudou (isso acontecerá se você apontar
# o hostname no DNS para uma máquina diferente)
if [ -f /home/tunnel/.ssh/known_hosts ]; then
rm /home/tunnel/.ssh/known_hosts
fi
# Comando responsável por estabelecer o túnel SSH reverso
COMMAND="ssh -Cp 26 -o StrictHostKeyChecking=no -nNT -R $1:localhost:22 tunnel@$2"
# Comando para verificar se o túnel já se encontra estabelecido
CHECK_TUNNEL=`ps ax | grep "$COMMAND" | grep -v grep`
# Verifica se o túnel está criado. Se não estiver, executa comando para criá-lo
if [ -z "$CHECK_TUNNEL" ] ; then
$COMMAND
fi
Repare que em COMMAND utilizei a porta 26 porque minhas máquinas cliente costumam estar com a porta 22 bloqueada pela operadora de banda larga. Adapte essa porta para aquela que você utiliza para acessar o SSH em sua máquina cliente. A opção "C" pode ser colocada para habilitar a compressão do ssh, útil caso o link de internet seja lento.
A chave -nNT diz para o ssh não aceitar entrada de stdin, não executar comandos remotos e não alocar um terminal. Fazemos isso porque queremos apenas estabelecer o túnel para permitir conexões pela outra ponta, e não estabelecer uma sessão interativa com a máquina cliente.
A chave -R informa ao cliente para mapear a porta especificada (argumento $1 do script) para a porta 22 do servidor, conforme já explicado na seção "teórica". Se seu servidor também estiver em um link com portas bloqueadas, pode ser preciso rodar o daemon do SSH em outra porta, caso em que será necessário alterar também essa porta. O hostname a ser utilizado na conexão corresponde ao informado no argumento $2 do script.
2. Crie um usuário responsável por estabelecer o túnel SSH reverso e gere para ele uma chave ssh *sem passphrase* (isso é muito importante para que a coisa funcione de forma automática):
# adduser tunnel
# su tunnel
$ ssh-keygen -t dsa
3. Ainda logado como usuário tunnel, crie uma "cron job" para o servidor tentar conexão ao cliente de 1 em 1 minuto:
crontab -e
Na tela que se abrirá no editor "vi" (suponho que você saiba como utilizá-lo), entre com a seguinte linha:
*/1 * * * * /usr/local/bin/ssh-tunnel.sh 9000 hostname
Note que a porta 9000 e o nome "hostname" devem ser substituídos pela porta escolhida por você e o hostname que você criou no serviço de DNS dinâmico.
Salve o arquivo (comando :wq) e reinicie o cron daemon:
# killall crond
# crond