Como restringir o acesso à localização gerada dinamicamente no nginx?

3

Meus desenvolvedores querem permitir o download de alguns arquivos apenas para usuários na lan. Eu disse ok, é bem simples e eu escrevi mudanças na configuração do nginx assim:



location /restricteddir/download/file {                                                             
        allow   192.168.0.0/16;                                                              
        allow   10.0.0.0/8;                                                                  
        deny all;                                                                            
    }

Ok do lado de fora estou recebendo 403, isso é bom, mas de dentro (LAN) me dá 404. Por quê?

Eu verifiquei, a localização do arquivo não existe no disco. O desenvolvedor me disse que o local é gerado dinamicamente pelo php para que os arquivos estejam no diretório tmp, mas depois que você clicar em link como:

https://example.com/report/download/file/id/somefile.txt deve começar o download, mas dá erro 404.

A última loção física é /restricteddir/download então file/id/somefile.txt é gerado pelo php.

Para testar, mudei a localização para /restricteddir/download e depois disso, hiting https://example.com/restricteddir/download deu-me 404 para.

Estou confuso depois de desabilitar a restrição para esse dir everythings funciona bem, eu posso baixar o arquivo de https://example.com/report/download/file/id/somefile.txt e hit https://example.com/report/download/ sem 404. Então, onde está o bug? O que devo adicionar à minha configuração nginx para que funcione?

EDIT1 Esta é a configuração completa para este host virtual:


#example.com:443
server {
    listen 443 default;
    ssl on;
    ssl_certificate example.crt;
    ssl_certificate_key example.key;
    ssl_session_timeout  15m;
    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;                  
    server_name example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;



location / {
        root   /sites/public;
        index  index.php;
        if (!-f $request_filename) {
                rewrite ^.*$ /index.php last;
                break;
        }
    }
location /restricteddir/download/file {
       allow   192.168.0.0/16;
       allow   10.0.0.0/8;
       deny all;
    }

#PHP
location ~ \.php$ {        
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;      
        include /fastcgi_params;        
        fastcgi_param  SCRIPT_FILENAME /sites/public$fastcgi_script_name;
    }
}

server {
        listen   80 default;
        server_name example.com;
        access_log off;
        rewrite ^(.*)$ https://example.com$1 permanent;
        }

E eu fundei isso nos meus logs:


2012/08/07 11:55:43 [error] 11121#0: *90 open() "/usr/share/nginx/html/restricteddir/download/file/id/somefile.txt" failed (2: No such file or directory), client: 10.200.2.70, server: example.com, request: "GET /restricteddir/download/file/id/somefile.txt HTTP/1.1", host: "example.com"

Agora sei que o nginx está procurando esse local na raiz errada /usr/share/nginx/html/ em vez de /sites/public

Então, talvez eu deva escrever assim:


location /sites/public/restricteddir/download/file {                                                             
        allow   192.168.0.0/16;                                                              
        allow   10.0.0.0/8;                                                                  
        deny all;                                                                            
    }

EDIT2

Eu movi diretiva raiz para bloco de servidor e agora em logs depois de ativar a restrição para location / restricteddir / download / file que eu tenho:


2012/08/09 10:43:12 [error] 32120#0: *71 open() "/site/public/restricteddir/download/file/id/somefile.txt" failed (2: No such file or directory), client: 10.2.1.120, server: example.com, request: "GET /restricteddir/download/file/id/somefile.txt HTTP/1.1", host: "example.com"
Então agora o nginx está olhando no lugar certo mas não encontra nada. Como este arquivo não foi gerado pelo php? Eu estou lutando com isso e não tenho idéia do que está acontecendo ... Isso é uma tarefa simples restrcit localização porque isso não funciona?

EDIT3

Isto é como parece minha configuração virtualhost agora:


