SSH ou Secure Shell é o mais usado meio de acesso remoto para servidores e appliances baseados em Linux, BSD e seus derivados. Sem entrar em muitos detalhes históricos ou filosóficos, esta ferramenta praticamente acabou com o antigo Telnet e podemos dizer até com o FTP tradicional. Mas você sabe usá-la minimamente bem?
Neste texto eu vou abordar quatro funcionalidades do SSH e algumas algumas tarefas adicionais que possam ser necessárias:
- Linha de comandos remota
- Transferência de arquivos
- Acesso remoto ao sistema de arquivos
- Criação de certificados para autenticação
- Como enviar os certificados para o servidor
- Tunelamento de conexão
- Acesso a um servidor de banco de dados privado a partir de um túnel SSH
O texto ficou bem longo e pensei muito sobre a possibilidade de dividi-lo em vários artigos, ou manter assim mesmo em um único “textão” separado por tópicos. Optei pela segunda opção, então favorite o link e leia-o com calma e tempo em quantas sessões forem necessárias. Com certeza vai valer a leitura e quando terminar você pode ver mais conteúdo sobre o mesmo assunto procurando por SSH aqui mesmo no blog.
Antes do SSH, o meio mais comum de acesso remoto a um terminal era o Telnet, no entanto devido a sua comunicação em texto puro e sem criptografia, logo que a Internet se tornou um lugar selvagem e promíscuo o seu uso passou a ser desaconselhável.
Futuramente (em outro texto) veremos que o Telnet ainda tem sua vez, mas para acesso remoto a servidores, hoje isso é inconcebível.
Mas voltando ao SSH, nós podemos usá-lo de inúmeras formas, e o propósito será sempre o mesmo. Enviar e receber dados e comandos de uma máquina para outra com a segurança de uma conexão cifrada por um par de chaves assimétricas, o que impede a possibilidade de que algum curioso espionando a rede consiga capturar suas informações em trânsito.
Esta ferramenta é tão importante que é praticamente onipresente em todas as distribuições Linux, Unix e atualmente até o Windows disponibiliza a sua versão a partir do Powershell usando exatamente a mesma sintaxe. Basta abrir o shell do Windows e digitar o comando “ssh”.
Vamos começar então pelo básico.
Acessando uma máquina remota
A forma mais simples de acessarmos um servidor remoto usando SSH é invocando o comando ssh da sua máquina seguido do login e o endereço da máquina remota, como segue:
ssh -l meuloginremoto endereco.meuservidor
Uma outra forma que particularmente eu adoto com mais frequência é substituindo o “-l meuloginremoto” pelo “meuloginremoto@“
ssh meuloginremoto@endereco.meuservidor
Esta é apenas uma mudança estética e não afeta em nada o funcionamento do comando, sendo a critério do usuário escolher qual usará com maior frequência. Observe no entanto que algumas versões limitadas do ssh, como as disponíveis em alguns dispositivos embarcados, tal como switch, roteadores etc, poderá aceitar somente uma das duas opções.
Uma informação adicional aqui sobre este assunto é que se você não informar o login remoto, o ssh tentará usar o nome de usuário local como usuário remoto.
Por exemplo se o seu usuário, tanto na sua máquina local quanto na máquina remota é “welington”, você pode ignorar o “-l login” e mesmo o “login@”, informando diretamente o endereço do servidor a ser acessado.
ssh endereco.meuservidor
No entanto, se o login remoto for diferente, digamos, “welington” na máquina local e “welingtonbraga” então obrigatoriamente eu devo informar o login remoto, como feito nos exemplos anteriores.
Por fim, além do nome ou Ip da máquina e um login nela, você precisa saber em que porta o serviços está disponível.
Por padrão usa-se a porta TCP/22, mas não é raro que o administrador a altere para outra qualquer de acordo com suas políticas de segurança. Caso o sistema que você pretende acessar use uma porta diferente de 22, você precisará do parâmetro “-p” para informá-lo como segue:
ssh -p 2234 -l meuloginremoto endereco.meuservidor
No exemplo acima o SSH está na porta 2234 do meu servidor remoto.
Meu primeiro acesso remoto
Quando você se conecta a um servidor SSH pela primeira vez, você deve aceitar a chave apresentada. Como no exemplo abaixo:
welrbraga@local$ ssh welrbraga@meuweb1
The authenticity of host 'meuweb1 (192.168.1.4)' can't be established.
ECDSA key fingerprint is SHA256:ZZeCrTqeAIMG5mI+VEQU0aMAVIrFt/R55XIugB4M9/o.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'meuweb1' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.11.0-1022-aws x86_64)
welrbraga@meuweb1$
Observe que na terceira linha de resposta houve uma pergunta que eu respondi com “yes“
É aqui que a sua máquina e a remota estão “combinando” as chaves de criptografia que usarão entre si para assegurar a proteção desta comunicação. Se você não aceitar, a comunicação será cancelada.
Chaves com problema
Em algumas circunstâncias pode ocorrer da chave de criptografia da máquina ter sido alterada e neste caso você não será autorizado a entrar.
Destaco aqui que esta não é uma restrição da máquina remota, mas da sua máquina local que detecta que as chaves combinadas em sessões anteriores foram alteradas e por segurança ao invés de ignorar este “detalhe suspeito”, ela o alerta do ocorrido, para que decida se deve aceitar as novas chaves ou se está diante de um problema sério.
A mensagem se assemelha com esta:
welrbraga@local$ ssh wbraga@server2.datacenter
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The ECDSA host key for server2.datacenter has changed,
and the key for the corresponding IP address 192.168.1.3
is unchanged. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.
Offending key for IP in /home/wbraga/.ssh/known_hosts:437
remove with:
ssh-keygen -f "/home/wbraga/.ssh/known_hosts" -R "192.168.1.3"
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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 a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:7bt2BRXYJeK11lsW964TkcyCLbLgenlEVzGr45782no.
Please contact your system administrator.
Add correct host key in /home/wbraga/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/wbraga/.ssh/known_hosts:369
remove with:
ssh-keygen -f "/home/wbraga/.ssh/known_hosts" -R "server2.datacenter"
ECDSA host key for server2.datacenter has changed and you have requested strict checking.
Host key verification failed.
“Spoofing de DNS”, “Identificação do host remoto alterada” … Pode parecer assustador mas em muitos casos isso pode ser apenas porque o administrador alterou o nome da máquina ou seu IP para outro que você já tenha acessado antes.
Isso bem comum onde isso pode ocorrer é se você trabalhar para várias empresas com o mesmo computador e elas usarem o mesmo range de endereços IPs internos.
Por exemplo, digamos que você acessa por SSH o servidor WEB da empresa XYZ que possui o endereço IP 192.168.0.3. Dai há algum tempo, você vai para empresa ABCD e ao acessar o servidor de banco de dados desta empresa o endereço Ip, coincidentemente é o mesmo 192.168.0.3.
Neste caso o SSH vai cuspir na tela aquela mensagem assustadora e que, ao menso neste caso, não é uma falha de segurança mas apenas o fato de você ter dois hosts com o mesmo endereço.
Nestes casos, basta remover a chave antiga da sua máquina, com o comando ssh-keygen, como mostrado abaixo e em seguida fazer o acesso por SSH normalmente:
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "meuserver2.datacenter"
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "192.168.1.3"
Observe que eu usei o mesmo comando duas vezes trocando o nome pelo o IP. Isso porque o SSH registra no arquivo known_hosts uma chave para cada endereço da máquina.
Se você acessar por Ip, depois pelo hostname, então haverão duas chaves a serem removidas. Se a máquina tiver 10 endereços IPs ou alias (cnames) no DNS e você já acessou por todos eles … apague os todos.
É muito mais frequente você encontrar várias empresas que tenham uma máquina com o IP 192.168.1.10, ou até mesmo com o nome “web1”, do que várias empresas que tenham alguma máquina com o mesmo FQDN web1.minhaempresa.com. No máximo seria web1.outraempresa.com, mas veja que é completamente diferente.
Sendo assim, uma boa dica para evitar ou pelo menos minimizar estes problemas com chaves é acessar as máquinas sempre pelos seus nomes com FQDN, o que reduz a chance de termos estes alertas.
Esse tipo de problema é tão chato e tão frequente para quem trabalha com experimentação e máquinas e ambientes de testes que eu particularmente mantenho uma função no meu .bashrc para lidar com isso:
rm-known_host() {
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "$1"
}
Desta forma sempre que tenho problemas de chaves com o host de QUE EU TENHO CERTEZA DO QUE HOUVE PARA MUDANÇA DA CHAVE, E NÃO UM ATAQUE, basta eu digitar:
rm-known_host 192.168.1.3
rm-known_host meuserver2.datacenter
Executando comandos remotos
A forma de acesso que vimos antes abrirá o terminal remoto e você usará aquela máquina como se estivesse fisicamente diante de um terminal local, podendo digitar tantos comandos quanto necessário para sua atividade. No entanto, digamos que você só queira executar um único comando.
Por exemplo, você recebeu a não grata missão de descobrir o quanto há de memória, espaço livre em disco, se o horário está sincronizado ou qualquer outra informação parecida.
Claro que existem ferramentas especializadas nisso e que poderiam facilitar a tarefa para cada caso, mas suponhamos que não seja o caso e você terá que entrar em todas as máquinas remotas para descobrir tal informação. Ou seja, em todas as máquinas você deverá fazer o login, digitar o comando, sair e repetir tudo denovo em outra máquina.
Isso pode ser feito com um só comando. Por exemplo, para descobrir a quantidade memória livre poderiamos fazer assim:
wbraga@local$ ssh server2 free -m
Warning: Permanently added the ECDSA host key for IP address '192.168.1.3' to the list of known hosts.
wbraga@server2's password:
total used free shared buff/cache available
Mem: 948 200 189 3 558 584
Swap: 0 0 0
wbraga@local$
Perceba que na mesma linha de comandos eu invoquei o ssh e já informei o comando que queria executar (free -m). O resultado do comando foi exibido na minha tela e automaticamente eu já fui desconectado do servidor remoto, de forma bem simples e rápida, pronto para repetir na segunda máquina.
Eu poderia repetir isso inúmeras vezes com vários comandos e em diversas máquinas que necessitar, porém perceba que neste caso me foi pedida a senha do usuário remoto, o que vai me dificultar as coisas se estiver pensando em automatizar alguma tarefa. É aqui então que entra a autenticação com certificado.
Criando o meu certificado
O certificado usado para este propósito é o mesmo que você está acostumado a usar com o Git, por exemplo.
Caso você já tenha um não precisa criar outro. Você pode usar o mesmo se preferir, ou se não crie outro novo com o comando abaixo:
wbraga@local$ cd ~/.ssh
wbraga@local~/.ssh$ ssh-keygen -f certificado-server10
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in certificado-server10
Your public key has been saved in certificado-server10.pub
The key fingerprint is:
SHA256:DJSW5Ux79YtqY-SP/fO47h+fbLQRVtJtmFxnmPr/Ri0 wbraga@weldesk
The key's randomart image is:
+---[RSA 3072]----+
| .+o .. B+|
| + .++ . ..O.=|
| .. + . o.o.|
| o . .. ..|
| S . +....|
| . o =E o|
| O = o +* |
| o . =ooB|
| o=.o*=|
+----[SHA256]-----+
Isso criará dois arquivos:
- certificado-server10 (a parte privada do certificado – sempre guardada com você) e,
- certificado-server10.pub (a parte pública do certificado que você copiará para os servidores remotos que deseja acessar).
O comando “ssh-keygen” possui uma infinidade de parâmetros mas eu ignorei todas, exceto o “-f” para indicar o nome dos arquivos, mas podem haver circunstâncias em que você necessitará algo mais, se for o caso conulte a página de manual para obter mais informações.
Dois parâmetros mais comuns e que podem ser necessários em algumas ocasiões são:
- “-b” que define o número de bits do certificado. No exemplo acima, foi usado o padrão que atualmente é de 3072 bits. Mas eu poderia ter informado “-b 4096” ou “-b 1024” para ter criado um certificado mais, ou menos “resistente”;
- “-t” que define o tipo de certificado. O padrão usado quando nada é especificado, é o RSA, mas eu poderia ter usado “-t ecdsa” ou mesmo “-t dsa” etc.
Normalmente você pode seguramente usar o padrão, como eu coloquei no comando de exemplo, mas em casos específicos você terá que mudar ao menos estes dois argumentos acima.
Um roteador, switch ou outro appliance mais antigo que ainda esteja em operação mas o firmware só suporta chaves DSA, ou ainda mais atualizado e que só aceita chaves RSA com 4096bits.
Também é importante destacar que normalmente nós não colocamos senhas nestes certificados. no exemplo de criação de certificado acima, observe que foi pedida uma senha, mas nós simplesmente ignoramos este pedido, pressionando ENTER duas vezes.
Em alguns casos muito especificos, pode ser que haja necessidade de usar esta senha com o certificado, mas honestamente, em quase 20 anos usando SSH eu nunca me deparei com tal necessidade prática.
E por fim, estes arquivos deverão estar na pasta oculta “.ssh” no seu HOME, pertencer somente a você, ter permissão somente de leitura e escrita exclusivamente para o proprietário (permissão 700).
Estes últimos requisitos são importantíssimos em máquinas Linux e Unix, caso eles não sejam cumpridos há uma grande chance de você não conseguir acessar seu host via SSH. Sendo assim, caso você precise corrigir as coisas use os comandos chown e chmod para colocar a casa em ordem.
chown -r $HOME/.ssh
chmod 700 .ssh
chmod 600 .ssh/*
Duas últimas dicas sobre a criação dos certificados, desta vez para quem estiver em ambiente Windows:
A primeira. Instale o programa PuttyGen para poder gerar as chaves que estão sempre dentro do seu HOME em uma pasta oculta chamada “.ssh”
A segunda. Embora o PuttyGen possua uma interface gráfica no Windows, opte por criar as chaves via linha de comandos como fizemos nos exmeplos acima. Enquanto o ambiente gráfico cria as chaves em formato “.ppk” e que darão mais trabalho para serem convertidos para uso em servidores Linux, via linha de comandos as coisas funcionam como deveriam.
Enviando um certificado de autenticação para o servidor remoto
Uma vez que tenhamos os arquivos do certificado, nós devemos enviar somente a parte pública para os servidores que serão acessados remotamente.
No Linux, esta tarefa é feita com o comando abaixo:
ssh-copy-id server2
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 4 key(s) remain to be installed -- if you are prompted now it is to install the new keys
wbraga@server2's password:
Number of key(s) added: 4
Now try logging into the machine, with: "ssh 'server2'"
and check to make sure that only the key(s) you wanted were added.
Porém, como eu já disse anteriormente, o usuário remoto pode ser diferente do usuário local, então neste caso devemos informar o usuário remoto, ao copiar a chave para lá:
ssh-copy-id welingtonbraga@server2
Outra informação importante aqui é que o comando ssh-copy-id considera que encontrará um arquivo de chave pública na pasta “$HOME/.ssh” e cujo nome inicie com “id_*” (por exemplo id_rsa e id_rsa.pub), caso haja mais de um disponível, ele considerará o mais recente com base na data/hora de alteração dos arquivos.
Mas nós não precisamos renomear suas chaves caso tenha mais de uma e com nomes mais intuitivos. Se precisarmos enviar uma chave específica para o servidor, como por exemplo, exatamente aquela que criamos com o nome “certificado-server10”, basta usar o parâmetro “-i” e se necessário o caminho completo também:
ssh-copy-id -i ~/.ssh/certificado-server10 welingtonbraga@server2
Estes comandos farão uma cópia de nossa chave pública local no servidor remoto dentro do arquivo $HOME/.ssh/authorized_keys, pedindo a sua senha, que será fornecida pela última vez.
Feito isso todas as vezes que eu tentar fazer login no servidor remoto “server2”, a partir desta máquina e com este usuário, eu não terei mais o pedido de senha pois o processo de autenticação e autorização foi realizado com o certificado que é muito mais seguro do que a senha (desde que o você o guarde com segurança).
A propósito, muitos serviços de hospedagem remota hoje em dia obrigam a autenticação por certificado, como por exemplo se você tiver instâncias EC2 da AWS rodando Linux, por padrão você não poderá acessar estas máquinas via SSH usando login/senha, mas somente com um login/certificado.
Por fim, no windows não há o comando ssh-copy-id, então caso você tenha gerado seu par de chaves a partir do PuttyGen neste ambiente a forma mais “simples” de enviar sua chave para o servidor remoto será com o comando abaixo:
type $env:USERPROFILE\.ssh\id_rsa.pub | ssh meuservidorremoto "cat >> .ssh/authorized_keys"
ou ainda:
cat $envuserprofile/.ssh/id_rsa.pub | ssh meuusuarioremoto@meuservidorremoto 'cat >> .ssh/authorized_keys'
Não esqueça de trocar o nome do servidor pelo nome correto ou IP para onde a chave será enviada.
Um pouco sobre segurança e guarda de certificados
É importante dizer que você não precisa ter uma chave para cada servidor que deseja acessar, mas aqui entra um grande dilema da segurança de informação:
Uma chave para todos os servidores – Se ela for violada ou vazada todos os servidores remotos estarão vulneráveis, e dependendo da quantidade de máquinas envolvidas, será um processo bem lento para atualizar a chave em todos eles e mitigar os problemas.
Uma chave para cada servidor – Se uma chave for violada ou vazada apenas aquele servidor estará comprometido, no entanto não é tão trivial administrar dezenas ou mesmo centenas de chaves a partir de cada máquina que você use o cliente de acesso SSH. Imagine que você administre 100 servidores remotos a partir do seu desktop no escritório e também no notebook usado em viagens. Serão 200 chaves para gerenciar neste caso. Um conjunto para cada combinação de máquina remota+máquina local. E “pane geral” na sua cabeça se ainda tiver vários usuários remotos diferentes e cada uma delas, gerando então mais um par de chaves para cada caso.
Você pode usar algumas dezenas de artifícios para minimizar isso, por exemplo um repositório de chaves RSA que você compartilhe entre todas as máquinas, mas ai você já criou um novo ponto de falha. E se este repositório for violado!?
Em fim, este tema é motivo de muita discussão e já li threads imensas sobre o assunto em alguns fóruns e em todos os casos, após uma centenas de réplicas e tréplicas o assunto acabou sendo esquecido cada um se mantendo com a mesma opinião ou fazendo o que sempre fez.
Transferindo arquivos entre máquinas
Assim como você envia comandos, é possível também enviar arquivos. Esta funcionalidade substitui parcialmente o que antes faziamos com FTP, porém com mais segurança.
Considerando então que você já consiga acessar a máquina remota para emitir comandos, agora enviar arquivos para ela ou pegar arquivos para sua máquina é um processo extremamente simples com o comando “scp”.
SCP é o comando de cópia segura que vem no pacote de ferramentas do SSH, então você não precisa fazer nada de extra para tê-lo disponível.
wbraga@local$ scp act2019.xlsx welingtonbraga@server4:/tmp
act2019.xlsx 100% 13KB 90.3KB/s 00:00
No exemplo acima eu transferi um arquivo chamado act2019.xlsx para a pasta “/tmp” no meu servidor remoto “server4”. O login (welingtonbraga@) poderia ser omitido conforme já comentado anteriormente, mas atenção a forma como especifiquei o caminho onde o arquivo será armazenado.
Após o nome do servidor o caminho é obrigatoriamente precedido por “:”. Logo se eu conferir o conteúdo da pasta /tmp no meu servidor, deverei encontrar este novo arquivo por lá.
Tal como /tmp eu poderia ter usado qualquer outra pasta naquele servidor, desde que o usuário remoto usado no login (neste caso o “welingtonbraga”) tenha permissão de escrita.
Por exemplo, no próprio home do usuário (/home/welingtonbraga) ou dentro do pasta de logs (/var/log) etc.
Caminhos absolutos e relativos nas cópias
No exemplo anterior eu usei um caminho absoluto (a partir da raiz) como destino da cópia no servidor remoto. Para especificar caminho relativo (geralmente ao HOME do usuário) basta não incluir a primeira “/”.
Por exemplo o comando seguinte copia o arquivo download.csv para o home do usuário welingtonbraga naquela máquina remota:
wbraga@local$ scp download.csv welingtonbraga@server4:
download.csv 100% 28KB 165.7KB/s 00:00
Observe que após o “:”, nada foi especificado, então o arquivo estará no HOME do usuário.
Agora, vamos supor que eu use o comando assim:
scp download.csv welingtonbraga@server4:sheets
Aqui há duas possibilidades:
(1) Se “sheets” é uma pasta existente dentro do HOME, o arquivo “download.csv” será copiado para dentro dela;
(2) Se a pasta não existir, o comando SCP entenderá que você quer renomear o arquivo no destino, e neste caso o nosso arquivo “download.csv” será salvo com o nome “sheets”, ao invés do seu nome original.
wbraga@local$ scp download.csv server4:sheet
download.csv 100% 28KB 134.2KB/s 00:00
wbraga@local$ ssh server4 ls -lh sheet
-rwxr-xr-x 1 wbraga usuarios 28K Apr 12 13:50 sheet
Uma forma de fazer o SCP entender que “sheets” trata-se de um diretório é adicionar uma “/” após o nome dela. Desta maneira, se a pasta “sheets” não existir, a cópia não será realizada.
wbraga@local$ scp download.csv server4:sheets/
scp: sheets/: Is a directory
wbraga@local$ ssh server4 ls -lha
total 60K
drwx------ 1 wbraga usuarios 556 Apr 12 10:50 .ssh
Veja que o SCP retornou um erro e nada foi adicionado ao servidor remoto, já que a “/” ao final o força a entender “sheets” como diretório.
Cópias recursivas
Cópia recursiva é como chamamos as cópias de várias pastas aninhadas dentro de outra. Veja os dois exemplos a seguir:
wbraga@local$ scp 2020/ server4:
2020: not a regular file
wbraga@local$ scp -r 2020/ server4:
mikrotik-20200730.backup 100% 71KB 181.9KB/s 00:00
mikrotik-20200731.backup 100% 122KB 250.3KB/s 00:00
mikrotik-20200804.backup 100% 138KB 310.6KB/s 00:00
mikrotik-20200805.backup 100% 159KB 371.2KB/s 00:00
mikrotik-20200806.backup 100% 166KB 347.9KB/s 00:00
Note que a cópia não foi bem sucedida. Eu recebi uma mensagem de erro informando que “2020” não é um arquivo regular. Sim, isso é o esperado já que “2020” é uma pasta e não um arquivo..
Na segunda tentativa eu já indiquei o parâmetro “-r” que permite a cópia recursiva e transfere todo o conteúdo da pasta.
Copiando de volta
Da mesma forma que podemos levar arquivos para o servidor remoto, também podemos trazê-los. Por exemplo, abaixo, eu copio um arquivo de log que está no servidor para a minha máquina local:
wbraga@local$ scp server4:/var/log/cloud-init.log .
cloud-init.log 100% 138KB 497.7KB/s 00:00
Perceba que o processo é idêntico e tão simples quanto. O que muda aqui é que eu indiquei o servidor de origem do arquivo.
Como dica extra para finalizar este tópico. Você também pode copiar arquivos entre dois servidores remotos sem precisar acessar o terminal deles:
wbraga@local$ scp welington@servidorweb1.meudominio:/var/www/index.php welrbraga@servidorteste.meudominio:/var/www/
No exemplo acima, a partir da minha máquina local eu estou lendo o arquivo do “servidorweb1” e o transferindo para o “servidorteste” em um único comando.
Só esteja atento que se eu não tiver minha chave publicada nestes servidores eu receberei um pedido de senha para cada um deles, mas no final a cópia será realizada (desde que eu tenha permissão para ler e gravar, claro).
Usando as pastas do servidor remoto como se fossem locais
Se você precisa fazer muita atividade entre duas máquinas, ou precisa usar comandos que necessariamente devem ser executados a partir de sua máquina, você pode acessar as pastas da máquina remota como se fossem locais simplesmente montando o servidor como se fosse um volume virtual de storage de rede (NAS).
Isso será feito da mesma forma que fazemos com volumes samba, nfs, afs etc. Ou seja, montando o volume em um ponto de montagem (diretório local) e então lendo o seu conteúdo como se estivesse realmente na nossa máquina.
Para que isso funcione em primeiro lugar você deverá instalar o pacote sshfs, que permite montar um sistema de arquivos virtual com base no serviço SSH, mas normalmente não vem instalado por padrão.
A “mágica” acontece graças ao FUse (Filesystem in Userspace) que permite a criação de módulos diversos para que os desenvolvedores “inventem” seus volumes virtuais. E felizmente alguém muito iluminado inventou o SSHFS (SSH Filesystem) e que funciona com base no FUse, suportado pela maioria das principais distribuições Linux, MacOS X e FreeBSD.
Felizes usuários de sistemas baseados no Debian, como o Ubuntu, Mint etc basta rodar um apt para instalá-lo, como segue:
wbraga@local$ sudo apt install sshfs
Lendo listas de pacotes... Pronto
Construindo árvore de dependências
Lendo informação de estado... Pronto
Os NOVOS pacotes a seguir serão instalados:
sshfs
...
Obter:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 sshfs amd64 3.6.0+repack+really2.10-0ubuntu1 [43,5 kB]
Baixados 43,5 kB em 1s (73,6 kB/s)
A seleccionar pacote anteriormente não seleccionado sshfs.
A preparar para desempacotar .../sshfs_3.6.0+repack+really2.10-0ubuntu1_amd64.deb ...
A descompactar sshfs (3.6.0+repack+really2.10-0ubuntu1) ...
Configurando sshfs (3.6.0+repack+really2.10-0ubuntu1) ...
A processar 'triggers' para man-db (2.9.1-1) ...
Com o pacote instalado podemos montar este volume virtual e acessar os discos da máquina remota por SSH como se fossem locais.
wbraga@local$ sudo mkdir /mnt/remoto
wbraga@local$ sudo chown wbraga:wbraga /mnt/remoto
wbraga@local$ mount.fuse wbraga@server4: /mnt/remoto -t sshfs
wbraga@local$ df -h
Sist. Arq. Tam. Usado Disp. Uso% Montado em
/dev/sda5 224G 116G 105G 53% /
wbraga@server4: 7,7G 3,5G 4,3G 45% /mnt/remoto
Observe no exemplo acima que nas duas primeiras linhas eu apenas criei, localmente, uma pasta que serve de ponto de montagem (/mnt/remoto) e dei permissão de acesso ao meu usuário. Será nesta pasta que os arquivos da máquina server4 serão acessados como se estivessem locais.
A montagem do volume ocorreu de fato na terceira linha onde usei o comando “mount.fuse”, informando o caminho remoto (wbraga@server4:), o ponto de montagem na minha máquina local (/mnt/remoto) e o tipo de filesystem que neste caso é o “sshfs”.
Uma vez montado seus comandos locais nesta pasta (/mnt/remoto) afetarão diretamente os arquivos lá no servidor “server4”, ou qualquer outro que você indicar.
Após terminar suas atividades você pode desmontar o volume remoto simplesmente usando o comando umount.
umount /mnt/remoto
Notem que nem a montagem e nem a desmontagem requerem privilégios administrativo (de root).
AVISO AOS INICIANTES: Para quem não tem experiência com montagem de volumes manualmente, esta pasta poderia ter sido criada em qualquer lugar do sistema, inclusive dentro do meu HOME, ou dentro de /tmp … enfim, qualquer lugar de sua preferência, mas quando se faz isso muitas e muitas vezes, é de bom hábito seguir um padrão para você não se perder, e meu padrão é sempre criar dentro /mnt ou /media que são os locais recomendados para montagens de volumes, segundo o padrão FHS (Filesystem Hierarchy Standard).
Aqui vale deixar algumas considerações:
- A montagem do exemplo, me dá acesso apenas ao HOME do usuário wbraga, no server4. Se eu quisesse acessar qualquer outra pasta bastaria fazer como explicado nas seções sobre cópia de arquivos e informar o caminho a ser acessado após um “:”.
- Como você está acessando um sistema de arquivos remoto (via rede) o acesso poderá não ser tão veloz quanto você espera. Velocidade da sua rede, latência, tamanho dos arquivos, quantidade de arquivos, performance de ambas as máquinas, radiação cósmica, humor do administrador do firewall remoto… tudo pode ser um problema neste caso e muitas vezes você ou aceita, ou desiste.
- Se o acesso por certificado estiver funcionando corretamente, você não será questionado de senha para montagem do volume, o que pode ser bom se você pretende usar este artifício em scripts por exemplo.
O que mais eu preciso saber sobre cópias remotas?
Bom, este é o básico, mas particularmente, quando eu preciso fazer longas transferências de arquivos eu uso o Rsync, ao invés do SCP.
Eu já escrevi algumas vezes sobre o Rsync e talvez futuramente eu faça um compilado de tudo, já atualizando a experiência e facilitando a leitura, mas por hora uma busca por Rsync aqui no blog vai te apresentar todos os textos sobre o assunto.
A grande vantagem do Rsync para estes casos (cópias muito longas) é que ele usa um protocolo delta que transfere apenas o que ainda não foi transferido, então se a cópia precisar se suspensa por qualquer motivo, você poderá continuá-la depois a partir do ponto que parou.
Túneis SSH ou VPN de pobre (inteligente)
Até algum tempo atrás VPN era a palavra na moda para segurança e estava na boca de 9 entre 10 pessoas que não entendem mais do que a diferença entre o monitor e um tomate.
O pior é que seguindo a onda das “fakenews” que também fez muito sucesso nesta época, vários especialistas vergonhosamente entraram na onda de afirmar que isso era o suprassumo da tecnologia para questão segurança online.
Longe de discutir quem foi inocente, vítima, aproveitador ou oportunista neste assunto, a verdade é que uma VPN, ou túnel é uma ferramenta útil no dia a dia para administração remota e é isso que pretendo mostrar usando artifícios que já existem nativamente em qualquer sistema Linux.
Acessando um servidor PostgreSQL interno através de um túnel SSH
Digamos que eu esteja em casa e precise acessar um serviço de banco de dados PostgreSQL em uma máquina interna da minha empresa. Neste cenário, o serviço está em uma máquina exclusiva e isolada dentro da minha empresa. Ninguém sem acesso direto a rede interna tem acesso a ele. É aqui que entra a VPN ou rede Virtual Privada.
Uma VPN é um túnel criptografado entre a minha máquina e algum lugar seguro para acessar o meu serviço. Este “algum lugar seguro” normalmente é uma máquina devidamente preparada para aguentar as tentativas de ataque que ela receberá durante toda sua vida online, bloqueando os acessos indevidos e permitindo os acessos devidos.
Há muitas formas de se fazer isso, e o SSH permitem três delas (túneis locais, tuneis remotos e túneis dinâmicos). Para o que queremos nós vamos criar um túnel local, os demais ficam para uma nova oportunidade.
Considerando que uma ponta do túnel é a minha máquina de casa e a outra tem que está lá na empresa, nós precisaremos que haja um servidor SSH que eu possa acessar de fora da rede corporativa e que para simplificar os exemplos e as explicações eu vou chamá-la de “tunelserver”.
Além de acessível pela Internet por SSH, a máquina “tunelserver” deve ter permissão de acesso ao meu servidor PostgreSQL, pois para efeitos práticos o mecanismo de autorização do banco verá as conexões chegando desta máquina.
No caso do Postgresql me refiro ao arquivo pg_hba.conf, mas essa observação é valida para qualquer serviço e você deverá certificar-se de que a partir da máquina “tunelserver” você consiga acessar o serviço desejado.
No Mysql, por exemplo é na tabela mysql.hosts ou mysql.user que você define a autorização para cada usuário a partir de uma máquian especifica.
Se fosse um serviço web Apache/Nginx talvez não precise de autorização nenhuma … Você deve entender as particularidades de cada serviço para permitir o acesso remoto. Basta lembrar que na visão de segurança do serviço, ele será acessado pelo endereço Ip de “tunelserver”.
Seguindo então. Você tem certeza que consegue dar um um “ssh seuusuario@tunelserver” ? Se sim, siga adiante, senão volte ao texto sobre acesso SSH e só retorne a esta seção aqui, quando este acesso for possível.
O que vai mudar do acesso convencional para o túnel é o uso do parâmetro “-L” que para este caso eu usaria assim:
ssh -L 5432:postgresqlserver.datacenter:5432 welingtonbraga@tunelserver.minhaempresa
Atenção para a linha de comandos acima. Se eu tirar o parâmetro “-L” e todo o seu complemento, o que sobra é uma conexão SSH normal como já fizemos antes e isso é exatamente o que ocorre.
Você terá um terminal de linha de comandos aberto na máquina tunelserver.minhaempresa onde poderá digitar qualquer comando nesta máquina. Mas não é somente isso que ocorreu.
Por baixo do capô, o SSH está escutando na porta 5432 da sua máquina local e tudo que chegar ali ele vai enviar para postgresqlserver.datacenter, na mesma porta (mesma porta porque eu assim a defini, mas poderia ser portas diferentes se necessário).
Com esta sessão de SSH aberta em alguma janela minimizada, abra outro terminal na sua máquina e acesse o serviço PostgreSQL como se fosse um serviço instalado localmente.
wbraga@local$ psql -h localhost erp
Password for user wbraga:
psql (12.9 (Ubuntu 12.9-0ubuntu0.20.04.1), server 12.9.1)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
erp=#
Como eu expliquei antes e torno a repetir para não deixar dúvidas: O SSH abriu a porta 5432 em minha máquina e fica escutando por conexões ali. Sempre que ocorrer qualquer requisição nesta porta local ele vai encaminhar pelo túnel até o servidor “tunelserver” que é a ponta do túnel e dali para o meu servidor Postgresql.
Embora eu tenha usado o psql por linha de comandos, eu poderia usar um cliente Postgresql mais “bonito” como PgAdmin, DBeaver, Postbird etc que funcionaria normalmente.
Você só precisa lembrar que ao invés de enviar requisições diretamente ao servidor Postgres, você as está enviando para porta do túnel que está localmente na minha estação de trabalho.
Para fechar o túnel, eu devo encerrar minha conexão com PostgreSQL, em seguida a conexão SSH que iniciou o túnel.
Finalizando
O serviço de SSH é um dos que mais utilizo no meu dia-a-dia como administrador de sistemas Linux e presumo que seja o caso de 9 entre 10 outros administradores.
Normalmente nós usamos apenas o “feijão com arroz” apenas para acessar uma máquina e dar meia dúzia de comandos, mas como se vê esta é uma ferramenta bastante sofisticada e conhecer suas funcionalidades pode ser um diferencial na hora de agilizar certas atividades.
Por enquanto é só até a próxima.