segunda-feira, 16 de julho de 2012

SSH - Dicas, truques e um tutorial sobre o protocolo

SSH é uma ferramenta muito importante e usada, qualquer um que trabalhe envolvido com internet e redes precisa saber muito bem como usá-la. Para quem não o conhece, ele é muito similar ao telnet. Com a diferença de que é muito mais seguro, aliás, apresenta segurança, o telnet é completamente inseguro, além de fornecer diversas outras funcionalidades que o telnet não possui.

Por isso, vamos disponibilizar um resumo a respeito de sua história, e um tutorial do seu uso. O material usado é uma tradução livre (com alguns muitos acréscimos) do artigo "SSH tips, tricks & protocol tutorial" publicado por Damien Miller (djm@mindrot.org)" e apresentado na AUUG (Winter) 2002. Os direitos autorais do artigo pertencem a ele segundo as regras de uso, e temos que deixar isso claro. A página do site onde o artigo está é esta caso alguém se interesse em ver o texto original.





O que é SSH?

SSH (Secure SHell) é um protocolo de redes feito para substituir as ferramentas inseguras de login e execução de comandos remotos como telnet, rlogin e rsh. Acessar um sistema através de algum método como o telnet coloca tudo que você enviar e receber pois os dados são enviados através de texto puro. E sua sessão é completamente visível para qualquer outro na sua rede e na rede da máquina que você estiver acessando. Isso faz com que qualquer um possa monitorar e roubar ("sniffing") qualquer dado transmitido nessa conexão, como nome de usuário, senha, emails que você ler, comandos enviados, etc. Por essas razões, você precisa de algum sistema mais sofisticado para realizar a conexão remota.


Para evitar esses tipos de problemas, o SSH encripta a transmissão em ambas as direções. O SSH também oferece várias funcionalidades úteis:
  • Compressão: o tráfego pode ser comprimido a nível básico.
  • Chave pública de autenticação: pode, opcionalmente, substituir a autenticação por senha.
  • Autenticação do servidor: o que faz o ataque "homem-no-meio" mais difícil.
  • Encaminhamento de portas: Sessões arbitrárias de TCP podem ser encaminhadas por uma conexão TCP.
  • Encaminhamento X11: SSH pode encaminhar suas sessões do X11 (iniciar sessões no X via rede).
  • Transferência de arquivos: a família do protocolo SSH inclui dois protocolos exclusivos para transferência de arquivos.

História

SSH foi criado por Tatu Ylönen em 1995 e foi, primeiramente, lançado sob a licença de código fonte aberto. As versões seguintes foram tomando licenças mais restritas, porém elas no geral continuaram gratuitas para uso não comercial. Tatu então formou a SSH Communications security, a qual vende versões comerciais do SSH até hoje. As versões mais antigas do código implementado por ele são o que hoje chamamos de SSH versão 1.0.

Em 1997, um processo começo a tornar o SSH um padrão na Internet com o apoio da IETF. O que levou a criação da versão 2 do SSH. Na reimplementação, o protocolo foi dividido numa camada de transporte, e num protocolo de conexão e autenticação. Muitas falhas de segurança foram descobertas nesse processo.

Em 1999, a equipe do OpenBSD descobriu o código fonte das primeiras versões do SSH (através do OSSH2) feitas por Tatu Ylönen. A equipe adaptou o código para os padrões modernos e gerou o que ficou chamado de OpenSSH. O OpenSSH foi inserido no OpenBSD 2.6 em Dezembro de 1999. OpenSSH foi expandido por Markus Friedl para prover suporte ao SSH v.2 no começo de 2000.
Após isso, o OpenSSH se tornou, e continua a ser, a distribuição gratuita e mais popular, completa e portável. Inclusa em muitas distribuições de sistemas operacionais.
A história completa do OpenSSh está documentada aqui (em inglês).


O básico do uso do SSH

Login remoto

A sintaxe básica para logar em um host remoto é:
ssh hostname
Se você quiser adicionar um nome de usuário, você precisa utilizar o formato do rlogin:
ssh -l user hostname
Ou, numa forma mais simples:
ssh user@hostname

Caso seu sshd(servidor ssh) esteja sendo executado numa porta diferente da padrão, você pode especificar a porta na linha de comando:
ssh -p 2222 user@hostname

Descoberta inicial de chave do servidor

Na primeira vez em que você tenta conectar a um servidor ssh com o seu cliente, ele te pergunta para verificar a chave do servidor.
[djm@roku djm]$ ssh root@hachi.mindrot.org
The authenticity of host ’hachi.mindrot.org (203.36.198.102)’ can’t be established.
RSA key fingerprint is cd:41:70:30:48:07:16:81:e5:30:34:66:f1:56:ef:db.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ’localhost’ (RSA) to the list of known hosts.
root@hachi.mindrot.org’s password:
Last login: Tue Aug 27 10:56:25 2002
[root@hachi root]#

