Co oznacza ten błąd Nginx „przepisywanie lub wewnętrzny cykl przekierowań”?

67
tail -f /var/log/nginx/error.log
2013/05/04 23:43:35 [error] 733#0: *3662 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 127.0.0.1, server: _, request: "GET /robots.txt HTTP/1.1", host: "kowol.mysite.net"
HTTP/1.1", host: "www.joesfitness.net"
2013/05/05 00:49:14 [error] 733#0: *3783 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 127.0.0.1, server: _, request: "GET / http://www.qq.com/ HTTP/1.1", host: "www.qq.com"
2013/05/05 03:12:33 [error] 733#0: *4232 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 127.0.0.1, server: _, request: "GET / HTTP/1.1", host: "joesfitness.net"

Otrzymuję je z dziennika błędów nginx, nie mam subdomeny „kowol”, nie mam żadnych linków do qq.com ani joesfitness.net na mojej stronie. Co się dzieje?

Edycja: Domyślna konfiguracja Nginx:

server {
    listen   8080; ## listen for ipv4; this line is default and implied
    listen   [::]:8080 default ipv6only=on; ## listen for ipv6

    root /usr/share/nginx/www;
    index index.php index.html index.htm;

    # Make site accessible from http://localhost/
    server_name _;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to index.html
        try_files $uri $uri/ /index.html;
        # Uncomment to enable naxsi on this location
        # include /etc/nginx/naxsi.rules
    }

    location /doc/ {
        alias /usr/share/doc/;
        autoindex on;
        allow 127.0.0.1;
        deny all;
    }

    # Only for nginx-naxsi : process denied requests
    #location /RequestDenied {
        # For example, return an error code
        #return 418;
    #}

    #error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    #error_page 500 502 503 504 /50x.html;
    #location = /50x.html {
    #   root /usr/share/nginx/www;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        # With php5-cgi alone:
        fastcgi_pass 127.0.0.1:9000;
        #With php5-fpm:
        #fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #   deny all;
    #}
}
pavs-maha
źródło

Odpowiedzi:

78

To dziwne, ale założę się, że problem polega na:

        try_files $uri $uri/ /index.html;

Problem polega na tym, że drugi parametr tutaj $uri/powoduje, że każdy z plików w indexdyrektywie jest kolejno wypróbowywany. Jeśli nie zostaną znalezione, następuje przejście do /index.html, co powoduje locationponowne wprowadzenie tego samego bloku, a ponieważ nadal nie istnieje, powstaje nieskończona pętla.

Przepisałbym to jako:

        try_files $uri $uri/ =404;

zwracać błąd 404, jeśli nie istnieje żaden plik indeksu określony w indexdyrektywie.


BTW, te żądania, które widzisz, są szumem tła internetowego . W szczególności są to sondy mające na celu ustalenie, czy serwer sieciowy jest otwartym serwerem proxy i czy można go wykorzystać do ukrycia pochodzenia szkodliwego użytkownika, gdy idzie on do wykonania złośliwej działalności. Twój serwer nie jest otwartym proxy w tej konfiguracji, więc tak naprawdę nie musisz się o to martwić.

Michael Hampton
źródło
Dziękuję za wyjaśnienie. Czy jest jakiś sposób na zablokowanie / zablokowanie tego rodzaju sond?
pavs-maha
Nie bardzo, po prostu nakarm ich 404, a oni w końcu to wymyślą.
Michael Hampton
2
Co to jest „śmieszne” jest to, że domyślna konfiguracja Ubuntu 13.10 ma try_files $uri $uri/ /index.html;i index index.php index.html index.htm;ustawione. powodując błąd w pytaniu. Nie dotyczy to 12.04 i 14.04, więc jest mniej prawdopodobne na serwerze.
leifcr
9

Otrzymasz również ten komunikat o błędzie, jeśli index.phpcałkowicie go brakuje.

