Valdeir S.
Posted on October 1, 2021
Opa!! Vamos avançar em nossa série. Hoje aprenderemos como controlar o acesso com filtro de IP e autenticação interna.
Bloqueando acessos
Você pode bloquear um IP (ou faixa de IP) utilizando a diretiva deny
. Além do IP, é possível também utilizar o CIDR para bloquear requisições.
# Syntax: deny address | CIDR | unix: | all;
# Default: —
# Context: http, server, location, limit_except
#
# Bloqueia um IP específico
deny 127.0.0.1;
# Bloqueia faixa 142.250.218.0 - 142.250.218.255
deny 142.250.218.0/24;
# Bloqueia uma faixa de IP do tipo IPV6
deny 2001:0db8::/32;
# Bloqueia todos os acessos
deny all;
Bloqueando acesso a arquivos
Com o deny
, também é possível bloquear acesso aos arquivos ou a um diretório. Basta utilizar a diretiva dentro do contexto location
, por exemplo.
location ~ \.(log|zip|tar|gz|htaccess|bkp|old|txt)$ {
deny all;
}
Permitindo acesso a determinados IPs
Além de bloquear, você pode apenas permitir determinados IPs ou faixa de ips. Isso é útil para limitar o acesso a determinada rede.
# Syntax: allow address | CIDR | unix: | all;
# Default: —
# Context: http, server, location, limit_except
#
# Bloqueia acesso local
allow 127.0.0.1;
# Permite acesso da faixa de IP 162.158.214.0 - 162.158.214.255
allow 162.158.214.0/24;
# Permite acesso a uma faixa IPV6
allow 2001:0db8::/32;
# Bloqueia todos os acessos
deny all;
Não faz sentido usar apenas
allow
, visto que — por padrão — todos os acessos são permitidos.
Resolvendo problema com CDN
Quando você utiliza um serviço como CloudFlare (ou similar), eles recebem a requisição e a repassam para seu servidor. Isso faz com que o IP recebido pelo Nginx não seja o real, o do cliente; mas sim o IP do servidor da CloudFlare. Como resolver isso?
Para resolver, você precisa configurar duas diretivas: set_real_ip_from
e real_ip_header
.
Na primeira, você definirá os endereços de IP confiável (True-Client-IP) que sabem o IP do cliente, ou seja, você configurará com os IPs da CloudFlare.
Na segunda, você informará o header que contém o endereço real do cliente. Normalmente é CF-Connecting-IP ou X-Forwarded-For.
Como esses dados são mutáveis, deixarei o link com as configurações atuais.
Auth Request
O sistema de subautorização do Nginx funciona através do módulo ngx_http_auth_request_module
. Ele permite que o desenvolvedor crie um sistema de autorização baseado em sub-requisições (requisições internas).
Essas requisições devem retornar o status code 200 (2xx), 401 ou 403. A depender do código de status retornado, o Nginx liberará (ou não) a solicitação. Caso a autorização seja negada, o Nginx retornará o erro para o usuário.
Verificar suporte
Antes de começar, verifique se o Nginx foi compilado com o suporte ao módulo.
nginx -V 2>&1 | grep --color http_auth_request_module
Se não tiver configurado, compile o Nginx com a flag --with-http_auth_request_module
Observação: É importante que você saiba compilar o código fonte do Nginx. Caso não tenha esse conhecimento, acesse a postagem Série Nginx #2: Compilando o Nginx
Configurando rota
Para configurar a autorização, utilizaremos a diretiva auth_request
.
Iremos configurar a autorização para uma rota, mas você pode configurar para um servidor virtual (no contexto
server
) ou todos os sites (no contextohttp
), beleza? 👍
server {
# Outras configurações
location /upload {
# Syntax: auth_request uri | off;
# Default: auth_request off;
# Context: http, server, location
#
auth_request /auth_upload;
proxy_pass http://upload-server;
}
}
Perfeito! Agora vamos configurar a localização de autorização.
location = /auth_upload {
proxy_pass http://auth-server;
}
Com isso já conseguimos realizar a validação. Lembrando que o status code do proxy http://auth-server
deve retornar 2xx, 401 ou 403.
Bloqueando acesso direto
Em alguns sistemas, você pode querer bloquear o acesso direto à URL ou ao servidor de autenticação ou autorização. O Nginx oferece esse suporte com a diretiva internal
, ou seja, o Nginx impedirá que o usuário acesse a URL /auth_upload
e apenas ele fará o acesso.
location = /auth_upload {
internal;
proxy_pass http://auth-server;
}
No nosso exemplo, utilizarei os dados enviados na requisição POST para realizar a verificação da autorização, por isso é necessário configurar as diretivas proxy_pass_request_body
e proxy_method
.
Caso seu sistema de autorização não faça uso dos dados enviados no corpo da requisição, ignore-a.
location = /auth_upload {
internal;
proxy_pass http://auth-server;
proxy_pass_request_body on;
proxy_method POST;
}
Pronto! Com isso, o nosso sistema deverá funcionar corretamente.
Código para verificação da autorização
O código foi feito em Node e o servidor iniciado com Docker. Não explicarei o funcionamento porque a ideia é focar apenas no servidor web.
Utilizei o padrão adotado pelo S3, da AWS, para realizar a autorização ou negação. Ele basicamente verificará o método da requisição, content type, hash do arquivo e a data de envio e depois comparará com o hash enviado no header Authorization.
Realizando Upload
token="2HmVrZRYii8ZWrfIAFHLmlCYtqqv5nSASLCzZMHUg6M5vRlarfjumNDz9ZR5NHoY"
date_req=$(date -R)
hash=$(echo -en "POST\n$(md5sum anitta.mp4 | cut -d' ' -f1)\nvideo/mp4\n$date_req" | openssl sha1 -hmac "<user-key>" -hex)
http --form POST \
php.valdeirpsr.dev/upload \
Authorization:"AWS $token:$hash" \
Date:"$date_req" \
file@anitta.mp4
Como é feito o upload
- O arquivo é enviado para a URL
/upload
; - O Nginx recebe a requisição;
- O Nginx realiza uma subrequisição para autorização em
/auth_upload
; - O servidor
http://auth-server
realiza a validação e retorna o status code 200 ou 401. - O Nginx recebe a resposta da subrequisição e verifica o código retornado;
- Se o código for 401 ou 403, o Nginx retorna um erro para o cliente; caso retorne 2xx, prossegue com a requisição de upload.
Conclusão
É isso aew, meu povo! Finalizamos mais uma etapa da série de Nginx. Caso tenham dúvidas e/ou sugestões, basta deixarem o comentário. Beleza?
Até a próxima!
Posted on October 1, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.