Personal tools
You are here: Home Dicas e Tutoriais Como Fazer um túnel com SSH
Document Actions

Como Fazer um túnel com SSH

by Pablo Costa — last modified 13-06-2007 02:28 PM http://creativecommons.org/licenses/by/2.0/br/deed.pt

Imagine que você tenha um linux instalado numa intranet com ip não válido, por exemplo 192.168.1.10, e que nesta rede tenha um firewall rodando um NAT padrão.

Dai você deseja de fora pela internet acessar este seu linux que se encontra atrás do firewall. Mas você não tem nenhuma amizade com o administrador da rede para pedir um redirecionamento de portas, ou ele não permite pelas vias normais.

O que fazer??

Arregaçar as mangas e lançar mãos do interessante truque "SSH PORTFORWARD"

Com isto eu consigo fazer com que uma máquina interna faça um "forward" de qualquer porta para um maquina externa na internet de modo que eu possa capturar esta conexão mais tarde.

Primeiramente vou mostrar o modo mais básico de se fazer isto interativamente. Depois vou ensinar como automatizar pelo crontab.

Vou utilizar da seguinte nomenclatura::

        REMOTEHOST = IP da Maquina na internet que você tem uma conta e roda sshd
        REMOTEPORT = Porta tcp/ip na maquina remota que vai fazer o forward

        LOCALHOST = IP da Maquina na intranet que vai receber o portforward
        LOCALPORT = Porta tcp/ip da maquina da intranet que vai ser exportada
        user = usuário que você loga na maquina remota

Com o ssh instalado você deve executar o seguinte comando:

Exemplo de como fazer um forward local do telnet para um porta numa maquina remota::

        ssh -l user -R REMOTEPORT:LOCALHOST:LOCALPORT REMOTEHOST

Traduzindo em números para ficar mais fácil de visualizar::

        ssh -l user -R 2323:192.168.1.10:23 200.200.200.200

Vai ser pedida a senha do usuário "user" na máquina de ip 200.200.200.200 Você digita a senha e deixa parado no prompt.

De qualquer outra maquina da internet você pode fazer::

        telnet 200.200.200.200 2323

Que você cairá na maquina 192.168.1.10 da intranet. Muito legal !!!

Você não esta restrito a fazer forward somente de portas de sua maquina !! Pode especificar de qualquer uma da rede:

Exemplo::

        ssh -l user -R 2222:192.168.1.99:22 200.200.200.200

Dai resgataria a conexão assim::

        ssh -l user -p 2222 200.200.200.200

Você tem que às vezes remover o .ssh/know_hosts porque ele acumula chave de dois servidores de ssh diferentes e dá erro. Você pode remover somente a linha referente ao ip 200.200.200.200.

Mas este tipo de conexão é instável e portanto se você quer deixar isto um pouco mais estável deve fazer algum tipo de monitoramento da conexão e reiniciá-la quando necessário.

Eu sei que existem softwares para isto como vtun, rstunnel etc, mas tem que compilar e depender de outras bibliotecas...então elaborei uma solução simples que usa apenas ssh e bash :-)

Agora vou especificar a solução com mais detalhes.

Na máquina da intranet "LOCALHOST" vamos criar uma chave do ssh para ser possível logar sem senha no REMOTEHOST assim podemos colocar a conexão no crontab:

Tanto no LOCALHOST como no REMOTEHOST vou trabalhar com o usuário "user"

No LOCALHOST execute este comando::

        ssh-keygen -t dsa

E dê enter sem colocar senha:

        [root@192.168.1.10 root]# ssh-keygen -t dsa
        Generating public/private dsa key pair.
        Enter file in which to save the key (/root/.ssh/id_dsa):
        Enter passphrase (empty for no passphrase):
        Enter same passphrase again:
        Your identification has been saved in /root/.ssh/id_dsa.
        Your public key has been saved in /root/.ssh/id_dsa.pub.

Depois copie o arquivo /root/.ssh/id_dsa.pub no REMOMEHOST em /home/user/.ssh/authorized_keys

O sshd_config que costuma ficar em /etc/ssh/sshd_config do REMOTEHOST precisa ter estas configuracoes abaixo par permitir o portforward::

        RSAAuthentication yes
        PubkeyAuthentication yes
        AuthorizedKeysFile .ssh/authorized_keys
        GatewayPorts yes
        AllowTcpForwarding yes
        --

Uma vez feito isto você deve conseguir logar em REMOTEHOST sem senha através do comando: ssh -l user REMOTEHOST

Ultrapassado o passo acima podemos retirar a shell do user no REMOTEHOST. Edite o /etc/passwd:

        user:*:1000:1000::0:0:User &:/home/user:/sbin/nologin

Já que para fazer o forward não precisa ter uma shell.

Com isto tudo preparado o comando para se conectar no REMOTEHOST fica assim::

        ssh -l user -n -f -R REMOTEPORT:LOCALHOST:LOCALPORT -N REMOTEHOST

