Tutorial Debian 8 x64 com ISPConfig e NginX: Firewall

Um servidor sem Firewall é como aguardar por um desastre anunciado, você sabe que vai acontecer e, como administrador de sistemas, tem que tomar providências para minimizar os estragos.

Durante algumas semanas deixei o meu site num servidor que a gente chama “honey pot“. Esse tipo de servidor é usado para, propositalmente, receber ataques e fazer log de tudo direcionando-os para determinados arquivos do sistema. Com essa técnica consegue-se filtrar e catalogar os tipos mais comuns de ataques, e as análises extraídas servem de base para melhorar as defesas do sistema.

Neste artigo Vamos acionar o Firewall do ISPConfig (Bastille Firewall), reconfigurar o Fail2Ban melhorando a detecção, ajustar o JailKit, acertar o NginX para mitigar ataques DDoS e, opcionalmente, instalar o Logwatch e desativar o modo recursivo do BIND.

Configurando o Firewall do Sistema

* Acesse o terminal SSH como superusuário root para executar os comando de instalação e configuração.

1 Acionando o Firewall do ISPConfig

No artigo anterior deste tutorial mostrei como adicionar as portas para o modo passivo do FTP ao firewall do ISPConfig, se você pulou aquele passo ou não prestou atenção, proceda da seguinte maneira:

Acesse: ISPConfig → Sistema → Firewall

Clique no botão “Adicionar Registro de Firewall” e confirme a tela que abrirá (se já havia adicionado o Firewall simplesmente abra a configuração existente), em seguida clique na linha de configuração e na caixa de “Portas TCP abertas” adicione “40110:40210” (portas para o FTP passivo) desta maneira:

20,21,22,25,53,80,110,143,443,587,993,995,3306,8080,8081,10000,40110:40210

* Pode-se parar o firewall do ISPConfig pelo console a qualquer momento digitando: /etc/init.d/bastille-firewall stop (isso pode ser útil caso queira testar se algum serviço externo não está conseguindo acessar o servidor por causa de alguma restrição de porta)

2 Reconfigurando o Fail2Ban e melhorando a detecção de ataques

Fail2Ban é a ferramenta responsável por detectar ataques ao servidor e automaticamente aplicar regras de ban. Alguns serviços básicos já estão configurados, mas vamos adicionar outros para minimizar riscos.

* Antes de adicionar os filtros abaixo ao Postfix, verifique se você tem um nome de servidor FQDN configurado, isso é muito importante para o correto funcionamento. Para uma melhor explicação veja o passo “Antes de começar” neste link.

2a ⇒ Edite o arquivo /etc/postfix/main.cf e altere/adicione as linhas abaixo:

#Próximo à Linha 57: Substitua a instrução "smtpd_recipient_restrictions" por esta abaixo (note que é uma linha única. e note também que no script novo de instalação há suporte a greylisting de emails e que o repositório padrão configurado para checagens é o zen.spamhaus.org. O SpamHaus é conhecido por cometer "enganos" com IPs legítimos, caso decida usar o serviço deles não precisa alterar a linha 57):

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject_unknown_recipient_domain, permit
 
#Próximo às linhas 66 e 67: Substitua as linhas com instruções "smtpd_sender_restrictions" e "smtpd_client_restrictions" pelo bloco de código abaixo:

#EDIT Out/2016: Ajuste das instruções para a nova versão do instalador do ISPConfig, mantido o bloco antigo somente para compatibilidade

smtpd_data_restrictions = reject_unauth_pipelining
smtpd_delay_reject = yes
smtpd_sender_restrictions = 
   permit_mynetworks,
   reject_non_fqdn_sender,
   reject_unknown_sender_domain,
   check_sender_access mysql:/etc/postfix/mysql-virtual_sender.cf,
   permit
smtpd_client_restrictions = 
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unknown_client_hostname,
   check_client_access mysql:/etc/postfix/mysql-virtual_client.cf,
   permit

