即使我从conf中删除了规则,Nginx仍然会重定向

Vil*_*ila 6 nginx domain ip redirect 301-redirect

我使用此块将网站的 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;
}
Run Code Online (Sandbox Code Playgroud)

然而我决定删除它,但重定向并没有消失。我知道我的浏览器已经硬缓存了该重定向,我看不到更改,因此我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
Run Code Online (Sandbox Code Playgroud)

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

我做过的其他事情:

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

这是 Nginx 配置。显然,在生产中,该块被分割为多个文件,但为了解决这个问题,我将其粘贴到一个块中。

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;
                }
        }
}
Run Code Online (Sandbox Code Playgroud)

我也做了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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

我将 IP 到域重定向指令移回 Nginx conf,但这次返回 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;
}
Run Code Online (Sandbox Code Playgroud)

我已经重新加载了 Nginx 并卷曲了 IP。我很惊讶地看到302 Moved Temporarily回复:

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
Run Code Online (Sandbox Code Playgroud)

完全删除这个完全相同的指令并重新加载 Nginx 后,通过 CURL 的响应返回到301 Moved Permanently

这个测试告诉我问题可能不是缓存问题。一般来说,conf 文件或服务器体系结构中的某个位置必须有其他规则,使公共 IP 到 301 重定向到域。

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

我已将网站置于 CF 的开发模式,并清除了所有内容。我已经从同一网络上的本地计算机和家里的电脑上完成了curl。两种情况的响应均为 301。

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

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

curl -I -g "http://[server:public:ipv6:here]/"
Run Code Online (Sandbox Code Playgroud)

响应是301 Moved Permanently指向该网站的域名,这更令人费解且几乎令人难以置信。我一开始就从未设置过此 ipv6 重定向,除非在本问题开头发布的重定向服务器块也包含 ipv6 重定向。

有什么想法吗?

小智 2

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

\n

您在本地获得 200 状态代码的原因是您可以成功删除 301 重定向行,并且您的 NGINX 在重新启动守护程序后工作正常。所以你不用担心 NGINX,问题是缓存重定向的其他东西。

\n

如何找出导致问题的原因以及问题的根源?

\n

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

\n
    \n
  1. 你自己的架构中的一些东西是缓存零碎的东西
  2. \n
  3. 您的 VPS 提供商中的某些内容正在缓存赔率和草皮
  4. \n
\n
\n

如果您有多个服务器,您可以使用以下步骤找出其中一种可能的原因,如果您没有,我建议您与提供商联系,或者如果您根本不使用 VPS 并且您'如果您使用自己的服务器,请检查您是否正在使用代理、云服务、缓存服务器或任何可能缓存内容的内容 - (考虑原因可能是由上述两种可能性引起的)\xe2\x86\xb4

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

    \n
  2. \n
  3. 假设您的存储使用 192.168.1.122,而您的 Web 服务器使用 192.168.1.125 作为其私有 IP 地址。

    \n
  4. \n
  5. 从存储服务器中,用于curl 192.168.1.125查看您是否仍然收到 200 还是收到 301。

    \n
  6. \n
  7. 如果是 301,则表明这是您的架构中缓存内容的内容,它可能是您可能拥有的某些服务或其他服务器,例如 LoadBalancer。

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

    \n
  10. \n
\n

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

\n

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

\n

301是一条单行道。

\n

结论 :

\n

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

\n

希望您能尽快解决您的问题,也希望我能帮助您找到答案。

\n

队友的欢呼声。

\n

  • 我建议将来使用302 (2认同)