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.
* Acesse o terminal SSH como superusuário root para executar os comando de instalação e configuração.
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)
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
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
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;
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
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:
- Tutorial Debian 8 x64 com ISPConfig e NginX: Índice
- Tutorial Debian 8 x64 com ISPConfig e NginX: Servidor de Email
- Tutorial Debian 8 x64 com ISPConfig e NginX: Tabela DNS
- Tutorial Debian 8 x64 com ISPConfig e NginX: Instalação do Site
- Tutorial Debian 8 x64 com ISPConfig e NginX: Configurações Adicionais
- SMTP Relay com Postfix e SparkPost
- DigitalOcean Block Storage: Aprenda como adicionar mais espaço ao servidor
- Tutorial SSL com Lets Encrypt: Certificado gratuito e homologado para lojas virtuais
- Tutorial Debian 8 x64 com ISPConfig e NginX: Deploy do Linux
- Tutorial Debian 8 x64 com ISPConfig e NginX: ISPConfig 3
- Tutorial Debian 8 x64 com ISPConfig e NginX: Otimizando a Instalação
- Tutorial Debian 8 x64 com ISPConfig e NginX: Firewall