Isto é feito para prevenir que alguém tente se passar pelo seu servidor, ou tente intermediar sua conexão, o que daria a oportunidade de capturar sua senha e o conteúdo de sua sessão. Uma vez que você tenha verificado a chave do servidor, ela é salva pelo seu cliente, geralmente, no arquivo ~/.ssh/known_hosts para que uma verificação automática possa ser feita em toda tentativa de conexão. Se a chave do servidor mudar, o cliente exibe um aviso:
[djm@roku djm]$ ssh hachi
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.

The fingerprint for the RSA key sent by the remote host is
cd:41:70:30:48:07:16:81:e5:30:34:66:f1:56:ef:db.
Please contact your system administrator.

Add correct host key in /home/djm/.ssh/known_hosts to get rid of this message.
Offending key in /home/djm/.ssh/known_hosts:24
RSA host key for localhost has changed and you have requested strict checking.

Host key verification failed.

Executando comandos remotamente

SSH também suporta a execução de comandos remotamente. Quando você faz login, um pseudo-terminal é associado a sua sessão até você efetuar log out ou ser derrubado pelo servidor. Uma lista de comandos que são usados comumente via ssh:
[djm@roku djm]$ ssh root@hachi.mindrot.org "ls -C /bin"
root@hachi.mindrot.org’s password:
[ cpio echo ksh mv rm sleep
cat csh ed ln pax rmail stty
chgrp date eject ls ps rmd160 sync
chio dd expr md5 pwd rmdir tar
chmod df hostname mkdir rcp sh test
cp domainname kill mt rksh sha1
Caso você queira especificar qual o terminal vai utilizar (bash, konsole, lxterminal, etc), você precisa forçar o ssh a alocar qual você quer utilizando o argumento -t:
ssh -t user@hostname vi /tmp/foo

Redirecionando comandos de entrada e saída

Você pode redirecionar os descritores padrão de arquivos (stdin, stdout e stderr). O que permite alguns truques bem úteis:
[djm@roku djm]$ ssh root@hachi.mindrot.org "ls /bin | grep -i rm"
root@hachi.mindrot.org’s password:
rm
rmail
rmd160
rmdir
Neste exemplo, o comando grep é executado na máquina remota. Porém, é possível obtém a mesma resposta rodando o grep na máquina local:
ssh root@hachi.mindrot.org "ls /bin" | grep -i rm
Já aqui, note que o grep está fora das aspas. Ou seja, ele é executado no cliente. O que realiza um redirecionamento do stdio, que é muito útil quando estamos trocando dados entre duas máquinas diferentes.

No exemplo a seguir, um arquivo SQL hipotético é enviado para a máquina remota e retorna a mensagem de resultado do comando:
ssh hachi "psql billing" < billing.sql | grep -v ^INFO

Cuidado: um erro muito comum quando redirecionamos a saída de um processo ssh é o de haver comandos que dão algum retorno em scripts de inicialização que são executados toda vez que o shell é iniciado.  (e.g. .tcshrc, .kshrc, .bashrc, etc) ao de nos scripts de login (e.g. .profile, .login, .bash profile). Se houver algum comando que produz alguma saída nos scripts de inicialização do shell, a saída deles será incluída junto com a saída dos seus comandos. Eles também interrompem transmissão de arquivos via SSH.

Transferência de arquivos

SSH oferece várias maneiras de transferir arquivos. A maioria delas se usa do redirecionamento de entrada e saída já mencionados. Além desses temos mais alguns.

scp

scp é o mecanismo original do SSH para transferir arquivos. Ele é modelado com base no rcp (comando para cópia remota) do BSP (protocolo da Xerox PARC análogo ao TCP). Um protocolo com mais de 25 anos. Sua sintaxe é muito simples:
scp [user@]host:/path/to/source/file /path/to/destination/file

Ele copia um arquivo remoto para um destino local. Para fazer o inverso, copiar um arquivo local para um destino remoto, basta inverter os parâmetros do comando:
scp /path/to/source/file [user@]host:/path/to/destination/file

Em ambos os casos, o nome do arquivo a ser enviado pode ser um curinga referente a vários arquivos. Se o local para salvar os arquivos for omitido, o diretório home do usuário será usado. Por exemplo:
scp[user@]host:/home/djm/*.diff

O scp não trabalha muito bem com cópias de arquivos entre dois servidores remotos. Embora seja possível utilizando a seguinte sintaxe:
scp [user@]host1:/path [user@]host2:/path

Para esse comando funcionar, o host1 deve estar configurado para acessar o host2 sem o uso de login (através do uso de chaves públicas, que são explicadas mais adiante). De qualquer forma, uma pequena resposta é dada ao usuário quanto ao sucesso da operação.

scp pode também copiar arquivos de forma recursiva:
scp -r source-path [user@]host:/destination-path
scp -r [user@]host:/source-path /destination-path

Enquanto é muito útil para transferência simples de poucos arquivos, tem várias limitações. A mais incômoda é o péssimo tratamento de caracteres que podem ser interpretados pelo shell (como espaços). Por exemplo:
[djm@roku djm]$ scp "hachi:/mp3/J.S Bach/Matthaus Passion 0101.ogg" /tmp
cp: cannot stat ‘/mp3/J.S.’: No such file or directory
cp: cannot stat ‘Bach/Matthaus’: No such file or directory
cp: cannot stat ‘Passion’: No such file or directory
cp: cannot stat ‘0101.ogg’: No such file or directory

Nestes casos você tem que escapar os caracteres problemáticos:
scp "hachi:/mp3/J.S.\ Bach/Matthaus\ Passion\ 0101.ogg" /tmp

Outro problema do scp é que é necessário que ele seja capaz de encontrar um binário dele mesmo na máquina remota. Geralmente, esses comandos são instalados sem problema algum no $PATH dos sistemas remotos, mas se não as transferências não vão funcionar:
[djm@roku djm]$ scp hachi:/tmp/foo /tmp
bash: scp: command not found

draft-secsh-filexfer (vulgo sftp)

Muitas das deficiências do protocolo scp foram mapeadas e resolvidas pelo grupo IETF. O resultado foi o protocolo descritos no conjunto de rascunhos para Internet: draft-secsh-filexfer-*. Este protocolo, mais conhecido como sftp, é um protocolo genérico para transferência de arquivos elaborado para ser executado através de qualquer sistema de transporte seguro.

sftp parece bastante com a API UNIX de leitura de leitura de arquivos, com equivalentes para open(), read(), write(), lseek() assim como readdir() e família. Essa similaridade faz com que ele seja considerado mais próximo do NFS que ao protocolos de transferência de arquivos como o FTP.

O OpenSSH inclui um cliente interativo de sftp:
[djm@roku ssh-tutorial]$ sftp hachi
Connecting to hachi...

sftp> cd /usr/share/games
sftp> ls
drwxr-xr-x 8 root wheel 512 Aug 21 19:01 .
drwxr-xr-x 22 root wheel 512 Apr 30 2001 ..
drwxr-xr-x 2 root wheel 512 Aug 21 19:01 atc
drwxr-xr-x 2 root wheel 512 Aug 21 19:01 boggle
drwxr-xr-x 2 root wheel 512 Apr 30 2001 ching
drwxr-xr-x 2 root wheel 512 Aug 21 19:01 fortune
drwxr-xr-x 2 root wheel 512 Aug 21 19:01 larn<
drwxr-xr-x 2 root wheel 1024 Aug 21 19:01 quiz.db
-r--r--r-- 1 root games 2030 Aug 21 19:01 cards.pck
-r--r--r-- 1 root games 10087 Aug 21 19:01 cribbage.instr
-r--r--r-- 1 root games 1565 Aug 21 19:01 fish.instr
-r--r--r-- 1 root games 1941 Aug 21 19:01 wump.info
sftp> lcd /tmp
sftp> get c*
Fetching /usr/share/games/cards.pck to cards.pck
Fetching /usr/share/games/ching to ching
Cannot download a directory: /usr/share/games/ching
Fetching /usr/share/games/cribbage.instr to cribbage.instr
sftp> quit

tar-over-ssh

Como falamos antes, ssh pode ser usado para redirecionar entrada e saída entre hosts. Essa capacidade torna fácil a transferência de arquivos pro meio de utilidades padrões do unix como tar e cpio. Estes comandos apresentam vantagens quando você precisa transferir uma grande quantidade de arquivos, mantendo os atributos dos arquivos e copiar links comuns e simbólicos.

O exemplo a seguir vai copiar todos os arquivos e diretórios de /usr/share/games no host hachi para /tmp na máquina local. Note que isto vai preservar a estrutura do diretório e os atributos incluindo os utimes (datas de acesso e alteração), dono, grupo e permissões:
[root@roku root]# ssh hachi "cd /usr/share/games ; tar cf - ./a*" | \ > (cd /tmp ; tar xpvf -)
./atc
./atc/Atlantis
./atc/Game_List
./atc/Killer
./atc/OHare
./atc/Tic-Tac-Toe

Para copiar arquivos locais para um destino remoto, um comando simétrico pode ser usado:
(cd /tmp ; tar cf - ./xyz*) | ssh hachi "cd /tmp ; tar xcvf -"

Um pequena mudança no exemplo anterior permite gerar um arquivo tar local a partir de um conjunto de arquivos remotos (note que há um passo extra de compressão):
ssh hachi "cd /tmp ; tar cvf - ./* | bzip2 -9" > tmp.tar.bz2

Esta técnica é muito útil para realizar backup remoto automático, desde que a autenticação com chaves públicas esteja configurada.


Rsync

Rsync é um pacote e algoritmo para manter dois conjuntos de arquivos sincronizados. O Rsync envia somente as diferenças entre os dois conjuntos pela rede ao invés de enviar somente os conteúdos. Ele é muitas vezes usado como um sistema, muito bom, de espelhamento de arquivos ou como um substituto do scp/rcp. O Rsync possui suporte para ssh, o qual pode ser utilizado por uma opção de linha de comando. 
Podemos usá-lo para listar arquivos de diretórios específicos em máquinas remotas:
rsync -e ssh djm@hachi:/tmp/

Para sincronizar/copiar um conjunto de arquivos para a máquina local:
rsync -ve ssh djm@hachi:/bin/c* /tmp

O Rsync tem muitas outras opções e utilidades. Veja as páginas "man" sobre ele para ver melhor os detalhes.


Autenticação por chaves públicas

O SSH inclui a capacidade de autenticar os usuários através de chaves públicas. Ao invés de exigir um nome de usuário e senha, o servidor vai verificar a chave privada do usuário em comparação com a chave pública do usuário, armazenada no servidor.

Definir uma chave pública de autenticação requer que você gere um par de chaves pública/privada e instalar a porção pública no servidor. Também é possível atribuir privilégios a cada chave e quais hosts/endereços podem se autenticar utilizando-as.

Gerando chaves públicas

As chaves públicas são geradas utilizando o ssh-keygen. Ele pode gerar três tipos de chaves: rsa, dsa e rsa1. As chaves rsa1 são usadas para autenticação pelo SSH 1.0 (o que é mantido por questões de compatibilidade com sistemas antigos). Já as outras duas são utilizadas pelo SSH 2.0.


O tipo da chave a ser gerada é escolhida pela opção -t do ssh-keygen. Normalmente é preferível utilizar as chaves rsa pois elas são um pouco mais rápidas de autenticar que as chaves dsa. Exemplo de criação de uma chave rsa:
[djm@roku ssh-tutorial]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/djm/.ssh/id_rsa):
Created directory ’/home/djm/.ssh’.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/djm/.ssh/id_rsa.
Your public key has been saved in /home/djm/.ssh/id_rsa.pub.
The key fingerprint is:
3c:7e:41:2c:d2:51:f8:0b:ef:78:e7:e3:22:eb:af:6a djm@roku.mindrot.org

Caso você queira gerar uma chave sem utilizar uma frase secreta, o que pode ser útil em algumas situações (que serão descritas mais a frente):
ssh-keygen -t dsa -N ’’ -f ~/.ssh/id_dsa_example


Autenticando com chaves públicas

Agora que você já tem seu par de chaves, você deve instalar a chave pública no servidor em que você deseja realizar login. Essa chave é armazenada num arquivo com extensão .pub codificado em formato ASCII. Veja como é uma dessas chaves:
[djm@roku ssh-tutorial]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoosorAF8t6k6cmNXiPdP4eE63YFLr/3SjA
GLzCKAJ4cWyAPIrIdeaud1e+y5rj+1E6qEYM3Nl6Sju2dL21+ia+toqA2SQCtUrZTBYVyX
2D4f1x31oK4pTIlWrYzGuj+k3h3tmbr5AdUOk5kxki/xiLRx91gIuWC60qCsYJYVV10H9h
2LRNaSh2YRPptf7aJk+4QcwUuu6QB9g4WBznWWpwj7YeT7n57f38kTbSvatr5hrPWTRFYB
qT4LJqvalkrxQNX143uWOmfTMKV2pUBcMWroVR7Xo2d4Gh6VS2rpKxnq+CNjjj12TunVHR
qbbdkua5Ml/HbpHubmta/dGkoFrQ== Laptop key
Nota: o conteúdo acima fica todo em uma linha só. Acrescentamos quebras de linha para ficar mais fácil de visualizar e não ferrar com a layout do blog.

Para habilitar a autenticação com chaves públicas, você precisa copiar a chave pública para o fim do arquivo ~/.ssh/authorized_keys. O seguinte comando faz isso para você:
ssh hachi "umask 077; cat >> .ssh/authorized_keys" < ~/.ssh/id_rsa.pub

O umask restritivo é obrigatório porque o servidor se recusa a ler o arquivo ~/.ssh/authorized_keys se ele tiver permissões pouco restritivas. Uma vez que a chave estiver instalada no seu servidor, você já deve ser capaz de autenticar usando sua chave privada:
[djm@roku ssh-tutorial]$ ssh djm@localhost
Enter passphrase for key ’/home/djm/.ssh/id_rsa’:
Last login: Thu Aug 29 11:08:29 2002
[djm@roku ssh-tutorial]$
Note que foi pedida a frase secreta da chave privada ao invés de pedir a senha do usuário no servidor.

Usando o ssh-agent

Bem, até aqui a autenticação por chaves públicas não demonstrou nenhuma vantagem - trocamos apenas a necessidade de digitar uma senha por o de digitar uma frase secreta (geralmente muito mais longa que senhas). A solução para isso é o ssh-agent, um pequeno aplicativo que é executado uma vez por sessão de login e carrega todas as suas chaves privadas. Ele fornece as chaves automaticamente para o cliente e não será mais necessário digitar nada.

Para iniciar o ssh-agent, caso ele não esteja configurado no seu sistema, você precisa adicionar a seguinte linha ao arquivo de inicialização do sistema (o arquivo .profile ou algum similar):
test -z "$SSH_AUTH_SOCK" && eval 'ssh-agent -s'

Quando executado, o ssh-agent vai emitir uma série de variáveis de ambiente na saída padrão. A diretiva eval serve para verificar que as variáveis foram importadas para o seu sistema e a diretiva test serve para garantir que não vamos iniciar um processo do ssh-agent.

Assim que o ssh-agent estiver trabalhando, você tem que carregar suas chaves nele através do ssh-add. Executá-lo sem nenhum argumento resulta numa tentativa de carregar os três arquivos padrões (RSA 1.0, RSA 2.0 e DSA) no agente:
[djm@roku ssh-tutorial]$ ssh-add
Enter passphrase for /home/djm/.ssh/id_rsa:
Identity added: /home/djm/.ssh/id_rsa (/home/djm/.ssh/id_rsa)

Adicionadas as chaves ao agente, você pode realizar login sem precisar autenticar manualmente:
[djm@roku ssh-tutorial]$ ssh djm@hachi
Last login: Thu Aug 29 12:40:18 2002 from localhost.localdomain

O ssh-add serve para verificar quais chaves estão carregadas no agente:
[djm@roku ssh-tutorial]$ ssh-add -l
2048 40:a6:0a:59:e9:15:c0:d6:85:87:ec:63:5d:cc:06:ab /home/djm/.ssh/id_rsa (RSA)
2048 39:9f:9c:47:a9:be:94:f6:1e:e6:a5:97:2d:b0:74:c3 /home/djm/.ssh-old/id_rsa (RSA)

E também pode apagar todas as chaves no agente:
[djm@roku ssh-tutorial]$ ssh-add -D
All identities removed.

Restrições em chaves públicas

Chaves públicas podem ter restrições colocadas no lado do servidor. As mais comuns são os comandos forçados. Isto força o servidor a executar um comando sempre que uma certa chave execute um comando específico, independente do que for pedido pelo cliente. Isso é feito desta forma:
[djm@roku ssh-tutorial]$ cat ~/.ssh/authorized_keys
command="/bin/ls -l /tmp" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoosorAF
8t6k6cmNXiPdP4eE63YFLr/3SjAGLzCKAJ4cWyAPIrIdeaud1e+y5rj+1E6qEYM3Nl6Sju
2dL21+ia+toqA2SQCtUrZTBYVyX2D4f1x31oK4pTIlWrYzGuj+k3h3tmbr5AdUOk5kxki/
xiLRx91gIuWC60qCsYJYVV10H9h2LRNaSh2YRPptf7aJk+4QcwUuu6QB9g4WBznWWpwj7Y
eT7n57f38kTbSvatr5hrPWTRFYBqT4LJqvalkrxQNX143uWOmfTMKV2pUBcMWroVR7Xo2d
4Gh6VS2rpKxnq+CNjjj12TunVHRqbbdkua5Ml/HbpHubmta/dGkoFrQ== Laptop key
Neste exemplo, sempre que a chave especificada for usada num login, o comando /bin/ls -l /tmp será executado:
[djm@roku ssh-tutorial]$ ssh djm@hachi netstat
arch date gunzip mv sleep
ash dd gzip netstat sort
...

Note que o comando especificado na linha de comando, netstat, foi ignorado. O mesmo teria ocorrido se não tivéssemos especificado um comando. Quando um comando forçado é aplicado, o comando original é armazenado na variável de ambiente $SSH_ORIGINAL_COMMAND. Isto pode ser útil para scripts que restringem o acesso para um conjunto pré-definido de comandos permitidos.


Outra restrição bem útil é a clausula from="". Ela permite restringir os endereços das máquinas que serão autorizadas a realizar login utilizando a chave dada. Note que esta negação não se impede o usuário de se autenticar por outros meios, por exemplo, com o login e senha.
A clausula from apresenta um sistema básico de coringas:
from="192.168.*" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoosorAF ...

O mesmo sistema de restrições pode ser usado também para variáveis de ambiente:
environment="FREEDOM=SLAVERY" ssh-rsa AAAAB3NzaC1yc2EAAAABIw ...

Há muitas outras restrições relativas a encaminhamentos e requisições de pseudo-terminais. As quais são importantes se você quiser restringir completamente uma chave:
[djm@roku ssh-tutorial]$ cat ~/.ssh/authorized_keys
from="192.168.*",command="cvs server",no-pseudo-terminal,no-agent-forwarding,
no-X11-forwarding,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQ
...
Essa chave só está autorizada a conectar de 192.168.0.0/16, não pode requisitar um pseudo-terminal, não pode criar nenhum redirecionamento e é forçado a usar o comando cvs server.

Esta é uma excelente forma de fornecer acesso somente leitura ao CVS para desenvolvedores remotos.
Extremamente restritivas, chaves sem senha são muito úteis para tarefas automatizadas como backup remoto:
[djm@roku ssh-tutorial]$ cat ~/.ssh/authorized_keys
command="cd /var/cvs ; tar cvf - ./* | bzip2 -9 | gpg --encrypt -r djm@mindrot.org", 
no-pty,no-agent-forwarding,from="192.168.*",no-X11-forwarding,no-port-forwarding 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQ
...

Conectar com a chave acima geraria um backup do diretório /var/cvs compactado e encriptado usando OpenPGP. Poderíamos adicionar uma tarefa no cron para executar esse comando periodicamente:
[djm@roku ssh-tutorial]$ sudo crontab -lu root
0 0 * * * ssh -i .ssh/id_rsa_backup hachi > /var/backup/cvs-‘date +%Y%m%d‘.tar.bz2.gpg


Encaminhamento SSH

O SSH possui a capacidade de multiplexar várias conexões através de um canal SSH. Estes "encaminhamentos" permitem você realizar conexões TCP/IP, X11 e sessões do ssh-agent por meio de uma sessão SSH.

Encaminhamento do agente de autenticação

O exemplo mais simples de encaminhamento é o "encaminhamento de agente". Isto permite que uma conexão com o agente local (ssh-agent) seja encaminhada por uma conexão SSH e você poderá usá-la na máquina remota.

Por padrão, esta opção fica desativada, pois pode levar a problemas de segurança se você encaminhar seu agente (contendo suas chaves privadas) para uma máquina não confiável. Entre hosts confiáveis, o encaminhamento de agente é muito útil.

O encaminhamento de agente pode ser ativado pela linha de comandos:
ssh -A trustedhost

Ou no arquivo de configurações do cliente, especificando host por host:
[djm@roku ssh-tutorial]$ cat ~/.ssh/config
Host trustedhost
ForwardAgent yes

Uma vez ativado, será como ter um agente sendo executado na máquina remota:
[djm@roku ssh-tutorial]$ ssh -A hachi
Last login: Thu Aug 29 12:58:01 2002 from localhost.localdomain
[djm@argon djm]$ ssh-add -l
2048 40:a6:0a:59:e9:15:c0:d6:85:87:ec:63:5d:cc:06:ab /home/djm/.ssh/id_rsa (RSA)
2048 39:9f:9c:47:a9:be:94:f6:1e:e6:a5:97:2d:b0:74:c3 /home/djm/.ssh-old/id_rsa (RSA)


Encaminhamento do X11 (ou Área de trabalho remota via SSH)

O SSH também permite encaminhar sessões do X11, o que permite a você seguramente utilizar sessões X11 remotas como se fossem sessões locais. Novamente, esta opção é desativada por padrão por questões de segurança. Além de ser ativada, também é necessário que o servidor e o cliente tenham um binário do xauth disponível e acessível para configurar o sistema de autenticação MIT-MAGIC-COOKIE-1.



O encaminhamento do X11 pode ser ativo via linha de comando ou pelo arquivo de configurações:
ssh -X hachi xclock

Pelo arquivo de configurações:
[djm@roku ssh-tutorial]$ cat ~/.ssh/config
Host trustedhost
ForwardX11 yes


Encaminhamento de portas (ou tunelamento)

Uma ferramentas mais flexíveis do SSH é o encaminhamento de portas, o qual permite o SSH a encaminhar sessões de TCP arbitrárias. E, uma vez que essas conexões vão estar rodando sobre um canal SSH, elas vão ser completamente encriptadas. Isto faz com que o encaminhamento de portas seja muito útil para acrescentar segurança a protocolos tradicionalmente inseguros.

O SSH suporta encaminhamento de portas tanto do servidor para o cliente (localmente) quanto do cliente para o servidor (remotamente). O encaminhamento local permite que você encaminhe uma porta na máquina local (cliente), através duma conexão SSH, para um host e porta do servidor que você preferir. Ou seja, quando você tentar conectar nessa porta de sua máquina, o SSH vai redirecioná-la para o host e porta que você especificou. Isso de maneira completamente invisível tanto para você quanto para qualquer aplicativo que acessar essa porta.

Encaminhamento de portas local pode ser feito utilizando a opção -L PortaLocal:HostRemoto:PortaRemota na linha de comando. Por exemplo, o comando a seguir vai fazer com que acessos a porta 8000 da máquina local sejam redirecionados para o host remoto 10.88.45.12 na porta 80:
ssh -L8000:10.88.45.12:80 somehost

Também é possível inserir esse encaminhamento no arquivo de configurações do cliente:
Host fw.somedomain.com.au
LocalForward 8000 somehost.int.somesomain.com.au:80

Isto ajuda muito a administrar máquinas que trabalham atrás de firewalls. Com o uso de encaminhamento de portas sobre uma conexão ao firewall, você pode ganhar acesso às máquinas protegidas como se você estivesse se conectando a partir do firewall. Outro truque muito útil é encaminhar uma porta para um servidor proxy para burlar um filtro web local.

Quando utilizamos encaminhamento local de portas, o comportamento padrão é só permitir conexões da máquina local para as portas encaminhadas (feito por razões de segurança). Para permitir outros endereços de se conectarem as portas encaminhadas é preciso especificar a opção GatewayPorts. Isto pode, como nos casos anteriores, ser especificado via linha de comando -ogatewayports=yes ou no arquivo de configurações do cliente.


Alguns exemplos (retirados daqui):
Acessando remotamente a administração de impressoras do CUPS (porta 631):
Vamos direcionar o tráfego da porta local 5555 para a porta 631 do servidor 192.168.0.12, através de uma conexão SSH nesse mesmo servidor:
ssh -L 5555:192.168.0.12:631 192.168.0.12

Caso fosse necessário utilizar um usuário específico (por exemplo: joao), o comando ficaria assim:
ssh -L 5555:192.168.0.12:631 joao@192.168.0.12

Caso o servidor SSH estivesse em uma porta diferente da padrão (22), digamos porta 2222, faríamos dessa maneira:
ssh -p 2222 -L 5555:192.168.0.12:631 joao@192.168.0.12

Caso você deseje que as máquinas que se conectarem à sua estação possam utilizar o tunel, o comando seria (supondo que o IP de sua estação seja 10.0.0.28):
ssh -p 2222 -L 10.0.0.28:5555:192.168.0.12:631 joao@192.168.0.12

Com a conexão estabelecia, bastaria abrir o navegador web e acessar o endereço
http://localhost:631 (ou http://10.0.0.28:631 no caso de outras máquinas) para realizar o acesso.

Agora, suponhamos que você está com seu notebook em um CyberCafe, com conexão WiFi Open (sem criptografia) e deseja acessar os emails no servidor POP de sua empresa de forma segura. Para isso, você precisaria ter acesso SSH a um dos equipamentos da empresa, como um firewall ou outro servidor. Supondo-se que que dados de conexão sejam:
Firewall (com acesso SSH na porta 7788): 200.200.200.200
Servidor de Email (rodando POP na porta 110) : 172.16.100.50
Usuário para acesso SSH: antonio

o comando seria:
ssh -p 7788 -L 110:172.16.100.50: antonio@200.200.200.200

Basta configurar seu cliente de email para acessar o servidor POP-3 no endereço 127.0.0.1, porta 110 e acessar suas mensagens de forma criptografada.


Encaminhamento de portas remotas é o oposto: conecta uma porta do servidor a uma porta no cliente. A sintaxe é bem similar: -R remoteport:localhost:localport. O exemplo a seguir faz com que as conexões na porta 2500 da máquina remota sejam direcionadas para a porta 25 do host 10.34.54.12, que no caso se tratava do host local:
ssh -R 2500:10.34.54.12:25 somehost

Isso é útil, quando você precisa disponibilizar acesso da máquina remota a outra máquina, seja a sua máquina local ou qualquer outra. Pode ser por questões de segurança, burrocracia, constante troca de informações importantes, etc. Basicamente, seria o mesmo que conectar no host remoto e criar um encaminhamento local lá.

Encaminhamento dinâmico de portas

O SSH também suporta um modo que permite encaminhamento de portas "dinâmico". Nesta configuração, o SSH se comporta como um proxy SOCKS na porta especificada. Os clientes que se conectam a essa porta podem especificar um endereço e porta remotos ao qual querem conectar usando o protocolo SOCKS. Este modo é útil para fazer túneis através de firewalls (se você tiver clientes que suportem SOCKS). Este modo é definido passando a opção -D na linha de comando,e qual a porta que o seu ssh vai esperar por requisições SOCKS.


Para fazer isso basta usar a opção -D:
ssh -D 9999 username@remotehost.net

Qualquer aplicação que oferecer suporte ao protocolo SOCKS5 (e a maioria dos grandes programas de rede oferecem) pode encaminhar uma conexão via SSH e encaminhá-la para qualquer host que você especificar. Por exemplo, para um navegador, qualquer URL que você digitar será enviada através do túnel. Firefox, Xchat, Gaim e muitos outros suportam o uso de SOCKS5. A configuração para isso fica geralmente em preferências em configurações de conexão.

Lembre-se, como dizia Benjamin Parker ou "Tio Ben" , com grandes poderes vem grandes responsabilidades. Não é porquê você pode burlar firewalls e usar outros hosts para movimentar seu tráfego na rede que você deva, nem que nenhum administrador não vá notar a sua presença.


Mantendo sua sessão SSH ativa

De vez em quando você pode ter problemas com manter sua sessão parada mas disponível.  Por qualquer razão, a conexão é simplesmente fechada após X minutos de inatividade. Geralmente, isto acontece porque há um firewall entre você e a internet que está configurado para manter somente as conexões que não ficarem ociosas por 15 minutos ou algo nessa casa.

Felizmente, nas versões mais recentes do OpenSSH, há uma solução para esse problema. Simplesmente acrescente o código a seguir:
Host *
Protocol 2
TCPKeepAlive yes
ServerAliveInterval 60

No seu arquivo de configurações:
~/.ssh/config

Para mais detalhes sobre o arquivo de configurações, veja a página man do ssh_config. A diretiva  'TCPKeepAlive yes' diz ao cliente que ele deve enviar um tiquinho de dados pela conexão periodicamente para que o servidor saiba que você ainda está ali. 'ServerAliveInterval 60' define o período de tempo entre uma mensagem e outra para 60 segundos. Este truque engana muitos firewalls que de outra forma derrubariam a conexão, e você pode ir no banheiro tranquilo e ler toda a sessão de quadrinho sem precisar conectar novamente a todas as máquinas em que você estava conectado.



Finalizando a sessão SSH

Tudo que é bom acaba um dia. E há várias formas de finalizar sua sessão do SSH:
1 -
exit

2 -
logout

3 -
(Ctrl-d)

A última seria apertar as teclas "CTRL" + "D". Estas são maneiras de finalizar a sessão do SSH do lado do cliente. Geralmente elas finalizam o shell em que você está e fazem logoff na máquina remota. Algo que talvez você não saiba é que há outra maneira de finalizar uma sessão SSH. Isto é útil caso você perca conectividade com uma máquina e você não tenha como terminar sua sessão. Por exemplo, isto acontece se você permanecer logado em uma máquina enquanto ela está desligada. SSH tem suas próprias sequências de escape na linha de comando. Isto pode ser usado para terminar conexões, criar novos túneis ou listar os atuais e algumas outras funções.Para terminar uma conexão mesmo quando você não tem um terminal de comandos, pressione ENTER duas vezes (por precaução) e então a sequência '~.'. Um til e um ponto:
(ENTER) (ENTER) ~.

Isto vai finalizar a conexão SSH pelo lado do cliente ao invés de finalizá-la pelo lado do servidor.

Implementações do SSH

OpenSSH

OpenSSH é implementação mais popular do SSH. OpenSSH suporta o protocolo SSH (v1 e v2) e é distribuído sob uma licença BSD de código fonte aberto. OpenSSH roda no *BSD, Linux,
Solaris, Windows (via CygWin), HP/UX, Irix, Mac OS X, AIX, SCO, Tru64 e muitas outras plataformas.

OpenSSH é incluso com muitas distribuições gratuitas de sistemas operacionais (Linux, *BSD) assim como em várias comerciais (incluindo Mac OS X e IBM AIX). Ele também é a base da implementação do SSH do Solaris.

SSH Communications Corporation

SSH Communications Corporation foi fundada por Tatu Ylönen, (o criador do SSH). Eles fornecem implementações comerciais dos protocolos SSH v1 e v2. Eles também oferecem versões não comerciais da versão 1 e uma versão mais restrita da versão 2. Os produtos deles são suportados no Windows, Linux e diversos tipos de Unix.

Unix

OSSH
Uma implementação do protocolo SSH v1 feita por Björn Grönvall, baseado num código antigo do Tatu Ylönen o qual foi lançado sob a licença de código aberto. OSSH formou as bases das primeiras versões do OpenSSH.
FreSSH
Uma implementação gratuita do protocolo SSH v1 feita por Eric Haszlakiewicz, Thor Lancelot Simon e Jason R. Thorpe.
Uma implementação GPL do protocolo SSH  v2 feita por Niels Möller. LSH é interessante por seu suporte ao SPKI.

Windows

PuTTY
Uma implementação de ótima qualidade do telnet e dos protocolos SSH v1 e v2 feito por Simon Tatham. Ele também inclui um ssh-agent (pagent) assim como suporte a scp e sftp.
TTSSH
A free plugin providing SSH protocol v.1 capability for Tera Term Pro, a free terminal
emulator. Written by Robert O’Callahan.

Macintosh

Uma versão melhorada do NiftyTelnet, o qual suporta o protocolo SSH v1.
MacSSH
Uma implementação gratuita do protocolo SSH v2 baseada no BetterTelnet e no LSH.

Other

Uma implementação do protocolo SSH v1 para palmtops com PalmOS. Ele requer o PilotSSLeay.
Mindterm é uma implementação aberto em Java dos protocolos SSH. Mindterm 1 implementa SSH v1 e é código fonte aberto. As versões mais recentes suportam o protocolo v2 mas são comerciais.
Um cliente para o protocolo SSH v1 com uma licença confusa.




5 comentários:

sidtj disse...

Cara, esse foi o MELHOR post sobre ssh que já li! Você está de parabéns! De verdade, excelente!

Muito obrigado por compartilhar esse material de alta qualidade! Já está nos meus favoritos.

[sidtj]

Anônimo disse...

Valeu!
Mas o mérito não é nosso, é do Damien Miller que montou o tutorial de fato, nós só traduzimos. ;)

Mestre Delta disse...

Faço minha as palavras do sidtj : Esse foi o melhor tutorial sobre SSH que eu já li !! Parabéns cara, de ótima qualidade esse material. Já salvei nos favoritos.

Mestre Delta disse...

Creio que na linha :

ssh -p 7788 -L 110:172.16.100.50: antonio@200.200.200.200

Esteja faltando o número da porta do host remoto, ficando assim:

ssh -p 7788 -L 110:172.16.100.50:110 antonio@200.200.200.200

Espero não estar errado, e ter ajudado.

Abraços!

Joao paulo disse...

Como posso criar um arquivo no cygwin para acessar o host via SSH pelo nome e não pelo IP? Conheço as máquinas pelo nome, e sem esta conversão preciso ter uma tabela de ips em paralelo. jphbueno@gmail.com