O Nginx ( pronuncia-se “engine-x”) é um webserver e proxy reverso para os protocolos http, smtp, pop3 e imap focado em alta performance. Sua utilização vêm crescendo bastante rapidamente, numa pesquisa realizada em janeiro deste ano pela Netcraft ele ocupa o 2o. lugar entre os servidores webs ativos na internet.
Neste post apresentarei como configurar o Nginx com suporte ao PHP e todos os ajustes de segurança necessários.
NOTA: Informações importantes encontram-se nos comentários dos arquivos de configuração.
Para obter as versões mais recente usaremos os pacotes disponíveis no repositório squeeze-backports
deb http://backports.debian.org/debian-backports squeeze-backports main
aptitude install -t squeeze-backports nginx spawn-fcgi php5-cgi
Configurando o vhost
vim /etc/nginx/sites-available/www.acme.com
#O dominio acme.com é um alias para www.acme.com
server {
server_name www.acme.com acme.com;
access_log /var/log/nginx/www.acme.com.access.log;
error_log /var/log/nginx/www.acme.com.error.log;
root /var/www/acme/;location / {
index index.php;
}#Restrigindo o acesso ao ambiente administrativo
location /admin {
root /var/www/acme/;
index index.php;
allow 200.222.222.222;
deny all;
}#Negando o acesso a alguns arquivos
location =/*.txt {
deny all;
log_not_found off;
access_log off;
}location =/xmlrpc.php{
deny all;
log_not_found off;
access_log off;
}location =/readme.html {
deny all;
log_not_found off;
access_log off;
}#Habilitando o suporte ao PHP
location ~ .php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/acme$fastcgi_script_name;
}
}
Hardening do Nginx
user www-data;
#Total de threads. Configure de acordo com a quantidade de CPU existente, acima de 2 CPUs = 4.
worker_processes 4;
pid /var/run/nginx.pid;events {
#Juntamente com o work_processes permite calcular o máx. de clientes ( max clients = worker_processes * worker_connections )
worker_connections 1024;}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log;
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;# Oculta banner
server_tokens off;
}# Limita o maximo de conexoes concorrentes por IP
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;
Script de inicialização do PHP-Fastcgi
vim /etc/init.d/php-fastcgi
RETVAL=0
case “$1” in
start)
$PHP_SCRIPT
RETVAL=$?
;;
stop)
killall php5-cgi
RETVAL=$?
;;
restart)
killall php5-cgi
$PHP_SCRIPT
RETVAL=$?
;;
*)
echo “Usage: php-fastcgi {start|stop|restart}”
exit 1
;;
esac
exit $RETVAL
Adicionando nos Runlevels
update-rc.d php-fastcgi defaults
Habilitando o vhost e iniciando os serviços
cd /etc/nginx/sites-enabled
ln -s ../sites-available/www.acme.com
invoke-rc.d nginx start && invoke-rc.d php-fastcgi start
UPDATE 21/03/2012
Dicas adicionais do Jeronimo Zucco (@jczucco)
#Para evitar conexões DAV (PROPFIND TRACE PROPPATCH MKCOL COPY MOVE LOCK UNLOCK OPTIONS) se isso não for utilizado, é claro.
proxy_cache_methods GET HEAD POST;
#Para acompanhar a performance e utilização do nginx, afinal a disponibilidade também é importante. Pode ser feito gráfico do rrdtool usando essa ferramenta:http://blog.kovyrin.net/2006/04/29/monitoring-nginx-with-rrdtool/
HttpStubStatusModule
Configuração do limits.conf do parâmetro “nofile” para o usuário que está rodando o nginx. Por padrão o valor é 1024 arquivos abertos, se isso for insuficiente, o log irá apresentar: “failed (24: Too many open files)”, causando negação de serviço.
#Alguns bloqueios por extensão:
location ~ /.ht {
deny all;
}
location ^/MSOffice {
deny all;
}location ~ _vti_bin {
deny all;
}location ~* .(dll|cmd|src)$ {
deny all;
}
#Se o nginx for proxy reverso de HTTPS, habilitar somente criptografia forte para evitar o BEAST attack (CVE-2011-3389):
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
UPDATE 2 – 22/03/2012
Mais dicas do meu amigoJeronimo Zucco (@jczucco)
#Regra para evitar acidentes de “desenvolvedores” que esquecem arquivos em diretórios expostos para a internet, como dump de base de dados, código fonte backup, etc:
location ~* .(ant|asa|asax|ascx|axd|backup|bak|bat|bkp|cdx|cer|cfg|cmd|com|config|conf|cs|csproj|csr|dat|db|dbf|dll|dos|htr|htw|ida|idc|idq|inc|ini|key|licx|lnk|log|mdb|old|pass|pdb|pol|printer|pwd|resources|resx|sql|src|sys|vb|vbs|vbproj|vsdisco|webinfo|xsd|xsx)$ {
deny all;
}
#Bloqueio por hostname do que está sendo feito proxy, para evitar que uma configuração mal feita acabe abrindo o proxy para o mundo externo:
if ($host !~ ^(dominio.com.br|www.dominio.com.br)$ ) {
return 403;
}
Considerações finais
As melhores práticas de segurança do PHP já foram abordadas nos posts anteriores [1] [2]
Como pudemos constatar sua implementação é aparentemente fácil, o site do projeto é bastante rico em documentação.
O Nginx é muito utilizado como proxy reverso tornando-se um frontend para balanceamento de carga suportando diversos protocolos, existe também um módulo de WAF chamado Naxsi, esta e outras soluções serão tratadas nos próximos posts.
Referências
Muito bom to implementando aqui no trabalho, quando comecei a pesquisar encontrei esse tutorial fantástico, ia usar o varnish mas desisti dele.
Parabéns “case of sucess”
Obrigado Luiz. =]
Grande Alexos, valeu pelo post.
Para contribuir, segue mais alguns parâmetros no nginx para hardening:
– proxy_cache_methods GET HEAD POST; – para evitar conexões DAV (PROPFIND TRACE PROPPATCH MKCOL COPY MOVE LOCK UNLOCK OPTIONS) se isso não for utilizado, é claro.
– HttpStubStatusModule – Para acompanhar a performance e utilização do nginx, afinal a disponibilidade também é importante. Pode ser feito gráfico do rrdtool usando essa ferramenta:http://blog.kovyrin.net/2006/04/29/monitoring-nginx-with-rrdtool/
– Configuração do limits.conf do parãmetro “nofile” para o usuário que está rodando o nginx. Por padrão o valor é 1024 arquivos abertos, se isso for insuficiente, o log irá apresentar: “failed (24: Too many open files)”, causando negação de serviço.
– Alguns bloqueios por extensão:
location ~ /.ht {
deny all;
}
location ^/MSOffice {
deny all;
}
location ~ _vti_bin {
deny all;
}
location ~* .(dll|cmd|src)$ {
deny all;
}
– Se o nginx for proxy reverso de HTTPS, habilitar somente criptografia forte para evitar o BEAST attack (CVE-2011-3389):
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
Por enquanto é isso. 🙂
Valeu Zucco!
Suas considerações foram adicionadas no post.
Muito obrigado mano!
Abs,
Alexos
Eta, tem mais… 🙂
– Juntei numa regra algumas extensões que são recomendáveis serem bloqueadas. Algumas eu peguei nas regras do modsecurity, outras eu coloquei. Isso é mais para evitar acidentes de “desenvolvedores” que esquecem arquivos em diretórios expostos para a internet, como dump de base de dados, código fonte backup, etc:
location ~* .(ant|asa|asax|ascx|axd|backup|bak|bat|bkp|cdx|cer|cfg|cmd|com|config|conf|cs|csproj|csr|dat|db|dbf|dll|dos|htr|htw|ida|idc|idq|inc|ini|key|licx|lnk|log|mdb|old|pass|pdb|pol|printer|pwd|resources|resx|sql|src|sys|vb|vbs|vbproj|vsdisco|webinfo|xsd|xsx)$ {
deny all;
}
– Bloqueio por hostname do que está sendo feito proxy, para evitar que uma configuração mal feita acabe abrindo o proxy para o mundo externo:
if ($host !~ ^(dominio.com.br|www.dominio.com.br)$ ) {
return 403;
}
Abraço !
Putz! Muito obrigado pelas dicas mano!
Post atualizado.
Abração
Alexos
Parabéns pelo texto! Estou começando a mexer nele, achei bem interessante.
Achei um possível problema, se eu estiver falando besteira, me fala.
As sintaxes abaixo:
# Limita o maximo de conexoes concorrentes por IP
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;
Pela sua descrição, ficaria fora da sessão “Server”, acho que ideal seria descrever ela antes do fechamento da sessão, certo? Veja no seu texto como colocou.