Nginx rewite regras erro 403

3

Estou tendo problemas ao converter arquivos .htaccess para o nginx. Eu tenho 3 arquivos .htaccess. O primeiro arquivo .htaccess está localizado na raiz do documento e é o seguinte:

Options +FollowSymLinks
RewriteEngine On
RewriteRule ^img-(.*)\.html img.php?id=$1 [L]
RewriteRule ^slide-(.*)\.html slider.php?id=$1 [L]
RewriteRule ^page-(.*)\.html page.php?name=$1 [L]
RewriteRule ^contact\.html$ contact.php [QSA,L,NC]

O segundo arquivo .htaccess está localizado em uma pasta chamada upload:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?foo\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .*\.(jpe?g|gif|bmp|png)$ nohotlink.gif [L]
<Files ~ "\.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
  order allow,deny
  deny from all
</Files>

E o terceiro e último arquivo .htaccess é encontrado em um subdiretório da pasta de upload chamada "small":

RewriteEngine Off

Agora eu criei uma pasta em / etc / nginx chamada includes e fiz 3 arquivos separados .access com estas regras de reescrita:

Para o primeiro arquivo .htaccess localizado no diretório raiz do documento, criei um arquivo em / etc / nginx / includes chamado root.access. Neste arquivo eu tenho:

# nginx configuration 

location /img { 
rewrite ^/img-(.*)\.html /img.php?id=$1 break; 
} 
location /slide { 
    rewrite ^/slide-(.*)\.html /slider.php?id=$1 break; 
} 
location /page { 
    rewrite ^/page-(.*)\.html /page.php?name=$1 break; 
} 
location /contact { 
    rewrite ^/contact\.html$ /contact.php break; 
}

Para o segundo arquivo localizado na pasta "upload", criei um arquivo em / etc / nginx / includes chamado upload.access. Este arquivo contém o seguinte:

# nginx configuration 

location /upload { 
if ($http_referer !~ "^http://(.+\.)?foo\.com/"){ 
rewrite .*\.(jpe?g|gif|bmp|png)$ /nohotlink.gif break; 
} 
} 
location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ { 
deny all; 
}

E para o terceiro e último arquivo eu criei um arquivo em / etc / nginx / includes names small.access. O conteúdo deste arquivo é o seguinte:

# nginx configuration 

location /upload/small { 
}

No arquivo de configuração do bloco de servidores, tenho:

 location / {
              try_files $uri $uri/ /index.php;
              include /etc/nginx/includes/root.access;
     }

 location /upload {
              include /etc/nginx/includes/upload.access;
     }

 location /upload/small {
              include /etc/nginx/includes/small.access;
     }

Agora com esta configuração ao tentar o site recebo 403 erros. Relatórios de log de erros do Nginx:

[error] 18156#0: *7 access forbidden by rule, client: 111.**.**.**, server: foo.com, request: "POST /upload.php HTTP/1.1", host: "foo.com", referrer: "http://foo.com/"

Agora, sob o apache, tudo funciona sem problemas. Mas eu não consigo ver porque estou recebendo 403 erros. Também estou preocupado que as regras de reescrita como eu as afirmei, além do erro 403, não funcionem adequadamente. Alguém pode me ajudar com isso? Eu não consigo ver o que está errado aqui.

    
por Adrian 18.09.2014 / 07:38

1 resposta

9

Este é o comportamento padrão do nginx para esta parte da sua configuração:

location /upload { 

    if ($http_referer !~ "^http://(.+\.)?foo\.com/"){ 
        rewrite .*\.(jpe?g|gif|bmp|png)$ /nohotlink.gif break; 
    } 

    location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ { 
        deny all; 
    }

}

Por quê?

Deixe-me esclarecer como os locais funcionam: quando o nginx lê os arquivos de configuração, ele classifica os blocos de localização em três tipos:

  • Bloqueios de locais Exatos , por exemplo %código%
  • Bloqueios de locais Prefixados , por exemplo %código%
  • Blocos de localização que contêm expressões regulares , por exemplo %código%

Quando uma solicitação chega ao nginx, o processo de seleção de local é o seguinte:

  1. Se um bloco de local exato correspondente ao URI for encontrado, o nginx interromperá a pesquisa por outros blocos de local e atenderá a essa solicitação.
  2. Se não, o nginx pesquisará o bloco de localização prefixado correspondente mais longo e o memorizará antes de passar para a próxima etapa.
  3. Em seguida, o nginx verifica os blocos de localização que contêm expressões regulares sequencialmente. A primeira correspondência será usada para atender à solicitação.
  4. Se nada foi encontrado na etapa anterior, o nginx usará o bloco de localização com prefixo da etapa 2 para atender à solicitação. Se nenhum for encontrado, várias coisas podem acontecer, mas não é o assunto.

Portanto, no seu caso, o bloco de localização que corresponde à extensão location = /upload { } tem precedência sobre o bloco de localização que corresponde à parte location /upload { } do URI.

Editar : esclarecimento sobre solução, solução alternativa adicionada.

Usando o location ~ /upload { } , você pode dizer ao nginx para alterar o comportamento dele para a etapa 2, de modo que ele use imediatamente o local prefixado correspondente, ignorando a pesquisa de locais de expressões regulares. Então você tem 2 soluções:

Solução 1 :

upload.access:

if ($http_referer !~ '^http://(.+\.)?foo\.com/') { 
    rewrite '.*\.(jpe?g|gif|bmp|png)$' '/upload/nohotlink.gif' break; 
} 

if ($uri ~ '\.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$') {
    return 403; 
}

mesmo bloco de servidor

Solução 2 :

upload.access:

if ($http_referer !~ '^http://(.+\.)?foo\.com/') { 
    rewrite '.*\.(jpe?g|gif|bmp|png)$' '/upload/nohotlink.gif' break; 
} 

location ~ \.(php|sql|php3|php4|phtml|pl|py|jsp|asp|htm|shtml|sh|cgi)$ {
    deny all;
}

bloco de servidores:

 location ^~ /upload {
     include /etc/nginx/includes/upload.access;
 }

Agora, sua configuração atual não levará a nada se você não configurar um local para encaminhar o processamento de arquivos php: confira nginx módulo fastcgi . Em seguida, você precisará alterar suas regras de regravação no arquivo root.access para que elas não sejam resolvidas no contexto de local atual (ou seja, criar um único local de fallback e alterar .php to /upload para informar ao nginx para executar o processo de seleção de local novamente depois de reescrever).

    
por 18.09.2014 / 20:52