#Para instalações a partir de Out/2016 use este bloco de código:
smtpd_data_restrictions = reject_unauth_pipelining
smtpd_delay_reject = yes
smtpd_sender_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_non_fqdn_sender,
   reject_unknown_sender_domain,
   check_sender_access mysql:/etc/postfix/mysql-virtual_sender.cf,
   permit
smtpd_client_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unknown_client_hostname,
   check_client_access mysql:/etc/postfix/mysql-virtual_client.cf,
   permit

OPCIONAL mas altamente RECOMENDÁVEL: Ainda no arquivo main.cf pode-se adicionar uma linha para garantir que somente o root e usuários de sistema consigam enviar emails através de scripts no servidor. Isso é muito útil para revendas de sites que não conseguem controlar os scripts dos programadores, ou ainda em casos quando hackers injetam um script PHP no site que dispara emails de SPAM. Adicionando esta linha somente o root e contas autenticadas, que tenham caixa de email, poderão enviar.

authorized_submit_users = !www, root, static:all

2b ⇒ Edite o arquivo /etc/postfix/header_checks e adicione a linha abaixo:

/^X-Spam-Level: \*{15,}.*/ DISCARD

2c ⇒ Edite o arquivo /etc/fail2ban/jail.local apagando todo o conteúdo e substituindo por este abaixo:

[DEFAULT]

# Adicione IPs internos e o DNS do Google na lista de redes confiaveis
ignoreip = 127.0.0.0/8 10.0.0.0/8 8.8.8.8 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 104.16.0.0/12 108.162.192.0/18 131.0.72.0/22 141.101.64.0/18 162.158.0.0/15 172.64.0.0/13 173.245.48.0/20 188.114.96.0/20 190.93.240.0/20 197.234.240.0/22 198.41.128.0/17 199.27.128.0/21
# Se você utiliza o ManageWP terá que adicionar os IPs da rede deles na WhiteList também (após o último IP na lista acima acrescente um espaço em branco e cole estes endereços):
# 192.155.230.147 174.37.199.34 89.216.23.220 77.105.2.42 77.105.2.43 77.105.2.44 77.105.2.45 77.105.2.46 77.105.2.47
# E para a CloudFlare adicione os seguintes IPs
# 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 104.16.0.0/12 108.162.192.0/18 131.0.72.0/22 141.101.64.0/18 162.158.0.0/15 172.64.0.0/13 173.245.48.0/20 188.114.96.0/20 190.93.240.0/20 197.234.240.0/22 198.41.128.0/17 199.27.128.0/21

# Antes de adicionar jails configure valores padrão de ação e ban (pode-se alterar cada jail individualmente)
# Os valores abaixo sao exemplos e estao em segundos: bantime (600 segundos); findtime (300 segundos); maxretry (4 tentativas):
bantime = 600
findtime = 300
maxretry = 4

#Altere o modo de detecção para o Debian reconhecer as alterações de arquivo corretamente:
backend = polling

#
# JAILS
#
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log

