目录前言问题探寻解决办法引用参考
现在访问我的博客,带或者不带斜杠均可正常访问。
前言
话说昨天整理了一下好久没折腾的个人博客网站,把之前 pwn
训练营的所有的资料整理到了一篇博客中,并发表了一条 Bilibili 动态。今天下午,我正喝着咖啡唱着歌,改着过两天要汇报的 PPT
,突然手机弹出一条消息,发现 B
站有个师傅给我留言说博客链接打不开,如下图:
而我动态里面的链接为:https://www.roderickchan.cn/zh-cn/2023-05-06-shg-pwn-tutorial-1,注意,这个链接的最后是不带反斜杠 /
的。
看到消息后我立马放下咖啡,将这个链接拷贝到浏览器中,发现确实打不开。但是,我又发现当链接结尾带上一个反斜杠之后,可以成功访问。于是,我先回复了这位师傅,将博客链接更新为带上反斜杠的 URL
。
回复后,我开始感到疑惑:为什么这个 URL
的末尾带上反斜杠会访问成功,而不带上反斜杠会访问失败呢?这其中一定蕴含着我不知道的知识点。我暂时先放下了手头的 PPT
,开始对问题进行分析。
问题探寻
考虑到我把博客同时备份到了 github
上面,因此,我把域名替换为 roderickchan.github.io
之后,再去访问https://roderickchan.github.io/zh-cn/2023-05-06-shg-pwn-tutorial-1,发现这个链接是可以正确打开的。但是这个域名是 github
提供的,我猜测他的服务器和我自己拥有的域名 www.roderickchan.cn
的服务器对请求的处理方式不太一样。
需要指出的是,我的 www.roderickchan.cn
这个域名提供的博客服务的运行架构如下,在我的[建站教程] 使用 aliyun+hugo 搭建个人博客 – roderick – record and learn!里面,有这样一张图解释了我是如何搭建个人博客服务以及把文件均存储在本地的。
我立马去看了一下我本地的文件,发现 zh-cn/2023-05-06-shg-pwn-tutorial-1
是一个目录,这个目录下面有一个 index.html
,正是 hugo
渲染后的 HTML
文件。按理来说,当使用 http
访问一个目录的时候,默认会访问目录下面的 index.html
,也就是说,访问不带斜杠的链接应该是可以访问成功的。
所以,我先访问了我本地端口,访问http://127.0.0.1:10081/zh-cn/2023-05-06-shg-pwn-tutorial-1,访问成功:
并且在访问成功后,浏览器会自动在 URL
后面添加一个反斜杠:
这里需要补充一个知识点。
当请求资源的 url
不带反斜杠的时候,服务器的处理一般如下:
如果对应的 url
是一个文件,会返回文件给你
如果对应的 url
是一个目录,会返回对应目录下的 index.html
文件
打开浏览器的控制台查看网络请求过程中的包信息:
结合上图分析可知,当我访问https://127.0.0.1:10081/zh-cn/2023-05-06-shg-pwn-tutorial-1的时候,我本地的 nginx
服务器会返回一段响应报文,报文中有一个字段 Location
,告诉浏览器资源的真正位置为https://127.0.0.1:10081/zh-cn/2023-05-06-shg-pwn-tutorial-1/;接着,浏览器基于收到的 Location
信息去发出第二次请求,此时就成功请求到了内容,如下所示:
那么问题来了,当访问https://www.roderickchan.cn/zh-cn/2023-05-06-shg-pwn-tutorial-1时,服务器给的 Location
字段是什么呢?
这个时候,为了避免需要重复修改浏览器窗口的 URL
,我掏出了 curl
分析报文。
发现服务器给的 Location
竟然带上了端口号,而且这个端口是我的后端代理端口,而我的公网服务器上的配置大概是酱紫的:
location / {
proxy_pass http://127.0.0.1:10081;
proxy_intercept_errors on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
怎么肥事?怎么在域名后面加上了本地代理的端口呢 ❓
我沉思片刻,联想到前面 127.0.0.1:10081
本地服务并无异常的情况,我好像有点明白了。我猜测这里的 Location
是真正处理请求的后端代理服务器转发给我的公网服务器的信息,然后公网服务器又拿着这个 Location
又转发给了我的浏览器,我的浏览器拿着这个 url
去访问,没有对应的服务,自然就会报错了。
为了验证自己的猜测,我登录自己的公网服务器对 10081
端口抓包:
红框是抓包命令,蓝框是公网服务器发给代理后端的请求,黄框是代理后端返回的请求。可以看到,代理后端确实返回了 http://www.roderickchan.cn:10081/zh-cn/2023-05-06-shg-pwn-tutorial-1/。
到这里,就搞清楚了整个访问过程是如何进行的。
于是,我接着谷歌[1],发现了 nginx
返回 location
字段时,如果不是默认 80/443
端口,会带上端口号,所以这就解释了为什么后端的代理服务器给的 Location
带有端口号。
解决办法
搞清楚问题来源后,我开始搜索 nginx
如何修改 proxy
的 Location
字段。很快啊,很快发现有个指令 proxy_redirect
。在查看了该指令的说明[1:1]后,我立马对配置文件进行了修改:
location / {
proxy_pass http://my_blog;
proxy_intercept_errors on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect ~^http://www.roderickchan.cn:(10080|10081|10082)(/.*)$ https://www.roderickchan.cn$2;
}
这里的 proxy_pass
为 http://my_blog;
是因为我做了负载均衡。
修改后重新启动 nginx
。然后,再使用 curl
验证,发现可以正常访问了:
至此,就成功地解决了这个问题。
于是我又继续打开 PPT
,重新点了一杯咖啡,然后合上 PPT
,开始写这篇博客。
哦对了,还有一个小问题,由于我配置了负载均衡,还代理了服务器上本地的 10080
端口,于是,之前有时候会访问 rodeirckchan.cn:10080
,会报错如下:
这个错误不同凡响!
搜索后发现:
竟然把端口给封了🤯
引用参考
http://nginx.org/en/docs/http/ngx_http_core_module.html ↩︎ ↩︎