markus
źródło
Tak, w moim przypadku popełniłem błąd, umieszczając ścieżkę parametru root.
dlopezgonzalez
8

To było denerwujące. Działało kilka tygodni temu i nie udało mi się, kiedy próbowałem dzisiaj.

Wierzyłem, że aktualizacja nginxpakietu Ubuntu spowoduje zmianę domyślnego katalogu, w którym Ubuntu zachował standardowe pliki indeksu, więc wiersz:

root /usr/share/nginx/www;

Nie będzie już działać, ponieważ lokalizacja plików znajduje się w /usr/share/nginx/html.

Aby to naprawić, wystarczy zmienić wskaźnik główny na właściwy katalog lub utworzyć dowiązanie symboliczne do nowego katalogu:

cd /usr/share/nginx
sudo ln -s html www

Pracuje dla mnie.

Wari Wahab
źródło
2

Wczoraj napotkałem ten problem, ponieważ testowałem nginx na serwerze proxy, który buforował przekierowanie, które już nie istniało. Rozwiązaniem było dla mnie $ sudo service squid3 restartpołączenie z serwerem proxy squid3, przez który się łączyłem.

Ninjaxor
źródło
Zauważ, że podzieliłem się tą odpowiedzią z dobrymi intencjami. Istnieje wiele przyczyn tego błędu i znalezienie pamięci podręcznej serwera proxy zajmuje trochę czasu.
Ninjaxor
2

Gdyby ten błąd był dzisiaj, poświęć kilka godzin na ustalenie przyczyny. Okazało się, że ktoś usunął wszystkie pliki strony.

ulu
źródło
1

Wystarczy dodać kolejny przypadek, gdy tak się stanie. Podobnie jak w zaakceptowanej odpowiedzi, dzieje się tak zwykle, gdy tworzona jest sekwencja testowanych lokalizacji, a następnie tworzona jest swego rodzaju wewnętrzna pętla przekierowania (niekończąca się).

Czasami objawia się to złą konfiguracją NGINX, a nawet restrykcyjnym chmod (w niektórych konfiguracjach blokujących). Oto przykład

Załóżmy, że masz index.phpkontroler z przodu, jak zwykle:

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

Najczęściej podajesz adresy URL SEO, jak /some/thingza pośrednictwem swojego index.php.

Ale jak zwykle istnieją pewne pliki PHP, które należy ujawnić bezpośrednio (a więc location ~\.phpi nie location = /index.php.

Przypuszczam też, że Twój index.phpzostała chmod-ded do 0400 dla Lockdown bezpieczeństwa.

W tym przypadku wszystko nadal działa poprawnie, o ile plik jest własnością „użytkownika PHP-FPM”. NGINX nie musi czytać pliku, ponieważ po prostu przekazuje swoją nazwę pliku do PHP-FPM w celu wykonania i odzyskuje odpowiedź FastCGI.

Następnie chcesz poradzić sobie z przypadkiem tego, co się dzieje, gdy ktoś odwiedza, /non-existent.phpponieważ przy tej raczej standardowej konfiguracji uzyskasz No input file specified.taką sytuację.

Aby sobie z tym poradzić, niektórzy dodają:

if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss

Cóż, oczywiście, że ifzło jest jak na Nginx, ale nie o to chodzi. Wszystko się teraz zepsuje z błędem cyklu przekierowania. Dlaczego?

Ponieważ ta sekwencja dzieje się w pętli:

  • Gdy /some/pageżądany jest adres URL, nginx wchodzi location /, nie znajduje prawdziwego pliku i zmienia go/index.php
  • Następnie wchodzi do .phpbloku lokalizacji i próbuje sprawdzić, czy potrafi odczytać index.php. Ponieważ nie może , przepisuje go do tego samego, index.phpa następnie wraca do niego .phpponownie.
Danila Vershinin
źródło
Dziękuję, Danila Vershinin ! Pomogło mi to: lokalizacja / {try_files $ uri $ uri / /index.php?$args; }
Brabus