Configurando Acesso Seguro em Múltiplos Servidores

Tabela de Conteúdo

O SSH (Secure Shell) é a ferramenta padrão para acesso remoto a servidores Linux. Porém, a configuração padrão do SSH não é suficiente para ambientes de produção, especialmente quando expostos à internet. Ataques comuns incluem brute force em senhas, port scanning e tentativas de exploração de vulnerabilidades conhecidas.

Neste post, vamos configurar um SSH seguro e automatizar essas configurações em múltiplos servidores usando Ansible.

Backup e Preparação

O arquivo que iremos trabalhar e efetuar as alterações é o

/etc/ssh/sshd_config

Então antes de qualquer alteração, sempre faça backup do arquivo de configuração do SSH:

$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +%Y%m%d)

Mantenha sempre uma sessão SSH aberta durante as alterações. Se algo der errado, você ainda terá acesso ao servidor.

Desabilitando Autenticação por Senha

A autenticação por senha é vulnerável a ataques de brute force. A melhor prática é usar apenas autenticação por chave SSH.

PasswordAuthentication no
PubkeyAuthentication yes

Após alterar, recarregue o serviço SSH:

$ sudo systemctl reload sshd

Bloqueando Login Root

O acesso direto como root via SSH é uma prática insegura. Desabilite e crie um usuário alternativo com privilégios sudo:

PermitRootLogin no

Crie um usuário alternativo com sudo:

$ sudo useradd -m -s /bin/bash admin
$ sudo passwd admin
$ sudo usermod -aG sudo admin

Restringindo Usuários e IPs

Limite quais usuários e de onde podem se conectar:

AllowUsers admin usuario1 usuario2

AllowGroups ssh-users

Match Address 192.168.1.0/24
    AllowUsers admin

Gerenciamento de Chaves SSH

Gerando Par de Chaves

No seu computador local, gere um par de chaves SSH:

$ ssh-keygen -t ed25519 -C "[email protected]"

Ou use RSA (se ed25519 não estiver disponível):

$ ssh-keygen -t rsa -b 4096 -C "[email protected]"

Copiando Chave para o Servidor

Use o ssh-copy-id para copiar sua chave pública:

$ ssh-copy-id -p 22 [email protected]

Ou manualmente:

$ cat ~/.ssh/id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Estrutura do Diretório .ssh

No servidor, configure permissões corretas:

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh/id_ed25519.pub

Configuração do Cliente SSH

Simplifique conexões usando o arquivo ~/.ssh/config:

Host servidor-producao
    HostName 192.168.1.100
    Port 22
    User admin
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60
    ServerAliveCountMax 3

Host servidor-homolog
    HostName 10.0.0.50
    User admin
    ProxyJump jump-host
    IdentityFile ~/.ssh/id_ed25519

Agora você pode conectar simplesmente com:

$ ssh servidor-producao

Automação com Ansible

Para aplicar essas configurações em múltiplos servidores, vamos criar um playbook Ansible.

Estrutura do Projeto

ansible-ssh-hardening/
├── playbook.yml
├── templates/
│   └── sshd_config.j2
└── group_vars/
    └── all.yml

Playbook Ansible

Crie o arquivo playbook.yml:

---
- name: SSH Hardening
  hosts: all
  become: yes
  vars:
    ssh_port: 22
    ssh_allowed_users:
      - admin
      - usuario1
    ssh_allowed_groups:
      - ssh-users

  tasks:
    - name: Backup sshd_config
      copy:
        src: /etc/ssh/sshd_config
        dest: /etc/ssh/sshd_config.backup.{{ ansible_date_time.epoch }}
        remote_src: yes

    - name: Deploy hardened sshd_config
      template:
        src: sshd_config.j2
        dest: /etc/ssh/sshd_config
        owner: root
        group: root
        mode: '0644'
      notify: restart sshd

    - name: Ensure SSH service is running
      systemd:
        name: sshd
        state: started
        enabled: yes

  handlers:
    - name: restart sshd
      systemd:
        name: sshd
        state: restarted

Template sshd_config.j2

Crie o template templates/sshd_config.j2:

Port {{ ssh_port }}

PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

PermitRootLogin no

{% if ssh_allowed_users is defined %}
AllowUsers {{ ssh_allowed_users | join(' ') }}
{% endif %}

{% if ssh_allowed_groups is defined %}
AllowGroups {{ ssh_allowed_groups | join(' ') }}
{% endif %}

ClientAliveInterval 300
ClientAliveCountMax 2

SyslogFacility AUTH
LogLevel VERBOSE

Executando o Playbook

$ ansible-playbook -i inventory playbook.yml

Validação e Testes

Antes de aplicar mudanças, valide a configuração:

$ sudo sshd -t

Se não houver erros, a configuração está sintaticamente correta.

Simples assim! :)