O Nginx é um servidor web/proxy reverso leve e de alto desempenho e proxy de e-mail (IMAP/POP3). Ele é executado em UNIX, GNU/Linux, variantes BSD, Mac OS X, Solaris e Microsoft Windows. De acordo com a Netcraft, 13,50% de todos os domínios na Internet usam o servidor web Nginx. Hoje, trazemos as melhores práticas de segurança para o servidor Nginx.
Ele é um dos poucos servidores escritos para solucionar o problema do C10K. Ao contrário dos servidores tradicionais, o Nginx não depende de threads para lidar com pedidos. Em vez disso, ele usa uma arquitetura muito mais escalável baseada em eventos (assíncrona). O Nginx alimenta vários sites de alto tráfego, como WordPress, Hulu, Github e SourceForge.
Arquivos de Configuração Padrão e Porta Nginx
- /usr/local/nginx/conf/ ou /etc/nginx/ – Diretório de configuração do Nginx
- /usr/local/nginx/conf/nginx.conf – Principal arquivo de configuração
- /usr/local/nginx/html/ ou /var/www/html – Localização padrão dos arquivos
- /usr/local/nginx/logs/ ou /var/log/nginx – Localização padrão dos logs
- Porta HTTP padrão: TCP 80
- Porta HTTPS padrão: TCP 443
Você pode testar as mudanças de configuração com o seguinte comando:
/usr/local/nginx/sbin/nginx -t
ou
nginx -t
Para carregar as mudanças de configuração:
/usr/local/nginx/sbin/nginx -s reload
Ou
nginx -s reload
Para parar o servidor, digite:
/usr/local/nginx/sbin/nginx -s stop
Ou
nginx -s stop
Melhores práticas de segurança para o servidor Nginx
1 – Habilite o SELinux
O Linux com segurança aprimorada (SELinux) é um recurso de kernel do Linux que fornece um mecanismo para suportar políticas de segurança de controle de acesso que oferecem uma ótima proteção. Pode interromper muitos ataques antes que seu sistema seja infectado. Veja como ativar o SELinux para sistemas baseados em CentOS/RHEL.
Faça um bloqueio booleano
Para proteger a máquina, e como parte das melhores práticas de segurança para Nginx, veja as configurações que estão configuradas em ‘on’ e mude para ‘off’ se elas não se aplicam à sua configuração com a ajuda do comando getsebool. Defina o SE Linux corretamente para manter a funcionalidade e a proteção.
Execute o comando getsebool -a e bloqueie o sistema:
getsebool -a | less
getsebool -a | grep off
getsebool -a | grep on
2 – Permitir privilégios mínimos por meio de opções de montagem
Servir todas as suas páginas da web html e php através de partições separadas. Por exemplo, crie uma partição chamada /dev/sda5 e monte no /nginx. Certifique-se de que /nginx esteja montado com permissões noexec, nodev e nosetuid. Aqui está a minha entrada /etc/fstab para montagem /nginx:
LABEL=/nginx /nginx ext3 defaults,nosuid,noexec,nodev 1 2
Note que você precisa criar uma partição usando os comandos fdisk e mkfs.ext3.
3 – Hardening no arquivo /etc/sysctl.conf
Você pode controlar e configurar configurações de kernel e rede do Linux através do arquivo /etc/sysctl.conf.
# Avoid a smurf attack
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Turn on protection for bad icmp error messages
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Turn on syncookies for SYN flood attack protection
net.ipv4.tcp_syncookies = 1
# Turn on and log spoofed, source routed, and redirect packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# No source routed packets here
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Turn on reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Make sure no one can alter the routing tables
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# Don't act as a router
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Turn on execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# Tuen IPv6
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
# Optimization for port usefor LBs
# Increase system file descriptor limit
fs.file-max = 65535
# Allow for more PIDs (to reduce rollover problems); may break some programs 32768
kernel.pid_max = 65536
# Increase system IP port limits
net.ipv4.ip_local_port_range = 2000 65000
# Increase TCP max buffer size setable using setsockopt()
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
# Increase Linux auto tuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high BDP paths
# Tcp Windows etc
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1
4 – Como remover todos os módulos Nginx indesejados
Você precisa minimizar o número de módulos compilados diretamente no binário nginx. Isso minimiza o risco limitando os recursos permitidos pelo servidor web. Você pode configurar e instalar o nginx usando apenas os módulos necessários. Por exemplo, para desativar o módulo SSI e autoindex, você pode digitar:
./configure --without-http_autoindex_module --without-http_ssi_module
make
Digite o seguinte comando para ver quais módulos podem ser ativados ou desativados ao compilar o servidor nginx:
./configure --help | less
Desative os módulos nginx que você não precisa.
Alterar o cabeçalho da versão Nginx (Opcional)
Edite src/http/ngx_http_header_filter_module.c, digite:
vi +48 src/http/ngx_http_header_filter_module.c
Ache a linha:
static char ngx_http_server_string[] = "Server: nginx" CRLF; static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
E mude para:
static char ngx_http_server_string[] = "Server: Ninja Web Server" CRLF; static char ngx_http_server_full_string[] = "Server: Ninja Web Server" CRLF;
Salve e feche o arquivo. Agora, você pode compilar o servidor. Adicione o seguinte no nginx.conf para desligar o número da versão nginx exibido em todas as páginas de erro geradas automaticamente:
server_tokens off
5 – Use mod_security (somente para servidores Apache no backend)
O mod_security fornece um firewall de nível de aplicativo para o Apache. Instale mod_security para todos os servidores web do Apache. Isso irá parar muitos ataques de injeção.
6 – Instale a política SELinux para proteger o servidor Web Nginx
Por padrão, o SELinux não protegerá o servidor web nginx. No entanto, você pode instalar e compilar a proteção da seguinte maneira. Primeiro, instale o suporte de tempo de compilação SELinux necessário:
yum -y install selinux-policy-targeted selinux-policy-devel
Baixe as diretivas SELinux direcionadas para endurecer o servidor web nginx em servidores Linux da página inicial do projeto:
cd /opt
wget http://downloads.sourceforge.net/project/selinuxnginx/se-ngix_1_0_10.tar.gz
Descompacte o arquivo:
tar -zxvf se-ngix_1_0_10.tar.gz
Compile o arquivo:
cd se-ngix_1_0_10/nginx
make
Exemplo de saída do Terminal:
sempreupdate@lab:$ Compiling targeted nginx module /usr/bin/checkmodule: loading policy configuration from tmp/nginx.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 6) to tmp/nginx.mod Creating targeted nginx.pp policy package rm tmp/nginx.mod.fc tmp/nginx.mod
Instale o módulo nginx.pp SELinux resultante:
/usr/sbin/semodule -i nginx.pp
7 – Acesso restrito com Firewall baseado em Iptables
O seguinte script de firewall bloqueia tudo e só permite:
- Solicitações HTTP (Porta TCP 80) recebidas
- Solicitações de ping ICMP recebidas
- Pedidos de saída ntp (porta 123)
- Pedidos de saída smtp (TCP porta 25)
!/bin/bash IPT="/sbin/iptables" #### IPS ###### # Get server public ip SERVER_IP=$(ifconfig eth0 | grep 'inet addr:' | awk -F'inet addr:' '{ print $2}' | awk '{ print $1}') LB1_IP="204.54.1.1" LB2_IP="204.54.1.2" # Do some smart logic so that we can use damm script on LB2 too OTHER_LB="" SERVER_IP="" [[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB="$LB2_IP" || OTHER_LB="$LB1_IP" [[ "$OTHER_LB" == "$LB2_IP" ]] && OPP_LB="$LB1_IP" || OPP_LB="$LB2_IP" ### IPs ### PUB_SSH_ONLY="122.xx.yy.zz/29" #### FILES ##### BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt SPOOFIP="127.0.0.0/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 0.0.0.0/8 240.0.0.0/4 255.255.255.255/32 168.254.0.0/16 224.0.0.0/4 240.0.0.0/5 248.0.0.0/5 192.0.2.0/24" BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v "^#|^$" ${BLOCKED_IP_TDB}) ### Interfaces ### PUB_IF="eth0" # public interface LO_IF="lo" # loopback VPN_IF="eth1" # vpn / private net ### start firewall ### echo "Setting LB1 $(hostname) Firewall…" # DROP and close everything $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP # Unlimited lo access $IPT -A INPUT -i ${LO_IF} -j ACCEPT $IPT -A OUTPUT -o ${LO_IF} -j ACCEPT # Unlimited vpn / pnet access $IPT -A INPUT -i ${VPN_IF} -j ACCEPT $IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT # Drop sync $IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP # Drop Fragments $IPT -A INPUT -i ${PUB_IF} -f -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP # Drop NULL packets $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " NULL Packets " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP # Drop XMAS $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " XMAS Packets " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # Drop FIN packet scans $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " Fin Packets Scan " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP # Log and get rid of broadcast / multicast and invalid $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j LOG --log-prefix " Broadcast " $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j DROP $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j LOG --log-prefix " Multicast " $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j DROP $IPT -A INPUT -i ${PUB_IF} -m state --state INVALID -j LOG --log-prefix " Invalid " $IPT -A INPUT -i ${PUB_IF} -m state --state INVALID -j DROP # Log and block spoofed ips $IPT -N spooflist for ipblock in $SPOOFIP do $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG --log-prefix " SPOOF List Block " $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP done $IPT -I INPUT -j spooflist $IPT -I OUTPUT -j spooflist $IPT -I FORWARD -j spooflist # Allow ssh only from selected public ips for ip in ${PUB_SSH_ONLY} do $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} --destination-port 22 -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} --sport 22 -j ACCEPT done # allow incoming ICMP ping pong stuff $IPT -A INPUT -i ${PUB_IF} -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -m limit --limit 30/sec -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT # allow incoming HTTP port 80 $IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p tcp --sport 80 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT # allow outgoing ntp $IPT -A OUTPUT -o ${PUB_IF} -p udp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p udp --sport 123 -m state --state ESTABLISHED -j ACCEPT # allow outgoing smtp $IPT -A OUTPUT -o ${PUB_IF} -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT ### add your other rules here #### ####################### # drop and log everything else $IPT -A INPUT -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " DEFAULT DROP " $IPT -A INPUT -j DROP exit 0
8 – Controlando ataques de estouro de buffer
Edite nginx.conf e defina as limitações do tamanho do buffer para todos os clientes.
vi /usr/local/nginx/conf/nginx.conf
Edite e defina as limitações do tamanho do buffer para todos os clientes da seguinte maneira:
Start: Size Limits & Buffer Overflows ## client_body_buffer_size 1K; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k; ## END: Size Limits & Buffer Overflows
Onde:
- client_body_buffer_size 1k: (o padrão é 8k ou 16k) A diretiva específica o tamanho do buffer do corpo do pedido do cliente.
- client_header_buffer_size 1k: A diretiva define o tamanho do buffer de cabeçalho para o cabeçalho da solicitação do cliente. Para a grande maioria dos pedidos, um tamanho de buffer de 1K é suficiente. Aumente isso se você tiver um cabeçalho personalizado ou um grande cookie enviado pelo cliente (por exemplo, cliente wap).
- client_max_body_size 1k: A diretiva atribui o tamanho máximo aceito do pedido do cliente, indicado pela linha Content-Length no cabeçalho da solicitação. Se o tamanho for maior, o cliente obtém o erro “Request Entity Too Large” (413). Aumente isso quando você estiver recebendo uploads de arquivos através do método POST.
- large_client_header_buffers 21k: A diretiva atribui o número e tamanho máximo de buffers para cabeçalhos grandes para ler a partir do pedido do cliente. Por padrão, o tamanho de um buffer é igual ao tamanho da página, dependendo da plataforma, seja 4K ou 8K, se no final da conexão de solicitação de trabalho converte para o estado keep-alive, esses buffers serão liberados. 2x1k aceitará URI de dados de 2kB. Isso também ajudará a combater erros e ataques DoS.
Você também precisa controlar os tempos limite para melhorar o desempenho do servidor e reduzir os clientes. Edite-o da seguinte maneira:
Start: Timeouts ## client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10; ## End: Timeouts
- client_body_timeout 10: A diretiva define o tempo limite de leitura para o corpo de solicitação do cliente. O tempo limite é configurado apenas se um corpo não for inserido em um readstep. Se depois deste tempo o cliente não envia nada, o nginx retorna o erro “Solicitar tempo limite” (408). O padrão é 60.
- client_header_timeout 10: A diretiva atribui tempo limite com a leitura do título do pedido do cliente. O tempo limite é configurado somente se um cabeçalho não for obtido em um passo de leitura. Se depois deste tempo o cliente não envia nada, o nginx retorna o erro “Solicitar tempo limite” (408).
- keepalive_timeout 5 5: O primeiro parâmetro atribui o tempo limite para conexões keep-alive com o cliente. O servidor fechará conexões após esse tempo. O segundo parâmetro opcional atribui o valor do tempo no cabeçalho Keep-Alive: timeout = tempo da resposta. Este cabeçalho pode convencer alguns navegadores para fechar a conexão, de modo que o servidor não precisa. Sem esse parâmetro, o nginx não envia um cabeçalho Keep-Alive (embora isso não seja o que faz uma conexão “keep-alive”).
- send_timeout 10: A diretiva atribui tempo limite de resposta ao cliente. O tempo limite é estabelecido não em transferência total de resposta, mas apenas entre duas operações de leitura, se depois deste tempo o cliente não demora nada, então o nginx está desligando a conexão.
9 – Controlar Conexões Simultâneas
Você pode usar o módulo Nginx Http Limit Zone para limitar o número de conexões simultâneas para a sessão atribuída ou, como caso especial, a partir de um endereço IP. Edite nginx.conf:
Directive describes the zone, in which the session states are stored i.e. store in slimits. ### ### 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session ### limit_zone slimits $binary_remote_addr 5m; ### Control maximum number of simultaneous connections for one session i.e. ### ### restricts the amount of connections from a single ip address ### limit_conn slimits 5;
A configuração acima limitará os clientes remotos a não mais de 5 conexões “abertas” simultaneamente por endereço IP remoto.
10 – Permitir acesso apenas a nosso domínio
Se o bot estiver fazendo apenas varredura aleatória do servidor para todos os domínios, basta negar isso. Você só deve permitir pedidos de proxy de domínio virtual ou reverso configurados. Você não deseja exibir solicitação usando um endereço IP:
Only requests to our Host are allowed i.e. nixcraft.in, images.nixcraft.in and www.nixcraft.in if ($host !~ ^(nixcraft.in|www.nixcraft.in|images.nixcraft.in)$ ) { return 444; }
11 – Limitar Métodos Disponíveis
GET e POST são os métodos mais comuns na Internet. Os métodos do servidor da Web são definidos no RFC 2616. Se um servidor web não requer a implementação de todos os métodos disponíveis, eles devem ser desativados. O seguinte irá filtrar e permitir somente os métodos GET, HEAD e POST:
Only allow these request methods ## if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; } ## Do not accept DELETE, SEARCH and other methods
Mais sobre Métodos HTTP
- O método GET é usado para solicitar um documento como https://sempreupdate.com.br/index.php.
- O método HEAD é idêntico ao GET, exceto que o servidor NÃO DEVE retornar um corpo de mensagem na resposta.
- O método POST pode envolver qualquer coisa, como armazenar ou atualizar dados, ou solicitar um produto, ou enviar e-mail enviando o formulário. Isso geralmente é processado usando o script do lado do servidor, como PHP, PERL, Python e assim por diante. Você deve usar isso se desejar carregar arquivos e processar formulários no servidor.
12 – Como eu recuso certos User-Agents?
Você pode facilmente bloquear agentes de usuário, ou seja, scanners, bots e spammers que podem estar abusando do seu servidor.
Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; }
Bloquear robôs chamados msnbot e scrapbot:
## Block some robots ## if ($http_user_agent ~* msnbot|scrapbot) { return 403; }
Bloquear Spam de Referência
Referer spam é perigoso. Pode prejudicar o seu ranking de SEO através de web-logs (se publicado). Você pode bloquear o acesso de spammers com essas linhas.
Deny certain Referers ### if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) { # return 404; return 403; }
13 – Como bloquear hotlink de imagem?
A imagem ou HTML hotlinking significa que alguém faz um link para o seu site para uma das suas imagens, mas a exibe em seu próprio site. O resultado final você acabará por pagar contas de largura de banda e tornar o conteúdo parecido com parte do site do sequestrador. Isso é geralmente feito em fóruns e blogs. Eu sugiro fortemente que você bloqueie e pare o hotlinking da imagem no próprio nível do servidor.
Stop deep linking or hot linking location /images/ { valid_referers none blocked www.example.com example.com; if ($invalid_referer) { return 403; } }
14 – Restrições de Diretório
Você pode definir o controle de acesso para um diretório especificado. Todos os diretórios da Web devem ser configurados caso a caso, permitindo o acesso somente quando necessário.
Limitando o acesso por endereço IP
Você pode limitar o acesso ao diretório por endereço IP no diretório /docs/:
location /docs/ { ## block one workstation deny 192.168.1.1; ## allow anyone in 192.168.1.0/24 allow 192.168.1.0/24; ## drop rest of the world deny all; }
Proteger com senha o diretório
Primeiro crie o arquivo de senha e adicione um usuário chamado kallklen:
mkdir /usr/local/nginx/conf/.htpasswd/
htpasswd -c /usr/local/nginx/conf/.htpasswd/passwd kallklen
Edite o nginx.conf e proteja os diretórios necessários da seguinte maneira:
Password Protect /personal-images/ and /delta/ directories ### location ~ /(personal-images/.|delta/.) { auth_basic "Restricted"; auth_basic_user_file /usr/local/nginx/conf/.htpasswd/passwd; }
Uma vez que um arquivo de senha foi gerado, os usuários subsequentes podem ser adicionados com o seguinte comando:
htpasswd -s /usr/local/nginx/conf/.htpasswd/passwd userName
15 – Configuração SSL
HTTP é um protocolo de texto simples e está aberto para monitoramento passivo. Você deve usar SSL para criptografar seu conteúdo para usuários. Uma opção gratuita de certificado SSL é a Let`s Encrypt, uma iniciativa trazida pelo Internet Security Research Group (ISRG).
16 – Dicas de segurança do Nginx e do PHP
O PHP é uma das linguagens de script mais populares do lado do servidor. Edite /etc/php.ini da seguinte maneira:
# Disallow dangerous functions disable_functions = phpinfo, system, mail, exec ## Try to limit resources ## # Maximum execution time of each script, in seconds max_execution_time = 30 # Maximum amount of time each script may spend parsing request data max_input_time = 60 # Maximum amount of memory a script may consume (8MB) memory_limit = 8M # Maximum size of POST data that PHP will accept. post_max_size = 8M # Whether to allow HTTP file uploads. file_uploads = Off # Maximum allowed size for uploaded files. upload_max_filesize = 2M # Do not expose PHP error messages to external users display_errors = Off # Turn on safe mode safe_mode = On # Only allow access to executables in isolated directory safe_mode_exec_dir = php-required-executables-path # Limit external access to PHP environment safe_mode_allowed_env_vars = PHP_ # Restrict PHP information leakage expose_php = Off # Log all errors log_errors = On # Do not register globals for input data register_globals = Off # Minimize allowable PHP post size post_max_size = 1K # Ensure PHP redirects appropriately cgi.force_redirect = 0 # Disallow uploading unless necessary file_uploads = Off # Enable SQL safe mode sql.safe_mode = On # Avoid Opening remote files allow_url_fopen = Off
17 – Execute Nginx Em Uma Cadeia de Chroot (Containers) Se Possível
Colocar nginx em uma cadeia de chroot minimiza o dano causado por um possível bloqueio ao isolar o servidor da Web em uma pequena seção do sistema de arquivos. Você pode usar o tipo de configuração chroot tradicional com o nginx. Se possível, use reservatórios do FreeBSD, XEN, Linux em um Debian/Ubuntu, LXD em um Fedora ou OpenVZ que use o conceito de contêineres.
18 – Limite conexões por IP no nível de firewall
Um servidor web deve manter um olho nas conexões e limitar as conexões por segundo. Tanto Pf quanto iptables podem acelerar usuários finais antes de acessar seu servidor nginx.
IPTables
O exemplo a seguir negará conexões recebidas se o IP fizer mais de 15 tentativas de conexão na porta 80 dentro de 60 segundos:
/sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set
/sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --
seconds 60 --hitcount 15 -j DROP service iptables save
BSD PF
Edite seu /etc/pf.conf e atualize-o da seguinte maneira. A configuração limita o número máximo de conexões por fonte a 100. 15/5 especifica o número de conexões por segundo ou intervalo de segundos, ou seja, a taxa limita o número de conexões a 15 em uma extensão de 5 segundos. Se alguém romper as regras, adicione-os à nossa tabela abusive_ips e bloqueie-os para fazer conexões adicionais. Finalmente, a palavra-chave de descarga mata todos os estados criados pela regra de correspondência que se originam do host que excede esses limites.
webserver_ip="202.54.1.1" table <abusive_ips> persist block in quick from <abusive_ips> pass in on $ext_if proto tcp to $webserver_ip port www flags S/SA keep state (max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_ips> flush)
19 – Configurar o sistema operacional para proteger o servidor Web
Ative o SELinux conforme descrito acima. Defina as permissões corretas na raiz do documento / nginx. O nginx é executado como um usuário chamado nginx. No entanto, os arquivos no DocumentRoot (/nginx ou /usr/local/nginx/html) não devem ser de propriedade ou graváveis por esse usuário. Para encontrar arquivos com permissões erradas, use:
find /nginx -user nginx
find /usr/local/nginx/html -user nginx
Certifique-se de alterar a propriedade do arquivo para root ou outro usuário. Um conjunto típico de permissão /usr/local/nginx/html:
ls -l /usr/local/nginx/html/
-rw-r--r-- 1 root root 925 May 3 00:50 error4xx.html -rw-r--r-- 1 root root 52 May 3 10:00 error5xx.html -rw-r--r-- 1 root root 134 May 3 00:52 index.html
Você deve excluir arquivos de backup indesejados criados pelo vi ou outro editor de texto:
find /nginx -name '.?' -not -name .ht -or -name '~' -or -name '.bak' -or -name '.old*'
find /usr/local/nginx/html/ -name '.?' -not -name .ht -or -name '~' -or -name '.bak' -or -name '.old*'
Passe -delete como opção para o comando find e irá livrar-se desses arquivos também.
20 – Restringir conexões Nginx de saída
Os crackers baixam o arquivo localmente em seu servidor usando ferramentas como o wget. Use iptables para bloquear conexões de saída do usuário nginx. O módulo ipt_owner tenta combinar várias características do criador de pacotes, para pacotes gerados localmente. É válido apenas na cadeia OUTPUT. Neste exemplo, permita que o usuário kallklen se conecte externamente usando a porta 80 (útil para o acesso da RHN ou para capturar atualizações do CentOS por repos):
/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner kallklen -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
Adicione a regra acima ao script de shell baseado em iptables. Não permita que o usuário do servidor web do nginx se conecte externamente.
21 – Mantenha seu software atualizado
Você deve manter seu software e kernel atualizados o tempo todo. Aplique o patch conforme sua versão ou distro. Se você estiver usando o comando apt-get Debian/Ubuntu Linux para aplicar patches:
sudo apt-get update
sudo apt-get upgrade
Se estiver usando RHEL/CentOS/Oracle/Scientific Linux, use o yum:
sudo yum update
22 – Evite clickjacking
Adicione o seguinte no seu nginx.conf ou domínio virtual para evitar clickjacking:
add_header X-Frame-Options SAMEORIGIN;
23 – Desativar content-type sniffing em alguns navegadores
Adicione o seguinte no seu nginx.conf ou domínio virtual:
add_header X-Content-Type-Options nosniff;
Habilitar Filtro Cross-site scripting (XSS)
Adicione o seguinte ao nginx.conf ou domínio virtual:
add_header X-XSS-Protection "1; mode=block";
24 – Force o uso de HTTPS
Se você configurou o certificado SSL no seu servidor, não tem porque usar HTTP. Adicione a seguinte linha em seu nginx.conf na configuração do HTTP:
return 301 https://$server_name$request_uri;
25 – Monitorando o Nginx
O Stub Status permite ver o número total de pedidos de clientes e outras informações. Para habilitá-lo adicione as seguintes linhas no contexto local do seu nginx.conf:
location /nginx_status { # Turn on stats stub_status on; access_log off; # only allow access from 192.168.1.5 # allow 192.168.1.5; deny all; }
Dica extra: observando seus registros e auditoria
Verifique os arquivos de log. Eles vão lhe dar uma compreensão de quais ataques são lançados contra o servidor e permitir que você verifique se o nível de segurança necessário está presente ou não.
grep "/login.php??" /usr/local/nginx/logs/access_log
grep "...etc/passwd" /usr/local/nginx/logs/access_log
egrep -i "denied|error|warn" /usr/local/nginx/logs/error_log
Esse foi um hardening para seu servidor nginx. No entanto, você deve consultar mais recursos para as necessidades de segurança de suas aplicações web. Por exemplo, o Wordpress ou qualquer outro aplicativo de terceiros possui seus próprios requisitos de segurança.