Explicando::

        -l : seleciona o usuário que vai logar
        -f : manda o ssh ir para background depois da execução
        -n : desvia o stdin para /dev/null ou seja não aparece nada na terra, nem motd
        -R : Faz o forward
        -N : Não execute nenhum comando no REMOTEHOST (Por isto que podemos por a shell como nologin)

Com tudo isto montado eu fiz alguns scripts simples para rodar no crontab e garantir a conexão::

        */1 * * * * /root/bin/online.sh 200.200.200.200
        0 */1 * * * /root/bin/uptime.sh 200.200.200.200
        5 */1 * * * /root/bin/rmlock.sh 200.200.200.200

Estes scripts rodam em linux, não testei com freebsd, mas deve dar diferença porque o netstat é diferente.

O online.sh roda de 1 em 1 minuto para verificar se a conexão esta ativa, se não estiver ele reinicia a conexão.

Ele usa como parametro um arquivo para você dizer quais os forward que você quer fazer

  • arquivo deve ter o seguinte nome: REMOTEHOST.ssh

Exemplo:

  1. 200.200.200.ssh:
            #LOCALHOST:LOCALPORT:REMOTEHOST:REMOTEPORT
            127.0.0.1:22:200.200.200.200:2222
            127.0.0.1:23:200.200.200.200:2323
            192.168.1.180:23:200.200.200.200:2301
    

O uptime.sh só para garantir de hora em hora mata todas as conexões e as restabelece.

  • rmlock.sh remove o lock que o uptime.sh faz para impedir de encavalar online.sh com uptime.sh

Eu sei que está confuso, mas se alguém um dia for precisar vai entender :-))

Aqui estão os scripts:

online.sh::

        #!/bin/bash
        PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/root/bin

        SERVER="$1"
        FWFILE=/root/bin/$SERVER.ssh

        export LANG=en

        if [ -f /tmp/$SERVER ]
        then
                echo -e "Lock"
                exit
        fi

        if netstat -nt tcp | grep "$SERVER:22" | grep -qi ESTABLISHED;
        then
                true
        else

                #killall -9 ssh
                grep -v \# $FWFILE|\
                while IFS=: read LOCALHOST LOCALPORT REMOTEHOST REMOTEPORT
                do
                        ssh -n -f -l user -R $REMOTEPORT:$LOCALHOST:$LOCALPORT -N $REMOTEHOST
                done
                date | mail -s forward_update user@dominio.com.br
        fi

uptime.sh:

        #!/bin/bash

        PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/root/bin

        SERVER="$1"
        FWFILE=/root/bin/$SERVER.ssh

        export LANG=en

        touch /tmp/$SERVER

        netstat -ntp tcp | grep $SERVER |\
        while read line ; do
                set $line
                proc=`echo $7 | cut -d/ -f1`
                kill -9 $proc

        done

        grep -v \# $FWFILE|\
        while IFS=: read LOCALHOST LOCALPORT REMOTEHOST REMOTEPORT
        do
                ssh -n -f -l user -R $REMOTEPORT:$LOCALHOST:$LOCALPORT -N $REMOTEHOST
        done
        date | mail -s forward_update user@dominio.com.br

        rm -f /tmp/$SERVER

rmlock.sh:

        #!/bin/bash

        SERVER=$1
        rm -f /tmp/$SERVER

E finalmente o ps.sh que server para ver os pid das conexões abertas: usa-se ps.sh 200.200.200.200

ps.sh:

        #!/bin/bash

        export LANG=en

        SERVER=$1
        netstat -ntp tcp | grep $SERVER |\
        while read line ; do
                set $line
                proc=`echo $7 | cut -d/ -f1`
                ps $proc
        done


Esse tutorial lhe foi útil? Economizou tempo ou dinheiro? Que tal colaborar com o Cybershark? Qualquer dólar ajuda :) MUITO OBRIGADO!

Parabens

Posted by Anonymous User at 12-01-2005 09:34 PM

gostei muito do vosso script, estava precisando disso... estou usando samba por tunel ssh via internet, isso ira me ajudar muito.

PARABENS PELO ARTIGO e SCRIPTS, OBRIGADO Huandel

D++++

Posted by Anonymous User at 22-06-2005 04:07 PM

Simplesmente fantástico

Cadastro de usuarios

Posted by Anonymous User at 03-02-2005 09:18 AM

Gostaria de cadastra usuario no linux via windows, fazer um script que quando colocar passwd e senha no mesmo tempo sem precisar apertar a tecla enter. Se alguem poder me ajudar eu agradeço. Obrigado

Ajuda

Posted by Anonymous User at 13-07-2006 10:39 AM

Alguem conhece um servidor sshd na internet gratuito e com suporte a PORTFORWARD? Revirei tudo no Google e nao achei nada. Socorro!

sshd gratuito

Posted by Anonymous User at 25-04-2007 02:53 PM

Um servidor sshd gratuito e com suporte a PORTFORWARD é o OpenSSH. :-)

Anúncios
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: