我使用这个块将网站的 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 指令时会发生什么
我通过 Nginx conf 将一个不存在的测试 URL 重定向到真实 URL。我重新加载了 Nginx。我访问了测试 URL,通过这样做,我将重定向缓存到了浏览器中,因此可能缓存在 CloudFlare 和 FastCGI Cache 中(如果 FastCGI 甚至缓存重定向的话)。之后,我从 SSH curl 了该测试 URL,并得到了 301响应。现在我得到了一个可靠的重定向示例。
然后我从 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:
- 你自己架构中的一些东西正在缓存零碎的东西
- 你的 VPS 提供商正在缓存一些杂七杂八的东西
如果您有多台服务器,您可以使用以下步骤找出上述哪一种可能性是原因,如果没有,我建议您联系提供商,或者如果您根本没有使用 VPS 而是使用自己的服务器,请检查您是否使用了代理、云服务、缓存服务器或任何可能缓存内容的东西 - (考虑原因可能是由上述两种可能性造成的)↴
通过 SSH 登录到您所拥有的同一 VLAN 中的其他服务器之一,例如您的存储服务器。
猜测您的存储使用 192.168.1.122 并且您的 WebServer 使用 192.168.1.125 作为其私有 IP 地址。
从存储服务器,用来
curl 192.168.1.125
查看您是否仍然获得 200 或是否获得 301。如果是 301,那么这就是您架构中缓存的东西,它可能是某些服务或您可能拥有的其他服务器,例如 LoadBalancer。
如果您得到 200,则这不是您的架构,因此请联系您的提供商。
301 状态代码导致问题的原因是什么?
301 重定向称为永恒的重定向!因此,所有接收它的内容(包括当今可用的大多数浏览器)都会将其视为永久内容,直到过期为止!这是意料之中的事情,没有什么奇怪的,这是永久内容的本质!
301 是一条单行道。
结论 :
如果您不是 100%(个人认为 500%)肯定,就永远不要使用永久性的东西!像 Google、Apple、RedHat 和其他大公司和制造商可以使用 301,因为他们知道自己在做什么,他们拥有每个人都会使用的大部分技术,而且他们还知道他们的计划在未来 5 年内会如何。您可以使用 301 进行简单的重定向,您可能每天都会使用它,就像您使用它一样(从 www 到非 www)。但永远不要永久使用它,直到您确定项目的未来五年(或至少两年)。
我希望您能尽快解决您的问题,并且希望我的答案能对您有所帮助。
队友的欢呼声。
答案2
您可以每次使用永久重定向。要取消永久重定向或删除重定向,只需删除重定向语句行。
如果你有这样的域名西弗吉尼亚并将重定向至laravel.com
并且您删除重定向语句,您打开浏览器仍然会打开重定向页面。这是因为浏览器缓存了。
尝试使用 curl,它将显示默认域,因为 curl 没有缓存。
结论删除浏览器的缓存