尽管我从配置文件中删除了该规则,但 Nginx 仍然会重定向

尽管我从配置文件中删除了该规则,但 Nginx 仍然会重定向

我使用这个块将网站的 IP 重定向到实际的 URL:

# IP to domain redirect
server {
        # tell on which port this server listens
        listen [::]:80;
        listen 80;

        # listen on the IP
        server_name xx.xx.xx.xxx;

        # and redirect to the domain
        return 301 $scheme://example.com$request_uri;
}

然而我决定删除它,但重定向并没有消失。我知道我的浏览器已经硬缓存了该重定向,我看不到变化,所以我curl -I xx.xx.xx.xxx通过 SSH 查看响应,其中 xx.xx.xx.xxx 是服务器的公共 IP:

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Tue, 10 Jan 2017 14:06:01 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: http://example.com/
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-UA-Compatible: IE=Edge

如您所见,重定向仍然存在。此外,我从第三方来源 ping 了 IP,他们确认 301 重定向存在。所以我真的很困惑,在没有重定向规则的情况下,这怎么可能呢。

我做过的其他事情:

  • 我已经检查了我的 iptables,没有任何类型的 PREROUTING 链。
  • 我没有忘记重新启动 Nginx,甚至还重新启动了服务器。
  • 由于我使用了 FastCGI 缓存,所以我清除了整个 FastCGI Nginx 缓存。
  • 由于服务器位于 CloudFlare 后面,因此我也清除了他们那边的整个缓存。但很明显,上面的 301 响应不是来自 CloudFlare,因为他们设置了容易识别的标头,而这些标头不是他们的。

这是 Nginx conf。显然,在生产中,这个块被分成几个文件,但为了回答这个问题,我把它粘贴在一个块中。

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
        worker_connections 1024;
        multi_accept on;
}

worker_rlimit_nofile 10000;

