UP | HOME

LPI-2 202-450 Topico 212.3
Shell seguro (SSH)

Índice

212.3 Shell seguro (SSH) - Objetivos

Peso 4

O candidato deve ser capaz de configurar e tornar seguro um daemon SSH. Este objetivo inclui administrar chaves e configurar o SSH para os usuários. Além disso, deve ser capaz de redirecionar um outro protocolo através do SSH e controlar o login SSH.

Conhecimentos-chave:

  • Arquivos de configuração e ferramentas do OpenSSH;
  • Restrições de login para o superusuário e para usuários normais;
  • Controlar e usar chaves de cliente e servidor para realizar login com e sem senha;
  • Uso de várias conexões de diversos hosts para garantir a manutenção da conexão em caso de perda de conexão com um host remoto.

Lista parcial dos arquivos, termos e ferramentas utilizados:

212.3 Shell Seguro (SSH) - Conteúdo

O protocolo SSH (também referenciado como Shell Seguro) é um metodo seguro para login remoto de um computador ao outro. Ele provê várias alternativas para uma autenticação forte protegendo a comunicação e a integridade dos dados com uma criptogriafia forte. É uma alternativa segura ante os protocolos de login não seguros tais como o telnet e o rlogin.

Usos típicos do protocolo SSH:

  • prover acesso seguro a usuários e processos automatizados;
  • transferências de arquivos interativas ou automáticas;
  • enviar comandos remotamente;
  • gerenciamento de infraestrutura de redes e outros componentes de sistema de missão crítica.

Funcionamento do protocolo SSH

O modo de funcionamento do SSH é utilizando um modelo cliente-servidor para permitir a autenticação de dois sistemas remotos e a criptografia dos dados que passam entre eles.

O SSH opera na porta TCP 22 por padrão (embora isso possa ser alterado se necessário). O host (servidor) escuta na porta 22 (ou qualquer outra porta atribuída) para conexões de entrada.

O SSH fornece vários mecanismos para autenticar o servidor e o cliente. Dois dos mecanismos de autenticação comumente usados são o baseado em senha e a autenticação baseada em chave. Embora a autenticação baseada em senha também seja segura, é aconselhável usar a autenticação baseada em chave.

diag-neg-ssh.png

Figura 1: Diagrama da negociação de conexão do SSH

A conexão é estabelecida pelo cliente SSH conectando-se ao servidor SSH. O cliente SSH conduz o processo de configuração da conexão e usa criptografia de chave pública para verificar a identidade do servidor SSH. Após a fase de configuração, o protocolo SSH usa criptografia simétrica forte e algoritmos de hash para garantir a privacidade e integridade dos dados trocados entre o cliente e o servidor.

O que é o OpenSSH?

O OpenSSH é um conjunto de ferramentas de código aberto e gratuito usado par fornecer comunicação segura e criptografada em uma rede de computadores usando o protocolo SSH. Ele é desenvolvido pelo grupo Open BSD e licenciado em uma licença BSD simplificada.

Todas as comunicações e trocas de credenciais usando o OpenSSH são cifradas portanto protegidas de ataques do tipo man-in-the-middle. Se um terceiro tenta interceptar uma conexão ativa em OpenSSH, o OpenSSH irá detectar e irá nos informar sobre isso.

O diretório /etc/ssh

O OpenSSH possui dois conjuntos diferentes de arquivos de configuração: um para programas clientes (ssh, scp e sftp) e um para o daemon do servidor (sshd).

┌─[root@centos7lpi]──[19:14]──[~]
└─[133]─># ls -l /etc/ssh/
total 604
-rw-r--r--. 1 root root     581843 Nov 24 13:35 moduli
-rw-r--r--. 1 root root       2276 Nov 24 13:35 ssh_config
-rw-------. 1 root root       3906 Mar  7  2021 sshd_config
-rw-r-----. 1 root ssh_keys    227 Mar  7  2021 ssh_host_ecdsa_key
-rw-r--r--. 1 root root        162 Mar  7  2021 ssh_host_ecdsa_key.pub
-rw-r-----. 1 root ssh_keys    387 Mar  7  2021 ssh_host_ed25519_key
-rw-r--r--. 1 root root         82 Mar  7  2021 ssh_host_ed25519_key.pub
-rw-r-----. 1 root ssh_keys   1679 Mar  7  2021 ssh_host_rsa_key
-rw-r--r--. 1 root root        382 Mar  7  2021 ssh_host_rsa_key.pub

O sshd_config é o arquivo de configuração do daemon ssh (ou processo do servidor ssh), enquanto o arquivo ssh_config é o arquivo de configuração do cliente ssh. O arquivo de configuração do cliente só tem influência quando você usa o comando ssh para se conectar a outro host por ssh. Como você pode ver, existem chaves públicas e chaves privadas aqui com algoritmos diferentes e podem ser usadas pelo OpenSSH para criptografar a sessão.

A relação entre os arquivos de configuração

Na verdade, o servidor OpenSSH lê vários arquivos de configuração. O arquivo sshd_config especifica as localizações de um ou mais arquivos de chave de host (obrigatório) e a localização de arquivos authorized_keys para usuários. Também pode referir-se a vários outros arquivos.

diag-ssh-conf-files.png

Figura 2: Diagrama de carga de configurações do daemon sshd

O arquivo /etc/ssh_config

Este arquivo contém diretivas similares as encontradas em /etc/ssh/sshd_config porém há ajustes específicos para os utilitários do SSH client tais como scp e sftp.

Precedência das configurações

Importante dizer que o cliente SSH obedece uma ordem de precedência na hora de carregar as configurações:

  1. primeiramente o SSH client lê as opções que lhe foram passadas via linha de comando no momento da execução;
  2. depois ele lê as configurações que constam no arquivo de configuração local do usuário /.ssh/config;
  3. Por fim ele lê as configurações que contam no arquivo global /etc/ssh/ssh_config.
O arquivo /etc/ssh/sshd_config

É o arquivo que o servidor OpenSSH lê ao ser iniciado, é bastante extenso pois é vastamente documentado com comentários pois tem uma boa quantidade de diretivas que podem ser ajustadas.

Vamos listar aqui algumas importantes:

Port
essa diretiva especifica a porta TCP que o serviço do SSH deve escutar, o padrão é na porta 22. Se for necessário mudar essa porta não esqueça de ajustar também no SELinux ou no Apparmor;
Protocol
o OpenSSH pode trabalhar com o protocolo do tipo 1, menos seguro, e o protocolo do tipo 2, mais seguro. Por isso, é bastante recomendável manter apenas o protocolo 2;
SyslogFacility

por padrão o servidor OpenSSH envia os logs para a facility AUTH do syslog;

  • auth: destina-se a registrar comandos relacionados à autenticação e autorização;
  • authpriv: destina-se a mensagens de natureza sensível.

Todos os logs serão escritos em /var/log/auth.log para sistemas Debian-like ou em /var/log/secure para sistemas RedHat-like.

LogLevel
por padrão o OpenSSH registra suas entradas de log no nível INFO. Se quisermos registrar mais detalhes (como tentativas de login malsucedidas) devemos aumentar o nível de registro para VERBOSE.
PermitRootLogin
especifica se o usuário root pode efetuar login por ssh ou não. Essa diretiva pode ser setada como:
  • yes: o usuário root poderá logar;
  • no: o usuário root não poderá logar de forma alguma;
  • without-password: a autenticação utilizando senhas fica desligada para o usuário root, assim permitindo login apenas utilizando chaves;
  • forced-commands-only: o login do root com autenticação de chaves será permitido, mas apenas se a opção de comando tiver sido especificada (o que pode ser útil para fazer backups remotos, mesmo se o login de root normalmente não for permitido). Todos os outros métodos de autenticação ficam desabilitados para o root.
PubkeyAuthentication
permite aos usuários logarem usando chaves ssh sem precisarem entrar com senhas;
PermitEmptyPassword
permite login para usuários sem senha definida;
PasswordAuthentication
permite autenticações utilizando senhas, porém para forçar autenticação por chaves para todos essa diretiva deve ser setada como no;
ChallengeResponseAuthentication
devene se a autenticação de "desafio-resposta" é permitida, para desabilitar a autenticação por senha também deve ser definida para no em conjunto com a diretiva acima;
IgnoreRhosts
Ignora uma modalidade de liberação de acesso legada, onde bastava que os endereços presentes nos arquivos /.rhosts e /.shosts pudessem entrar sem fornecer senha.
Banner
define um arquivo de texto para exibir seu conteúdo como banner para ser exibido sempre que alguém logar no ssh;
PrintMotd
exibe uma mensagem após o login;
MaxAuthTries
especifica o número máximo de tentativas de autenticação permitidas por conexão. Quando o número de falhas atinge a metade desse valor, as falhas adicionais são registradas no log. Ele pode ser sobrescrito pelo PAM se algum módulo PAM estiver associado;
GatewayPorts
permite a abertura de sockets no host onde roda o serviço OpenSSH permitindo o uso do recurso de encaminhamento de portas remotas, aceita os valores no (padrão), yes e clientspecified;
X11Forwarding
essa diretiva permite que janelas de programas sejam abertas através da conexão SSH. É necessário passar a opção -X para o comando ssh no cliente. Dessa forma, um programa sendo executado no servidor exibirá sua janela do ambiente gráfico do cliente.

