Série Nginx 6#: Controlando acesso

valdeirpsr

Valdeir S.

Posted on October 1, 2021

Série Nginx 6#: Controlando acesso

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;
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 contexto http), 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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Perfeito! Agora vamos configurar a localização de autorização.

location = /auth_upload {
    proxy_pass http://auth-server;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Como é feito o upload

  1. O arquivo é enviado para a URL /upload;
  2. O Nginx recebe a requisição;
  3. O Nginx realiza uma subrequisição para autorização em /auth_upload;
  4. O servidor http://auth-server realiza a validação e retorna o status code 200 ou 401.
  5. O Nginx recebe a resposta da subrequisição e verifica o código retornado;
  6. 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!

💖 💪 🙅 🚩
valdeirpsr
Valdeir S.

Posted on October 1, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related