3 votes

Nginx rewite rules 403 error

Je n'arrive pas à convertir les fichiers .htaccess en nginx. J'ai 3 fichiers .htaccess. Le premier fichier .htaccess est situé dans la racine du document et se présente comme suit :

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]

Le deuxième fichier .htaccess se trouve dans un dossier appelé 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>

Le troisième et dernier fichier .htaccess se trouve dans un sous-répertoire du dossier upload nommé "small" :

RewriteEngine Off

J'ai créé un dossier dans /etc/nginx appelé includes et j'ai créé 3 fichiers .access séparés avec ces règles de réécriture :

Pour le premier fichier .htaccess situé dans le répertoire racine du document, j'ai créé un fichier dans /etc/nginx/includes appelé root.access. Dans ce fichier, j'ai :

# 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; 
}

Pour le deuxième fichier situé dans le dossier "upload", j'ai créé un fichier dans /etc/nginx/includes appelé upload.access. Ce fichier contient les éléments suivants :

# 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; 
}

Et pour le troisième et dernier fichier, j'ai créé un fichier dans /etc/nginx/includes names small.access. Le contenu de ce fichier est le suivant :

# nginx configuration 

location /upload/small { 
}

Dans le fichier de configuration du bloc serveur, j'ai

 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;
     }

Avec cette configuration, lorsque j'essaie le site, je reçois des erreurs 403. Le journal des erreurs de Nginx rapporte :

[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/"

Maintenant, sous apache, tout fonctionne sans problème. Mais je ne vois pas pourquoi je reçois des erreurs 403. Je crains également que les règles de réécriture telles que je les ai énoncées, au-delà de l'erreur 403, ne fonctionnent pas correctement du tout. Quelqu'un peut-il m'aider ? Je ne vois pas ce qui ne va pas.

10voto

berto Points 221

C'est le comportement standard de nginx pour cette partie de votre 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; 
    }

}

Pourquoi ?

Permettez-moi de clarifier le fonctionnement des emplacements : lorsque nginx lit les fichiers de configuration, il classe les blocs d'emplacements en 3 types :

  • Exactement blocs de localisation, par exemple location = /upload { }
  • Préfixe blocs de localisation, par exemple location /upload { }
  • Blocs de localisation contenant expressions régulières par exemple location ~ /upload { }

Lorsqu'une requête arrive à nginx, le processus de sélection de l'emplacement se déroule comme suit :

  1. Si un bloc d'emplacement correspondant exactement à l'URI est trouvé, nginx arrête de chercher d'autres blocs d'emplacement et répond à cette demande.
  2. Si ce n'est pas le cas, nginx recherchera le bloc d'emplacement préfixé correspondant le plus long et le mémorisera avant de passer à l'étape suivante.
  3. Ensuite, nginx vérifie séquentiellement les blocs d'emplacement contenant des expressions régulières. Le premier bloc correspondant sera utilisé pour répondre à la demande.
  4. Si rien n'a été trouvé à l'étape précédente, nginx utilisera le bloc d'emplacement préfixé de l'étape 2 pour répondre à la requête. Si rien n'a été trouvé, plusieurs choses peuvent se produire, mais c'est hors sujet.

Ainsi, dans votre cas, le bloc de localisation correspondant à l'élément .php est prioritaire sur le bloc de localisation correspondant à l'extension /upload de l'URI.

Editer : Clarification de la solution, ajout d'une solution alternative.

L'utilisation de la ^~ vous pouvez dire à nginx de changer son comportement pour l'étape 2 afin qu'il utilise l'emplacement préfixé correspondant immédiatement, en contournant la recherche d'emplacements par expression régulière. Vous avez donc 2 solutions :

Solution 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; 
}

même bloc serveur

Solution 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;
}

bloc serveur :

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

Maintenant, votre configuration actuelle ne mènera à rien si vous ne mettez pas en place un emplacement pour acheminer le traitement des fichiers php : consultez nginx module fastcgi . Vous devrez alors modifier vos règles de réécriture dans le fichier root.access afin qu'elles ne soient pas résolues dans le contexte de l'emplacement actuel (c'est-à-dire créer un emplacement de repli unique et modifier le paramètre break a last pour indiquer à nginx de relancer le processus de sélection de l'emplacement après la réécriture).

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X