De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Alta disponibilidade e segurança com Nginx e Naxsi

Colaboração: Alexandro Silva

Data de Publicação: 07 de maio de 2013

Além de servir como um servidor web leve e versátil o Nginx é muito poderoso como proxy-reverso. Também podemos utilizá-lo como um sistema de balanceamento de carga de excelente performance.

Neste post mostrarei como criar um ambiente não só de balanceamento de carga com failover, como também irei incrementá-lo com uma camada de segurança usando o WAF Naxsi.

Instalação

  aptitude install nginx-naxsi

Habilitar o balanceamento de carga é muito simples bastando para isso incluir a diretiva upstream no vhost do site. Ele possibilita diversos tipos de configurações:

Esse é caso mais simples onde os backends serão tratados como um único host.

  upstream acme {
         server 192.168.0.2;
         server 192.168.0.3;
         server 192.168.0.4; 
         }
  

A entidade acme agora será tratada como upstream servindo de referência para o parâmetro proxy_pass como mostra o exemplo abaixo:

  server {
   listen acme:80;
   access_log /var/log/nginx/nginx.log;
  
   location / {
     proxy_pass http://acme;
   }
  }

Para o cliente sempre manter a conexão no mesmo backend utiliza-se o parâmetro hash_ip.

  upstream acme {
         hash_ip;
         server 192.168.0.2;
         server 192.168.0.3;
         server 192.168.0.4; 
         }
  

Prioridade e Failover

Para definir a prioridade de cada backend utiliza-se o parâmetro weight o valor padrão é 1. No exemplo abaixo as 3 primeiras requisições serão enviadas para o servidor 192.168.0.2, a 4a e 5a para o 192.168.0.3 e a 6a. para o 192.168.0.4.

  upstream acme {
         hash_ip;
         server 192.168.0.2 weight=3;
         server 192.168.0.3 weight=2;
         server 192.168.0.4; 
         }
  

O failover é habilitando usando os parâmetros max_fails define o total de falhas na requisição e fail_timeout define o intervalo de tempo entre as falhas a partir dai a requisição é enviada para o próximo backend.

  upstream acme {
         hash_ip;
         server 192.168.0.2 max_fails=3  fail_timeout=30s;
         server 192.168.0.3;
         server 192.168.0.4; 
         server 192.168.0.5 down;
         }

O parâmetro down é utilizado quando um backend está inacessível.

Naxsi

O Naxsi é um Web Application Firewall para o Nginx criado pelo Thibault Koechlin. Uma das grandes vantagens é que ele segue o modelo positivo de segurança aprendendo como a aplicação funciona e criando regras baseadas no comportamento (whitelist-based), ele não utiliza assinatura dos ataques (blacklist-based) como um AV por exemplo.

Habilitar esse WAF é muito simples bastando apenas adicionar a seguinte linha no arquivo nginx.conf:

  include /etc/nginx/naxsi_core.rules;

E no arquivo do vhost

     location / {
      include    /etc/nginx/naxsi.rules;
      proxy_pass  http://acme/;
      ...
      }
  
  #Naxsi Learning Mode 
  
   location /RequestDenied {
    proxy_pass http://127.0.0.1:4242;
    }
    

A opção Learning Mode permite ao Naxsi aprender o funcionamento da aplicação criando novas regras de whitelist.

Outra ferramenta bastante útil é o nx_util, ele é um parser que lê o arquivo de erro dos sites, atualiza uma base de dados sqlite, gera novas regras de whitelist e exporta os dados para a tela ou para um arquivo html muito bacana.

  wget https://naxsi.googlecode.com/files/nx_util-0.3.tgz``
  tail /var/log/nginx/acme.error.log | nx_util.py -d naxsi_ui -l -i -o -H /var/www/acme.html``

Visualizando os dados na console

  tail /var/log/nginx/naxsi.error.log | nx_util.py -d naxsi_ui -l -i -o``
  Using stdin.
  Committing to db ...
  # Optimized Rules Suggestion #
  # total_count:1 (50.0%), peer_count:1 (100.0%) | simple quote
  BasicRule wl:1306 "mz:$URL:/vulnerabilities/sqli/|$ARGS_VAR:id";
  # total_count:1 (50.0%), peer_count:1 (100.0%) | simple quote
  BasicRule wl:1013 "mz:$URL:/vulnerabilities/sqli/|$ARGS_VAR:id";

OBS1: Para acessar o html utilizei o lighttpd configurando-o na porta 8080.

OBS2: Para evitar problemas com o Wordpress existem regras específicas que podem ser encontradas neste blog

Abaixo seguem os arquivos de configuração completos:

Nginx

/etc/nginx/nginx.conf

  user  nginx;
  worker_processes  4;
  
  error_log  /var/log/nginx/error.log warn;
  pid        /var/run/nginx.pid;
  
  
  events {
     worker_connections  1024;
  }
  
  
  http {
     include       /etc/nginx/mime.types;
     default_type  application/octet-stream;
  
     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';
  
     access_log  /var/log/nginx/access.log  main;
  
     sendfile        on;
  
     tcp_nodelay on;
  
     gzip  on;
     gzip_disable "MSIE [1-6]\.(?!.*SV1)";
  
     include /etc/nginx/conf.d/*.conf;
     include /etc/nginx/sites-enabled/*;
  
  # Protecao contra DoS
     client_body_buffer_size 1K;
     client_header_buffer_size 1k;
     client_max_body_size 2M;
     large_client_header_buffers 2 1k;
     client_body_timeout 10;
     client_header_timeout 10;
     keepalive_timeout 5 5;
     send_timeout 10;
  
     server_tokens off;
  
     proxy_set_header   Host             $host;
     proxy_set_header   X-Real-IP        $remote_addr;
     proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
  
     proxy_max_temp_file_size 0;
  
     proxy_connect_timeout      90;
     proxy_send_timeout         90;
     proxy_read_timeout         90;
  
     proxy_buffer_size          4k;
     proxy_buffers              4 32k;
     proxy_busy_buffers_size    64k;
     proxy_temp_file_write_size 64k;
     proxy_cache_methods GET HEAD POST;
  
  # Naxsi WAF
  
     include /etc/nginx/naxsi_core.rules;
  
  }

Vhost

/etc/nginx/sites-available/acme

  upstream acme {
         hash_ip;
         server 192.168.0.2 weight=5;
         server 192.168.0.3 max_fails=3  fail_timeout=30s;
         server 192.168.0.4; 
         }
  
  server {
     listen       80;
     server_name  acme;
  
     access_log  /var/log/nginx/acme.access.log  main;
     error_log  /var/log/nginx/acme.error.log;
  
     location / {
      include    /etc/nginx/naxsi.rules;
      proxy_pass  http://acme/;
      proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
      proxy_redirect off;
      proxy_buffering off;
      proxy_set_header        Host            $host;
      proxy_set_header        X-Real-IP       $remote_addr;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;	
  }
  
  #Naxsi Learning Mode 
  
   location /RequestDenied {
    proxy_pass http://127.0.0.1:4242;
    }
  }

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Alexandro Silva