#example.com:443
server {
    listen 443 default;
    ssl on;
    ssl_certificate example.crt;
    ssl_certificate_key example.key;
    ssl_session_timeout  15m;
    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;                  
    server_name example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
    root   /sites/public;


location / {
        index  index.php;
        if (!-f $request_filename) {
                rewrite ^.*$ /index.php last;
                break;
        }
    }
location /restricteddir/download/file {
       allow   192.168.0.0/16;
       allow   10.0.0.0/8;
       deny all;
    }

#PHP
location ~ \.php$ {        
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;      
        include /fastcgi_params;        
        fastcgi_param  SCRIPT_FILENAME /sites/public$fastcgi_script_name;
    }
}

server {
        listen   80 default;
        server_name example.com;
        access_log off;
        rewrite ^(.*)$ https://example.com$1 permanent;
        }

Então eu só mudei a diretiva root para o bloco de servidores, depois disso o nginx está procurando em um bom lugar mas ainda obtendo o 404. Estou confuso porque depois eu comentei o local / restricteddir / download / file block está funcionando e eu posso baixe o arquivo.

Para mim, não é muito estranho, porque é apenas uma restrição simples ... porque é que depois de ativá-lo nginx não conseguiu encontrar esse arquivo ...

    
por B14D3 07.08.2012 / 11:43

2 respostas

3

Duas sugestões:

  1. Mova a diretiva root para o bloco server , para que ela seja aplicada a todos os blocos location que a seguem. Essa parece ser a sua intenção.
  2. Lembre-se de que a diretiva de localização se aplica a caminhos de arquivos URIs não *. Por exemplo, a ideia de location /sites/public não faz sentido.

E algum outro feedback:

A questão de saber se os arquivos existem fisicamente ou não não faz diferença ao processar as diretivas location , eles corresponderão de qualquer maneira.

Outro erro de correspondência que vejo é que sua entrada de log se refere a "restricteddir", mas sua postagem "full config" não menciona isso. Ele menciona um diretório "report" em vez disso.

    
por 07.08.2012 / 14:55
1

Primeiramente, eu evito o seguinte if bloco, se possível, porque se é mal . Use try_files em vez disso:

location / {
    root   /sites/public;
    index  index.php;
    if (!-f $request_filename) {
            rewrite ^.*$ /index.php last;
            break;
    }
}

Isso é melhor:

location / {
    try_files $uri $uri/ index.php?$args;
}

Para maior clareza, eu movo root e index de location / para o bloco server :

server {
    …
    server_name example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    root   /sites/public;
    index  index.php;

Os arquivos são completamente gerados dinamicamente pelo PHP, então não existem diretamente no sistema de arquivos e, portanto, não podem ser servidos pelo nginx sem passar a requisição para o PHP? Se assim for, você precisa passar as coisas com fastcgi_pass para fastcgi para que o PHP possa criar & servir o arquivo, em vez de nginx tentando servir algo que não existe. Então:

location /report/download/ {
   allow   192.168.0.0/16;
   allow   10.0.0.0/8;
   deny all;
   fastcgi_pass   127.0.0.1:9000;
   fastcgi_index  index.php;      
   include /fastcgi_params;        
   fastcgi_param  SCRIPT_FILENAME /sites/public$fastcgi_script_name;
}

Se os arquivos realmente existirem no disco, mas estiverem em um local diferente, ou seja, a solicitação entrar como https://example.com/report/download/file/id/somefile.txt , o que realmente aponta para o local em disco de /sites/public/restricteddir/download/file/id/somefile.txt e você deseja que o nginx o exiba diretamente sem entregando para o fastcgi, então você quer a diretiva de alias .

location /report/download/ {
   allow   192.168.0.0/16;
   allow   10.0.0.0/8;
   deny all;
   # The actual physical path on disk -
   alias /sites/public/restricteddir/download/;
   # or should this be the following? -
   # alias /restricteddir/download/;
}

Uma última coisa a verificar: se nginx e fastcgi estiverem sendo executados como usuários diferentes, certifique-se de que ambos tenham as permissões de arquivo do sistema operacional corretas para ler os arquivos em questão. Se o nginx está procurando no lugar correto, mas ainda não consegue encontrar o arquivo, talvez seu dono e grupo sejam fastcgi: fastcgi com 660 permissões? Ou isso ou há algum tipo de cache acontecendo, como open_file_cache em nginx.conf

    
por 10.08.2012 / 03:18