Por padrão, todos os usuários com contas de usuário podem fazer login por meio de ssh, mas existem duas opções que podem ser adicionadas ao arquivo sshd_config para alterar o comportamento padrão:

AllowUsers
especifica alguns usuários para fazer login (ninguém mais poderá logar);
DenyUsers
proíbe alguns usuários de logar.

Túneis SSH e/ou encaminhamento de portas

O encapsulamento SSH é um método de transporte de dados arbitrários por meio de uma conexão SSH criptografada. Ele pode ser usado para adicionar criptografia a aplicativos legados. Ele também pode ser usado para implementar VPNs (Redes Privadas Virtuais) e acessar serviços de intranet através de firewalls.

diag-ssh-tunnel.png

Figura 3: Diagrama basico do encapsulamento SSH

O SSH é um padrão para logins remotos seguros e transferências de arquivos em redes não confiáveis. Ele também fornece uma maneira de proteger o tráfego de dados de qualquer aplicativo usando encaminhamento de porta, basicamente encapsulando qualquer porta TCP/IP sobre SSH. Isso significa que o tráfego de dados do aplicativo é direcionado para fluir dentro de uma conexão SSH criptografada para que não possa ser espionado ou interceptado enquanto estiver em trânsito. O encapsulamento SSH permite adicionar segurança de rede a aplicativos legados que não oferecem suporte nativo à criptografia.

Portanto, o encaminhamento de porta SSH é um mecanismo em SSH para encapsular portas de aplicativos da máquina cliente para a máquina servidor, ou vice-versa. Alguns administradores de sistema e profissionais de TI usam-no para abrir backdoors na rede interna de suas máquinas domésticas. Ele também pode ser usado por hackers e malware para abrir o acesso da Internet à rede interna.

Há três tipos de encaminhamentos de portas:

Encaminhamento de porta local

No Encaminhamento de porta local as conexões de um cliente SSH são encaminhadas, por meio do servidor SSH, para um servidor de destino.

Explicando com mais detalhes podemos abrir uma porta de conexção local e através de um túnel SSH alcançar alguma porta remota.

Esse recurso é muito útil quando precisamos alcançar algum serviço não seguro tais como HTTP e Telnet através da Internet sem precisar expor o serviço ou os dados, pois tudo isso estará protegido pela forte criptografia e autenticação do SSH.

Sintaxe para execução:

ssh -L host_local:porta_local:host_destino:porta_destino usuario@servidor_ssh

Alcançando um serviço desprotegido através de um host com serviço SSHd

Este cenário é o mesmo mostrado na Figura 3 porém vamos detalha-lo mais.

Imagine uma rede contendo ativos de rede tais como switches ouvindo a porta de Telnet para administração. Por questões de segurança os switches estão protegidos por um Firewall de perímetro que não permite que o tráfego de Telnet seja alcançado de fora.

Um administrador de redes que estiver atuando remotamente poderia facilmente alcançar esses switches de forma muito segura utilizando um túnel ssh utilizando a sintaxe:

ssh -L localhost:2323:ip.do.switch:23 user@fw.exemplo

Como a opção -L sempre aponta para portas do host onde o comando de cliente SSH está sendo executado, podemos omitir o termo localhost do comando deixando-o um pouco mais prático:

ssh -L 2323:ip.do.switch:23 user@fw.exemplo

Existem mais duas opções úteis a agregar no comando ssh no ato da abertura do encaminhamento de porta, são elas:

  • -f: que indica que o comando deve ser executado em segundo plano;
  • -N: determina que não deve ser aberta seção de shell no servidor OpenSSH.

Por fim o comando ficaria:

ssh -fNL 2323:ip.do.switch:23 user@fw.exemplo

diag-ssh-tunnel-port-local-ex1.png

Figura 4: Diagrama de encaminhamento de porta local

Por fim para poder conectar no switch você entrará com o comando:

telnet localhost 2323

Resumindo, no cenário aqui proposto você está encaminhando os dados que entrarem pela porta local 2121 através de um túnel SSH com criptografia forta para a porta 23 do switch remoto.

  • Exemplo de uso, conexão através de um host com serviço SSHd

    Em meu laboratório de LPI estou utilizando meu notebook que tem o hostname tesla (IP 10.152.240.41), nele subi uma VM com o hostname centos7lpi (IP 10.152.240.45) e outra vm com o hostname debianlpi (IP 10.152.240.47), como pode-se notar todos esses hosts estão no mesmo barramento de rede.

    Na VM debianlpi instalei o utilitário netcat (que falaremos mais dele no tópico 212.4), e com ele fiz a VM debianlpi ouvir a porta 4560/TCP com a seguinte sintaxe:

    netcat -n -l -vv -p 4560

    No meu computador executei o comando:

    ssh -fNL 1230:localhost:4560 root@centos7lpi.infralinux.net

    ┌─[root@debianlpi]──[13:38]──[~]
    └─[103]─># netcat -n -l -vv -p 4560
    listening on [any] 4560 ...
    connect to [10.152.240.47] from (UNKNOWN) [10.152.240.45] 58214
    teste
     sent 0, rcvd 7
    

    Na saída do comando netcat no host debianlpi podemos constatar que ele recebeu uma conexão provinda do IP 10.152.240.45 que é pertencente ao host centos7lpi.

    ┌─[jeremias@tesla]──[13:38]──[~]
    └─[1013]─>$ ssh -fNL 1230:10.152.240.47:4560 root@10.152.240.45
    ┌─[jeremias@tesla]──[13:38]──[~]
    └─[1014]─>$ telnet localhost 1230
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    teste
    ^]
    telnet> quit
    Connection closed.
    

    No meu computador o host tesla eu executei o comando para a abertura do túnel SSH com destino ao IP do host centos7lpi e no conteúdo da opção -L pedimos que no host tesla fosse aberta a porta 1230 e que todo o tráfego enviado a ela fosse encaminhado para a porta 4560 do host debianlpi através do túnel criado no host centos7lpi.

    Depois disso, no meu computador, abri uma seção de telnet com destino a localhost na porta 1230, como consta na listagem 3 a conexão foi aberta com sucesso. Logo pude escrever a palavra teste nessa seção de telnet que foi apresentada na saída do comando netcat que estava ativo no host debianlpi, como consta na listagem 2. Por fim entrei com a combinação de teclas <ctrl+]> para finalizar a seção de telnet e também a seção do comando netcat que estava ativa no host debianlpi.

Acessando um serviço desprotegido no host com serviço SSHd

E se o serviço desprotegido estiver localizado no próprio servidor onde está rodando o servidor SSH?

Este cenário é uma variação do anterior. Imagine que você tem um servidor do tipo VPS (Virtual Private Server ou servidor privado virtual em tradução nossa) em alguma cloud qualquer. Nele está instalada uma aplicação PHP que trabalha em conjunto com um banco de dados MySQL.

Por segurança o servidor MySQL não permite logins de usuários que não provenham de localhost, assim para podermos administrar o banco de dados de forma segura podemos usar túneis SSH. Segue sintaxe do comando:

ssh -L localhost:3306:localhost:3306 user@app.exemplo

O comando ficou bastante confuso, não? Bom a sintaxe da opção -L é composta de 4 elementos divididos por : sendo os dois primeiros elementos relativos ao socket que será criado no cliente de SSH (até por isso que o primeiro elemento pode ser omitido do comando) e os dois últimos elementos ao socket de destino ao qual estamos tentando enviar os dados. Portanto no exemplo o socket localhost:336 que vem após o segundo : refere-se a algum socket existente no próprio host onde está rodando o servidor SSH que estamos tentando conectar.

Como já exposto para ficar uma sintaxe menos confusa podemos omitir a primeira porção do conteúdo de -L:

ssh -L 3306:localhost:3306 user@app.exemplo

diag-ssh-tunnel-port-local-ex2.png

Figura 5: Diagrama de encaminhamento de porta local para serviço no próprio servidor onde está o SSHd

  • Exemplo de uso, conexão em um serviço no host com serviço SSHd

    O ambiente de laboratório para exemplificar esse caso é bem semelhante ao anterior, porém nesse caso não iremos utilizar o host centos7lpi em outras palavras não haverá host intermediário. A conexão SSH será aberta no próprio host onde está o serviço que queremos acessar de forma segura.

    Portanto da mesma forma que no cenário anterior no host debianlpi vou colocar o netcat para ouvir a porta 4560.

    ┌─[root@debianlpi]──[14:04]──[~]
    └─[106]─># netcat -n -l -vv -p 4560
    listening on [any] 4560 ...
    connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 55928
    teste 2
     sent 0, rcvd 9
    

    Já no meu computador vou executar o comando:

    ssh -fNL 1230:localhost:4560 root@10.152.240.47

    ┌─[jeremias@tesla]──[14:05]──[~]
    └─[1024]─>$ ssh -fNL 1230:localhost:4560 root@10.152.240.47
    ┌─[jeremias@tesla]──[14:05]──[~]
    └─[1025]─>$ telnet localhost 1230
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    teste 2
    ^]
    telnet> quit
    Connection closed.
    

    Na listagem 4 podemos notar que agora a conexão aparece como provinda de 127.0.0.1 provinda também de 127.0.0.1 (localhost), bem diferente do que ocorre na listagem 2.

Encaminhamento de porta remota

No encaminhamento de porta remota as conexões de um servidor SSH são encaminhadas, por meio do cliente SSH, para um servidor de destino. Em outras palavras é o caminho inverso do tópico anterior.

No caso através do comando do cliente SSH iremos orientar ao servidor SSH a abrir no host que o sustenta uma porta especificada no comando e encaminhar o tráfego destinado a esta porta para o estino que também especificamos no comando.

A sintaxe de todo o processo é exatamente igual ao do tópico anterior porém ao invés de usarmos a opção -L (de local) usaremos a opção -R (de remoto).

A utilização desse recurso também é análoga ao do tópico anterior.

Permitindo acesso a um serviço rodando no próprio PC com o cliente SSH

Imagine o cenário de um desenvolvedor que tem em seu computador local um servidor MySQL com uma base de teste e ele se depara com o famoso problema de "no meu computador funciona".

A suposta base é relativamente grande e apenas para um teste não valeria a pena enviar a base para o servidor VPS. Seria prático se ele pudesse fazer sua aplicação poder ler na base de seu computador. Porém ele está em sua casa, com o IP público randômico atribuído pelo DHCP da operadora, atrás de firewall e outros complicadores.

Nesse cenário o tal desenvolvedor poderia abrir um túnel utilizando o encaminhamento de porta remota. O comando a utilizar seria o seguinte:

ssh -fNR 3306:localhost:3306 user@app.exemplo

diag-ssh-tunnel-port-remota-ex2.png

Figura 6: Diagrama de encaminhamento de porta remota para o próprio cliente SSH

  • Exemplo de uso, permitindo acesso a um serviço rodando no próprio PC com o cliente SSH

    Para esse exemplo irei utilizar meu próprio computador hostname tesla IP 10.152.240.42 e uma VM pública de teste com IP 189.72.106.199.

    No meu computador coloquei pra ouvir a porta 4560

    ┌─[jeremias@tesla]──[15:56]──[~]
    └─[1008]─>$ netcat -n -l -vv -p 4560
    Listening on 0.0.0.0 4560
    Connection received on 127.0.0.1 41776
    teste
    

    Também do meu computador abri um novo terminal e executei o comando ssh com a seguinte sintaxe:

    ssh -R 1230:localhost:4560 vpsuser@189.72.106.199

    Com esse comando eu já caí na seção do Bash do servidor e pude executar o teste de telnet para localhost:4560

    [vpsuser@vps05754928]~# telnet localhost 1230
    Trying ::1...
    Connected to localhost.
    Escape character is '^]'.
    teste
    ^]
    telnet> quit
    Connection closed.
    

    Desse exemplo importa notar que na listagem 6 vemos que a conexão é originada de localhost e na listagem 7 (no host remoto) também mandamos o comando telnet com destino a localhost. No fim de tudo é estranho. Mas funciona.

Permitindo acesso a um serviço interno através do cliente SSH

Imaginemos o cenário em que precisa-se expor para algum usuário em uma rede remota algum serviço de rede que está em sua rede local, mas por algum motivo você não tem permissão de escrita no seu firewall para poder criar um encaminhamento de porta. Porém você tem acesso a um computador onde está a o usuário ao qual você quer apresentar o serviço de rede.

Esse exemplo pode até parecer algo que nunca vai acontecer, mas é muito comum em empresas de desenvolvimento algum desenvolvedor querer exemplificar uma tela nova para um site que está criando ou coisa semelhante.

Bom esse cenário é um pouco mais complexo do que os apresentados até aqui, pois agora precisamos abrir uma porta no servidor SSH para ouvir conexões de outros hosts na rede onde ele se encontra. Esse comportamento é bloqueado por padrão na configuração do OpenSSH. Porém pode ser ajustado alterando o valor da diretiva GatewayPorts no arquivo de configuração /etc/ssh/sshd_config. Essa diretiva aceita três valores possíveis:

no
é o valor padrão, não permitindo a abertura de portas no host onde roda o servidor OpenSSH;
yes
permite que se abra quaisquer sockets possíveis no host onde roda o servidor OpenSSH;
clientspecified

também permite que se abra quaisquer sockets possíveis no host onde roda o servidor OpenSSH, mas com um porém, o cliente é obrigado a especificar o endereço de IP do socket a abrir.

Nessa opção fica bastante evidente a utilidade do formato de quatro elementos separados por : para as opções -L e -R. Pois para abrir um socket no servidor remoto que contenha o IP 192.168.30.18 o cliente precisaria especificar da seguinte forma:

192.168.30.18:8080:localhost:80

Posto isso o tal desenvolvedor precisaria fazer os devidos ajustes no serviço OpenSSH no servidor para permitir a criação de / sockets/ e depois usaria o comando ssh com a seguinte sintaxe:

ssh -R 8080:host.a.expor:80 usuario@host.remoto

diag-ssh-tunnel-port-remota-ex1.png

Figura 7: Diagrama de encaminhamento de porta remota

Com o arranjo exposto acima o "Cliente remoto" conseguiria alcançar a aplicação exposta na Intranet1 apontando seu navegador para o endereço fictício http://servidor-ssh:8080.

  • Exemplo de uso, permitindo acesso a um serviço interno através do cliente SSH

    Para esse exemplo irei utilizar 4 hosts sendo:

    • meu notebook hostname tesla IP 10.152.240.42;
    • o host centos7lpi IP 10.152.240.45;
    • o host debianlpi IP 10.152.240.47;
    • o host centos5 IP 10.152.240.51;

    Nesse laboratório supomos que o host tesla e o host debianlpi estão "lado a lado" no mesmo barramento. Já os hosts centos7lpi e centos5 estão "lado a lado" em barramentos diferentes.

    Execução do laboratório

    1. no host debianlpi coloco pra ouvir a porta 4560;
    2. no host centos7lpi configuro a diretiva GatewayPorts para yes;
    3. no host tesla executo o comando: ssh -fNR 1230:10.152.240.47:4560 root@10.152.240.45

      Que criará o túnel com o host centos7lpi e solicitará a abertura da porta 1230 para encaminhar conexões;

    4. No host centos5 executo o telnet com destino ao host centos7lpi na porta 1230.
    ┌─[root@debianlpi]──[15:56]──[~]
    └─[126]─># netcat -n -l -vv -p 4560
    listening on [any] 4560 ...
    connect to [10.152.240.47] from (UNKNOWN) [10.152.240.42] 47518
    teste
     sent 0, rcvd 7
    

    Note que na saída do comando netcat executado no host debianlpi mostra que a conexão veio pelo IP 10.152.240.42 que é o endereço do meu computador, o host tesla, que para efeitos do nosso laboratório devem ser considerados hosts que estão "lado a lado" no mesmo barramento.

    ┌─[root@centos5]──[17:04]──[~]
    └─[258]─># telnet 10.152.240.45 1230
    Trying 10.152.240.45...
    Connected to 10.152.240.45 (10.152.240.45).
    Escape character is '^]'.
    teste
    ^]
    telnet> quit
    Connection closed.
    

    Note que partindo do host centos5 estou enviando o comando Telnet para o IP 10.152.240.45 que é o IP do host centos7lpi na porta 1230.

    Resumindo utilizando o host centos5 alcançamos o socket 10.152.240.47:4560 ativo no host debianlpi utilizando o socket 10.152.240.45:1230 sustentado no host centos7lpi através de um túnel SSH com o host tesla.

Encaminhamento de portas dinâmico

Essa técinica consiste em criar uma conexão ssh com o objetivo de utilizar a máquina remota como um gateway/proxy. E como nos casos anteriores a opção em linha de comando a utilizar é diferente. Aqui utilizaremos -D (de Dinâmico).

Aqui, também diferente dos formatos anteriores, não precisaremos apresentar ao opcional -D todos aqueles detalhes sobre socket que precisávamos especificar. Agora basta especificar a porta TCP a qual iremos abrir em nosso cliente SSH para utilizar como entrada para nossos dados. O socket de saída será atribuído dinâmicamente pelo servidor OpenSSH funcionando análogo a um proxy squid. Segue um comando de exemplo:

ssh -D 3028 user1@end.do.servidor.remoto

X remoto via SSH

É uma técnica semelhante aos túneis SSH, no caso essa técnica permite abrir a janela de uma aplicação rodando no servidor onde está rodando o sshd por meio de uma conexão SSH.

Por exemplo, para exibir localmente o programa VirtualBox instalado em uma máquina remota:

  1. Abra a conexão SSH com a máquina onde está o VirtualBox utilizando a opção -X:

    ssh -X usuario@virtualbox.exemplo.local

  2. Na máquina remota basta chamar o programa:

    $ VirtualBox

Pode-se simplificar isso tudo em um só comando:

ssh -X usuario@virtualbox.exemplo.local "VirtualBox"

O comando passado como argumento no final será executado na máquina remota. Opcionalmente o comando ssh também pode enviar os dados recebidos pela entrada padrão para a entrada padrão do comando remoto.

Autenticação baseada em chaves SSH

Até agora nós entendemos como o SSH funciona. Como mencionamos quando a conexão SSH é iniciada, a chave pública do servidor SSH é transferida para o cliente e armazenada em ./ssh/known_hosts e o cliente a usará para continuar a negociação com o servidor. Depois o usuário deverá ser autenticado enviando nome de usuário e senha.

Como já mostrado no /etc/ssh/ constam as chaves públicas e privadas relativas ao computador.