http {
        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        client_body_timeout 12;
        client_header_timeout 12;
        keepalive_timeout 15;
        send_timeout 10;

        open_file_cache          max=10000 inactive=5m;
        open_file_cache_valid    2m;
        open_file_cache_min_uses 1;
        open_file_cache_errors   on;

        types_hash_max_size 2048;
        server_tokens off;

        server_names_hash_bucket_size 64;
        server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_min_length 256;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:800m inactive=4h;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_cache_use_stale error timeout invalid_header http_500;
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        add_header X-Cache $upstream_cache_status;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header "X-UA-Compatible" "IE=Edge";

        # www to non-www redirect
        server {
                # don't forget to tell on which port this server listens
                listen [::]:80;
                listen 80;

                # listen on the 'www' host
                server_name www.example.com;

                # and redirect to the non-www host (declared below)
                return 301 $scheme://example.com$request_uri;
        }

        # Begin the server config
        server {
                listen [::]:80;
                listen 80;

                # The host name to respond to
                server_name example.com;

                # The location of access and error logs (symlinked to /var/www/example.com/logs/)
                access_log /var/log/nginx/example.com.access.log;
                error_log /var/log/nginx/example.com.error.log;

                # Root for static files
                root /var/www/example.com/htdocs;
                index index.php index.html index.htm;

                # Find and replace CDN urls
                subs_filter example.com/wp-content/uploads/         cdn.example.com/wp-content/uploads/;
                subs_filter example.com/wp-content/themes/          cdn.example.com/wp-content/themes/;
                subs_filter example.com/wp-content/plugins/         cdn.example.com/wp-content/plugins/;
                subs_filter example.com/apple-touch-icon.png        cdn.example.com/apple-touch-icon.png;

                # Cache every page
                set $skip_cache 0;

                # POST requests and urls with a query string should always go to PHP
                if ($request_method = POST) {
                        set $skip_cache 1;
                }

                # Don't cache queries
                if ($query_string) {
                        set $skip_cache 1;
                }

                # Cache only these queries
                if ($query_string ~* "orderby|r_sortby|results") {
                        set $skip_cache 0;
                }

                # Don't cache uris containing the following segments
                if ($request_uri ~* "/wp-admin/|/xmlrpc.php|/opcache.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                        set $skip_cache 1;
                }

                # Don't use the cache for logged in users or recent commenters
                if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                        set $skip_cache 1;
                }

                # Don't log robots.txt and favicon.ico
                location ~ /(robots.txt|favicon.ico) { 
                        access_log off; 
                        log_not_found off; 
                }

                # Prevent clients from accessing hidden files (starting with a dot) - .htaccess or .htpasswd
                location ~ /\. { 
                        deny all; 
                        access_log off; 
                        log_not_found off; 
                }

                # Prevent clients from accessing backup/config/source files
                location ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ { 
                        deny all; 
                        access_log off;
                        log_not_found off;
                }

                # Don't allow access to files in /wp-admin/includes folder
                location ~* /wp-admin/includes { 
                        deny all;
                        access_log off;
                        log_not_found off;
                }

                # Don't allow php execution in wp-includes folder
                location ~* /wp-includes/.*.php$ {
                        deny all;
                        access_log off;
                        log_not_found off;
                }

                # Don't allow php execution in wp-content folder
                location ~* /wp-content/.*.php$ {
                        deny all;
                        access_log off;
                        log_not_found off;
                }

                # Don't allow php execution in uploads and files folders
                location ~* /(?:uploads|files)/.*\.php$ { 
                        deny all; 
                        access_log off;
                        log_not_found off;
                }

                # Deny access to XML-RPC requests
                # location = /xmlrpc.php {
                #       deny all;
                #       access_log off;
                #       log_not_found off;
                # }

                # Deny access to sensitive files
                location ~ /(wp-config.php|install.php|readme.html|licence.txt) { 
                        deny all;
                        access_log off;
                        log_not_found off;
                }

                # Redirect feed to FeedBurner
                if ($http_user_agent !~ "FeedBurner|FeedValidator") {
                        rewrite ^/feed/?.*$ http://feeds.example.com/example redirect;
                }

                # Strip/Redirect these queries
                if ($query_string ~* "fb_xd_fragment|fb_action_ids|iframe") {
                        rewrite ^(.*)$ $1? redirect;
                }

                rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml$ "/index.php?xml_sitemap=params=$2" last;
                rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml\.gz$ "/index.php?xml_sitemap=params=$2;zip=true" last;
                rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html$ "/index.php?xml_sitemap=params=$2;html=true" last;
                rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html.gz$ "/index.php?xml_sitemap=params=$2;html=true;zip=true" last;

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

                location ~ \.php$ {
                        # try_files $uri =404;
                        # try_files $uri =404 /index.php?$args;
                        try_files $uri /index.php?$args;
                        fastcgi_split_path_info ^(.+\.php)(/.+)$;

                        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
                        include fastcgi_params;

                        # Combat (110: Connection timed out) while reading response header from upstream
                        fastcgi_read_timeout 120;

                        fastcgi_cache_bypass $skip_cache;
                        fastcgi_no_cache $skip_cache;

                        fastcgi_cache WORDPRESS;
                        fastcgi_cache_valid 4h;

                        # combat error 'upstream sent too big header...' 
                        fastcgi_buffers 32 64k;
                        fastcgi_buffer_size 64k;
                }

                # Purge ULR only within localhost
                location ~ /purge(/.*) {
                        allow 127.0.0.1;
                        deny all;
                        fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
                }       

                # cache.appcache, your document html and data
                location ~* \.(?:manifest|appcache|html?|xml|json)$ {
                        expires -1;
                }

                # Feed
                location ~* \.(?:rss|atom)$ {
                        add_header Pragma public;
                        add_header Cache-Control "public";
                        expires 4h;
                }

                # Media: images, icons, video, audio, HTC, CSS, Javascript, and WebFonts
                location ~ \.(css|js|htc|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                        access_log off;
                        log_not_found off;
                        add_header Pragma public;
                        add_header Cache-Control "public";
                        expires max;
                }
        }

        server {
                listen 127.0.0.1:80;
                server_name 127.0.0.1;
                location /nginx_status {
                        stub_status on;
                        access_log off;
                        allow 127.0.0.1;
                        deny all;
                }
        }
}

我也这样做了curl -I 127.1,响应如下:

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 11 Jan 2017 14:09:08 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Apr 2016 13:31:19 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "571f6da7-264"
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-UA-Compatible: IE=Edge
Accept-Ranges: bytes

# 测试 1:查看删除其他 URL 的 301 指令时会发生什么

  1. 我通过 Nginx conf 将一个不存在的测试 URL 重定向到真实 URL。我重新加载了 Nginx。我访问了测试 URL,通过这样做,我将重定向缓存到了浏览器中,因此可能缓存在 CloudFlare 和 FastCGI Cache 中(如果 FastCGI 甚至缓存重定向的话)。之后,我从 SSH curl 了该测试 URL,并得到了 301响应。现在我得到了一个可靠的重定向示例。

  2. 然后我从 Nginx conf 中删除了重定向,重新加载了 Nginx,并通过浏览器访问了测试 URL。重定向仍然存在。但是,当我通过 SSH curl 测试 URL 时,我没有得到重定向,但得到了正确的 404 未找到状态。从 nginx conf 中删除重定向代码后,Nginx 服务器级别的重定向就消失了。

# 测试2:将公网IP重定向改为302