[ssh-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 6

[dropbear]
enabled = true
port = ssh
filter = dropbear
logpath = /var/log/auth.log
maxretry = 6

# Monitora as tentativas de autenticação para diretórios protegidos no NginX
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log

[pure-ftpd]
enabled = true
port = ftp,ftp-data,ftps,ftps-data
filter = pure-ftpd
logpath = /var/log/syslog
maxretry = 6

[pureftpd]
enabled = true
port = ftp
filter = pureftpd
logpath = /var/log/syslog
maxretry = 6

[postfix]
enabled = true
port = smtp,ssmtp,submission
filter = postfix
logpath = /var/log/mail.log
bantime = 1800
findtime = 600
maxretry = 3

[sasl]
enabled = true
port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s
filter = postfix-sasl
logpath = /var/log/mail.log

[dovecot]
enabled = true
port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log

#Bloqueando ataques DDoS no BIND9, servidor DNS. Note que mudamos o arquivo padrao de log e tambem trocamos o 
#action para hostsdeny, isso e necessario pois ataques ao DNS devem ser barrados logo na entrada do servidor
[named-refused-udp]
enabled = true
port = domain,953
protocol = udp
filter = named-refused
#logpath = /var/log/named/security.log
logpath = /var/log/daemon.log
action = hostsdeny
bantime = 1800
findtime = 300
maxretry = 10

[named-refused-tcp]
enabled = true
port = domain,953
protocol = tcp
filter = named-refused
#logpath = /var/log/named/security.log
logpath = /var/log/daemon.log
action = hostsdeny
bantime = 1800
findtime = 300
maxretry = 10

2d ⇒ Edite o arquivo /etc/fail2ban/filter.d/named-refused.conf e na linha 40, logo acima de “# DEV Notes:” digite:

ignoreregex = 

# Note que é um parâmetro sem valor, somente para não dar erro na inicialização do Fail2Ban. O mais comum é "WARNING 'ignoreregex' not defined in 'Definition'. Using default one"

2e ⇒ Edite o arquivo /etc/fail2ban/filter.d/postfix.conf e adicione as linhas em negrito abaixo (Isso é MUITO IMPORTANTE pois há um bug de detecção no filtro original, para identar as linhas use espaços normais):

failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$
^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[<HOST>\]:?$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 :*$
^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 454 4\.7\.1 .*$
reject: RCPT from (.*)\[<HOST>\]: 550 5.1.1
reject: RCPT from (.*)\[<HOST>\]: 450 4.7.1
reject: RCPT from (.*)\[<HOST>\]: 554 5.7.1
reject: RCPT from unknown\[<HOST>\]: 454 4.7.1
warning: Illegal address syntax from unknown\[<HOST>\]
warning: non-SMTP command from unknown\[<HOST>\]:

2f ⇒ Reinicie o postfix e o fail2ban

root# /etc/init.d/fail2ban restart

root# /etc/init.d/postfix restart

• Caso queira fazer experiências com jails no Fail2Ban use o comando abaixo, após reiniciar o serviço ele mostrará erros e avisos:

root# /etc/init.d/fail2ban status
3 Ajuste do JailKit

O JailKit permite configurar usuários de site em chroot, ou seja, em seções enjauladas. Caso um hacker consiga entrar no servidor através de algum exploit ele não terá acesso aos arquivos externos ao site.

• Edite o arquivo /usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh e adicione esta linha ao final (note que estamos modificando um script do próprio ISPConfig, caso faça um upgrade do painel futuramente verifique este arquivo novamente):

chmod g-w $CHROOT_HOMEDIR/bin

* Isso serve para que os usuários em chroot consigam fazer login SSH no servidor. Há um “bug” na criação do diretório bin dos sites quando adicionados pelo ISPConfig, se não consertarmos este bug os usuários em jail não conseguem fazer login (a seção SSH simplesmente desaparece após conectar)

* * Caso já tenha adicionado um usuário SSH de site antes de fazer a alteração acima então altere a permissão do subdiretório /bin dentro do espaço de site adicionado pelo ISPConfig para 0755. Por exemplo, digamos que o seu site seja meusite.com.br, então o caminho desse diretório /bin será: /var/www/meusite.com.br/bin

* * * Os erros encontrados no arquivo de log são parecidos com estes:

Dec 8 13:52:36 debian8 jk_chrootsh[29365]: path /var/www/clients/client0/web1/bin/ is group writable

Dec 8 13:52:36 debian8 jk_chrootsh[29365]: abort, /var/www/clients/client0/web1 is not a safe jail, check ownership and permissions

• Edite o arquivo /etc/jailkit/jk_init.ini e adicione ao final da linha 71 em [basicshell] (dependendo da distribuição Linux que você instalou essa linha poderá ser a 74 em [paths]). No parâmetro “executables=” adicione, ao final da linha, os comandos zip e unzip (note as vírgulas), assim os usuários em Jail de site poderão usar os comandos:

, /usr/bin/zip, /usr/bin/unzip

E por último reinicie o Jailkit:

> /etc/init.d/jailkit restart
4 Mitigando ataques DDoS ao NginX

Para a segurança e estabilidade do servidor este passo é de grande importância. Faremos o bloqueio da página padrão do NginX exibida pelo número IP e a limitação de conexões ao servidor por IP. Faremos as alterações primeiro porque acessar o servidor na porta 80 pelo número IP não ajuda em nada, só serve para ver se o NginX está funcionando, mas se ele não estivesse online nem mesmo o ISPConfig abriria.

E também porque deixar o acesso livre à página default pelo número IP é uma grande brecha para ataques DDoS. Mesmo se você configurar os domínios pela CloudFlare alguém pode descobrir o número IP do servidor e ordenar um ataque de negação de serviço ao VPS pelo IP. Por isso mostrarei abaixo como usar uma instrução especial do NginX para “interromper” a conexão para acessos diretos.

E por último o limite de acessos por IP mitiga em muito ataques ao servidor, neste caso são conexões aos sites e não ao IP do servidor.

Note que os demais serviços e páginas continuarão funcionando normalmente após as alterações.

  • Seguindo o nosso tutorial você deve ter notado que digitando o IP do servidor abre uma página padrão do Apache, isso acontece porque o script instalador não alterou o caminho da página padrão. Se quiser simplesmente modificá-la edite o arquivo /etc/nginx/sites-enabled/default e na linha 30 altere para “root /usr/share/nginx/html;“, e em seguida reinicie o nginx. Ou se preferir, siga os passos abaixo para desativá-la completamente.

4a ⇒ OPCIONAL: Altere o arquivo /etc/nginx/sites-enabled/default:

#Comente as linhas 30, 33 e 40 colocando um sinal de "#" no início, e adicione a linha 36 retornando a instrução 444

#root /usr/share/nginx/html;
 
# Add index.php to the list if you are using PHP
#index index.html index.htm index.nginx-debian.html;

server_name _;
return 444;
location / {
    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    #try_files $uri $uri/ =404;
}

4b ⇒ Altere o arquivo /etc/nginx/nginx.conf:

#Adicionando estas linhas no arquivo de configuração do NginX limitará o número de conexões ativas por número IP aos sites mitigando ataques DDoS (note que mesmo adicionando as linhas ainda será necessário adicionar as diretivas por site conforme passo 4d)

#Logo no início do bloco "http {" do arquivo nginx.conf adicione as linhas em vermelho conforme mostrado abaixo

http {

   ##
   # Basic Settings
   ##

#Habilite a linha 22 se quiser "ocultar" a versão do NginX, algumas ferramentas que analisam vulnerabilidades mostram uma mensagem como esta: "Server signature: HTTP response contains the version of the web server exposing its vulnerabilities."  

server_tokens off;

limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

#Se você usa a CloudFlare o serviço deles faz com que os IPs nos logs de acesso aparecam somente os deles, adicione as seguintes linhas para mostrar o IP real de acesso:

set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
 
sendfile on;
tcp_nopush on;

4c ⇒ Reinicie o NginX:

root# /etc/init.d/nginx restart

Caso tenha optado pelo passo 4a tente acessar a página novamente pelo número IP, note que exibirá uma mensagem de que “Nenhum dado foi recebido” (ERR_EMPTY_RESPONSE). Isso acontece porque modificamos a diretiva return para Status 444 que simplesmente interrompe e fecha a conexão com o navegador cliente impossibilitando ataques de negação de serviço.

4d ⇒ Após reiniciar o NginX adicione estas diretivas na caixa de diretivas NginX de cada site no ISPConfig (caso tente adicionar as diretivas sem editar o arquivo nginx.conf e reiniciar o serviço os sites ficarão offline):

ATENÇÃO: Em alguns sites leitores relatam problemas com CSS e imagens falham ao carregar. Em sites WordPress com Revolution Slider causará erros de CSS deixando de exibir alguns componentes como por exemplo a logo do site. O erro mais comum que aparece nos logs é este: “You have some jquery.js library include that comes after the revolution files js include“. A documentação para as regras abaixo é um pouco confusa mas consegui contornar o problema, veja o edit:

EDIT (março/2016): Após vários testes e com a ajuda do leitor Dan Rezende isolei o problema e modifiquei as regras abaixo, em especial a linha 4 (limit_req zone). Foi retirado o parâmetro nodelay e aumentado o burst de 10 para 20. Desta maneira você conseguirá manter as regras anti-DDoS sem afetar o CSS do site.

#Diretivas NginX por site para mitigar ataques DDoS
limit_conn conn_limit_per_ip 6;
limit_conn_log_level warn;
limit_conn_status 444;

#Caso o CSS do site nao carregue corretamente aumente o burst na proxima linha gradativamente ate solucionar
limit_req zone=req_limit_per_ip burst=20;
limit_req_log_level warn;
limit_req_status 444;
5 OPCIONAL: Instalação do Logwatch

Logwatch é uma ferramenta que verifica os arquivos de log diariamente e cria um relatório das principais atividades como ataques e acessos, enviando o relatório por email se configurado. Uma melhor explicação pode ser encontrada neste link.

5a ⇒ Baixe e instale o Logwatch:

root# apt-get -y install logwatch

5b ⇒ Edite o arquivo /usr/share/logwatch/default.conf/logwatch.conf:

#Linha 35 altere para que o relatorio seja enviado por email
Output = mail

#Linha 37 altere o formato para HTML facilitando a leitura
Format = html

#Linha 44 configure para qual email o relatorio será enviado (pode ser uma conta interna ou externa)
MailTo = [email protected]

#Linha 77 altere o nivel de detalhes para Medio que é suficiente
Detail = Med

5c ⇒ Faça um teste. Não é necessário reiniciar nenhum serviço, digite o comando abaixo (um email será entregue com o relatório do dia anterior e os próximos relatórios serão enviados automaticamente pois uma tarefa foi adicionada ao Cron durante a instalação):

root# logwatch
6 Fix para erros do named nos arquivos de log

Este passo é opcional e somente se você não pretende criar zonas DNS diretamente no servidor, como eu costumo ensinar nos tutoriais.

Durante a instalação e testes me deparei com um flood de mensagens de erro infinitas no arquivo /var/log/daemon.log, que são gravadas pelo serviço named (BIND9) e parecidas com esta:

Dec 18 17:32:54 debian8 named[2143]: client 66.1.64.135#11696 (dominio_qualquer.com): query (cache) 'dominio_qualquer.com/A/IN' denied

Para sanar o flood nos logs é necessário desativar o modo recursivo do BIND.

Se quiser desativá-lo edite o arquivo /etc/bind/named.conf.options e adicione estas linhas antes de fechar o bloco “options” (*adicione somente as 3 linhas em negrito):

    auth-nxdomain no; # conform to RFC1035
    listen-on-v6 { any; };
    recursion no;
    additional-from-auth no;
    additional-from-cache no;
};

• Reinicie o BIND9:

root# /etc/init.d/bind9 restart

• Verifique também que nos arquivos de log algumas datas estão erradas. Isso acontece porque alteramos o timezone anteriormente. Reinicie o servidor para acertar isso:

root# shutdown -r now

Índice do Tutorial:

©2014-2018 Fator Binário - Todos os direitos reservados

Fazer login com suas credenciais

ou    

Esqueceu sua senha?

Create Account