Pois bem além das chaves do próprio computador, cada usuário também pode possuir sua chave pública e privada que podem ser utilizadas para garantir sua autenticidade.

Dessa form, é possível fazer com que o acess ovia SSH seja feito automaticamente, sem necessidade de fornecer a senha em todo login. Isso é especialemte útil quando um computador remoto é acessado frequentemente. Antes de conseguir fazer o login sem senha, é necessário que o usuário crie a chave pública e chave privada.

As chaves criptográficas podem utilizar diferentes tipos de formatos, sendo os mais populares o DSA e o RSA. Para gerar uma chave DSA de 1024 bits, utiliza-se:

ssh-keygen -t dsa -b 1024

Chaves RSA suportam um tamanho em bits maior, como 4096:

ssh-keygen -t rsa -b 4096

Um tamanho maior em bits torna ainda mais difícil a quebra da criptografia.

As chaves podem ser criadas com ou sem senha, as chamadas passphrases. Importa dizer que chaves protegidas com senhas são mais seguras, pois toda vez que forem utilizadas será necessário informar a senha respectiva.

O comando ssh-keygen criará as chaves (pública e privada) no diretório ~/.ssh/ na máquina de origem para o usuário atual.

O conteúdo do arquivo da chave pública do usuário deverá ser incluída no arquivo authorized_keys, criado no computador de destino dentro do diretório .ssh/ na home do usuário a logar no computador de destino. Esse arquivo pode conter uma ou mais chaves que foram criadas em máquinas utilizadas como origem de acesso.

Enviando a chave pública para o computador de destino

Supondo que o computador de destino tenha o IP 192.168.1.1 e a conta jeremias, a chave pública do formato DSA pode ser copiada com o comando:

cat ~/.ssh/id_dsa.pub | ssh jeremias@192.168.1.1 "cat >> ~/.ssh/authorized_keys"