我将 IP 到域重定向指令移回 Nginx 配置,但这次返回 302。

# IP to domain redirect
server {
        # tell on which port this server listens
        listen [::]:80;
        listen 80;

        # listen on the IP
        server_name xx.xx.xx.xxx;

        # and redirect to the domain
        return 302 $scheme://example.com$request_uri;
}

我重新加载了 Nginx 并 curl 了 IP。我很惊讶地看到302 暂时移动回复:

HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Thu, 12 Jan 2017 14:46:49 GMT
Content-Type: text/html
Content-Length: 154
Connection: keep-alive
Location: http://example.com/
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-UA-Compatible: IE=Edge

删除此指令并重新加载 Nginx 后,通过 CURL 的响应将恢复为301 永久移动

这次测试告诉我问题可能不是缓存问题。一定是在 conf 文件中的某个地方或服务器的总体架构中存在其他规则,使得公共 IP 301 重定向到域。

# 测试 3:将站点置于 CloudFlare 的开发模式并清除所有缓存。

我已将网站置于 CF 的开发模式,并清除了所有内容。我已从同一网络上的本地计算机和我家里的 PC 执行过 curl。两种情况下的响应都是 301。

# 测试 4:检查 ipv6 是否也重定向。

我已经对服务器的公共 ipv6 进行了 curl 。

curl -I -g "http://[server:public:ipv6:here]/"

答案是301 永久移动指向网站的域名,这更令人费解,几乎令人难以置信。我从来没有设置过这个 ipv6 重定向,除非这个问题开头发布的重定向服务器块也包含 ipv6 重定向。

有什么想法吗?

答案1

curl 127.1由于您在问题中测试并提到的结果,您获得了 200 HTTP 状态代码 - 在使用curl在本地,并使用127.1而不是您的公共 IP 地址。

您在本地收到 200 状态代码的原因是,您可能已成功删除 301 重定向行,并且您的 NGINX 在重新启动守护进程后工作正常。因此,您不必担心 NGINX,问题在于其他缓存重定向的东西。

如何找出问题的原因以及问题出在哪里?

可能有两件事会导致问题 - 取决于您是使用自己的服务器还是使用 GoDaddy、OVH 等提供的 VPS:

  1. 你自己架构中的一些东西正在缓存零碎的东西
  2. 你的 VPS 提供商正在缓存一些杂七杂八的东西

如果您有多台服务器,您可以使用以下步骤找出上述哪一种可能性是原因,如果没有,我建议您联系提供商,或者如果您根本没有使用 VPS 而是使用自己的服务器,请检查您是否使用了代理、云服务、缓存服务器或任何可能缓存内容的东西 - (考虑原因可能是由上述两种可能性造成的)↴

  1. 通过 SSH 登录到您所拥有的同一 VLAN 中的其他服务器之一,例如您的存储服务器。

  2. 猜测您的存储使用 192.168.1.122 并且您的 WebServer 使用 192.168.1.125 作为其私有 IP 地址。

  3. 从存储服务器,用来curl 192.168.1.125查看您是否仍然获得 200 或是否获得 301。

  4. 如果是 301,那么这就是您架构中缓存的东西,它可能是某些服务或您可能拥有的其他服务器,例如 LoadBalancer。

  5. 如果您得到 200,则这不是您的架构,因此请联系您的提供商。

301 状态代码导致问题的原因是什么?

301 重定向称为永恒的重定向!因此,所有接收它的内容(包括当今可用的大多数浏览器)都会将其视为永久内容,直到过期为止!这是意料之中的事情,没有什么奇怪的,这是永久内容的本质!

301 是一条单行道。

结论 :

如果您不是 100%(个人认为 500%)肯定,就永远不要使用永久性的东西!像 Google、Apple、RedHat 和其他大公司和制造商可以使用 301,因为他们知道自己在做什么,他们拥有每个人都会使用的大部分技术,而且他们还知道他们的计划在未来 5 年内会如何。您可以使用 301 进行简单的重定向,您可能每天都会使用它,就像您使用它一样(从 www 到非 www)。但永远不要永久使用它,直到您确定项目的未来五年(或至少两年)。

我希望您能尽快解决您的问题,并且希望我的答案能对您有所帮助。

队友的欢呼声。

答案2

您可以每次使用永久重定向。要取消永久重定向或删除重定向,只需删除重定向语句行。

如果你有这样的域名西弗吉尼亚并将重定向至laravel.com

并且您删除重定向语句,您打开浏览器仍然会打开重定向页面。这是因为浏览器缓存了。

尝试使用 curl,它将显示默认域,因为 curl 没有缓存。

结论删除浏览器的缓存

相关内容