Descrevendo: o conteúdo do arquivo ~/.ssh/id_dsa.pub será direcionado para o comando ssh. Este, por sua vez, redirecionará o conteúdo para o comando cat na máquina remota que por fim incluirá o conteúdo no final do arquivo /.ssh/authorized_keys na ocnta na m[aquina remota.

Hoje o processo de cópia de chaves pode ser executado com um comando específico o ssh-copy-id:

ssh-copy-id -i ~/.ssh/id_dsa.pub jeremias@192.168.1.1

Se não for especificado o -i o comando ssh-copy-id irá procurar automaticamente o arquivo ~/.ssh/id_rsa.pub.

O uso de chaves públicas com passphrase

Se for informada uma passphrase durante a criação da chave, será perdida toda a conveniência de realizar o login sem senha, pois será necessário informar a pasphrase da chave todas vez que ela for utilizada. Contud, é possível evitar a digitação da passphrase a todo momento se for utilizado o comando ssh-agent.

O ssh-agent atua como uma espécie de chaveiro. Ele armazena a autorização e libera o usuário da necessidade de digitar a passphrase novamente durante a mesma seção. Para utilizá-lo, basta executar o comando ssh-agent:

┌─[jeremias@tesla]──[18:01]──[~]
└─[1003]─>$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-H4Fe0wcBpDjk/agent.1574038; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1574039; export SSH_AGENT_PID;
echo Agent pid 1574039;

O ssh-agent irá para o segundo plano e exibirá as variáveis de ambiente que necessitam ser declaradas. Somente se essas variáveis estiverem acessíveis na cessão é que a autorização automática do ssh-agent poderá ser utilizada. Essas variáveis serão usadas pelos outros programas para fazer a autenticação via ssh-agent.

Com o ssh-agent ativo e as variáveis de ambiente declaradas, é utilizado o comando ssh-add para incluir a chave do usuário no ssh-agent:

┌─[jeremias@tesla]──[18:12]──[~]
└─[1004]─>$ ssh-add
Enter passphrase for /home/jeremias/.ssh/id_rsa:
Identity added: /home/jeremias/.ssh/id_rsa (/home/jeremias/.ssh/id_rsa)

A pasphrase será solicitada apenas no momento da execução do comando ssh-add, feito isso, não será necessário informar a passphrase nas sessões onde as variáveis exportadas estiverem acessíveis.

Manipulação das chaves SSH

Além de servir pssh formatos de chaveara criar chaves SSH o comando ssh-keygen permite a manipulação das chaves SSH. Para entendermos isso importa dizer que as chaves SSH são chaves assimétricas, em outras palavras a chave privada é diferente da chave pública. Posto isso deve-se entender que a partir da chave privada podemos gerar a devida chave pública. Porém a partir da chave pública nunca poderemos gerar a chave privada. E é esse o segredo de toda a segurança quando se fala em assimetria dentro do escopo de cryptografia.

Bom com o que colocamos acima fica fácil entender o porque a chave privada sempre deve ser guardada com muito cuidado. Pois se a perdermos não temos como recuperá-la sem operações de backup.

Sobre as chaves públicas há 4 formatos disponíveis para aplicações diferentes:

  1. o formato do próprio OpenSSH;
  2. o formato PEM;
  3. o formato PKCS8;
  4. o formato RFC4716.

A chave no formato do próprio OpenSSH é a que o comando ssh-keygen gera automaticamente quando criamos uma chave. Mas no dia a dia é interessante saber alterar o formato da chave pública quando necessário.

Usaremos duas opções no ssh-keygen:

-e
esta é a opção de "exportação" no caso ela lê o arquivo de chave privada ou chave pública no formato OpenSSH que especificaremos com a opção -f e permite exportá-lo nos formatos RFC4716, PEM e PKCS8 que devem ser especificados na opção -m;
-f
especifica o arquivo de chave ao qual iremos trabalhar;
-i
essa é a opção de "importação" com essa opção poderemos apenas especificar arquivos de chave pública (não aceita arquivos de chave privada) e nos formatos que não sejam o do próprio OpenSSH (afinal estamos importando) usando essa opção poderemos especificar na opção -m os formatos RFC4716, PEM e PKCS8.
-m
é a opção que usamos para especificar os formatos de chave RFC4716, PEM e PKCS8. Quando na execução de uma importação essa opção irá especificar o formato do arquivo de entrada, quando na execução de uma exportação essa opção irá especificar o arquivo de saída, nos dois casos o formato padrão (se a opção for omitida) será o RFC4716.

Ao utilizar o comando ele sempre irá printar o resultado na saída padrão. Portanto deveremos usar o pipe > para direcionar essa saída para um arquivo e podermos manipulá-lo.

Exemplos:

Exportar uma chave pública (formato RFC4716) a partir de uma chave privada: ssh-keygen -e -m RFC4716 -f .ssh/chave > /tmp/chave.ppk

Exportar uma chave pública (formato PEM) a partir de uma chave pública:

ssh-keygen -e -m PEM -f .ssh/chave > /tmp/chave.pem

Importar uma chave pública para o formato do OpenSSH:

ssh-keygen -i -m PEM -f /tmp/chave.pem > /tmp/chave.pub

Clientes SSH

Nessa seção vamos dar uma olhada rápida nos clientes de SSH começando por algumas formas de chamar o próprio SSH:

Tabela 1: Formatos de chamar o ssh client
Comando SSH Descrição
ssh -V Mostra a versão do cliente SSH
ssh -v user1@server1.exemplo.com Conecta no servidor no modo verboso
ssh -lv user1 server1.exemplo.com O mesmo do comando anterior
ssh user1@server1.exemplo.com <comando> Executa <comando> no host remoto
ssh -X user@server1.exemplo.com Executa o ssh ativando o encaminhamento do X11
Comandos SCP

Podemos usar o comando SCP para copiar arquivos entre o host local e o host remoto usando a criptografia e autenticação do SSH.

  • Copiando um arquivo local para um servidor remoto:

    scp localhostfile.txt user1@remotehost.example.com:/home/user1/

  • copiando um arquivo de um host remoto para a o host local:

    scp user1@remotehost.example.com:/home/user1/remotehostfile.txt .

Comandos SFTP

O SFTP (SSH File Transfer Protoco ou protocolo de transferência de arquivo por SSH) é um protocolo de transferência de arquivos seguro. Ele tem pleno suporte as funcionalidades de segurança e autenticação do OpenSSH.

Tabela 2: Comandos SFTP
Comandos SFTP Descrição
sftp user1@server1.example.com Conecta o SFTP com o user1
sftp> ? Apresenta a ajuda
sftp> lpwd Mostra o diretório local
sftp>ls Lista os diretórios remotos
sftp>lls Lista os diretórios locais
sftp> put local.profile Envia o arquivo local.profile
sftp> mput *.txt Envia múltiplos arquivos
sftp> get myfile.txt Baixa o arquivo myfile.txt
sftp> mget *.txt Baixa múltiplos arquivos
sftp> cd testdir Muda o diretório remoto
sftp> lcd test Muda o diretório local
sftp> mkdir mytestdir Cria um diretório remoto
sftp> lmkdir mydownloads Cria um diretório local
sftp > rm mytempfile.txt Apaga um arquivo remoto
sftp > rm mytempfile.txt Apaga um diretório remoto
sftp> ! Sai do shell sftp

Autor: Jeremias Alves Queiroz

Criado em: 2021-12-19 dom 13:12

Valid XHTML 1.0 Strict