奇怪的Bug…从来没有见过这么奇怪的Bug…
前言
学习学累了 ,又想着折腾折腾。这次准备折腾个OSU!私服架设,先从Google上搜信息。。又在Git上找到了许多Bancho(OSU!服务端)的实现。还发现了OSU!圈子里国人大神用Rust写的实现。看README说性能优越。就它了。
Peace
PurePeace大佬写的实现
https://github.com/Pure-Peace/Peace
大概描述一下这个项目的结构
配置
本机修改hosts
127.0.0.1 osu.ppy.sh
127.0.0.1 c.ppy.sh
127.0.0.1 c1.ppy.sh
127.0.0.1 c2.ppy.sh
127.0.0.1 c3.ppy.sh
127.0.0.1 c4.ppy.sh
127.0.0.1 c5.ppy.sh
127.0.0.1 c6.ppy.sh
127.0.0.1 ce.ppy.sh
127.0.0.1 a.ppy.sh
127.0.0.1 i.ppy.sh
修改nginx配置(bancho.conf)
# Peace's bancho & avatar server config
#
# Please change: $default_avatar, $avatar_dir and ssl_certificates
#
upstream peace {
# Tcp (default) peace
server 127.0.0.1:8080 fail_timeout=0;
# Unix sock
# server $unix:/path/to/.sock fail_timeout=0;
keepalive 600;
keepalive_timeout 120s;
keepalive_requests 4000;
}
server {
# Bancho server
server_name ~^(?:c[e4-6|osu]?)\.ppy\.sh;
listen 80;
listen 443 ssl;
gzip on;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
ssl_certificate /cargo/Peace/nginx/cert/cert.cer;
ssl_certificate_key /cargo/Peace/nginx/cert/key.pem;
location / {
proxy_pass http://127.0.0.1:8080/bancho/;
}
location /web/ {
proxy_pass http://127.0.0.1:8080/web/;
}
}
server {
# Avatar static server
server_name a.ppy.sh;
listen 80;
listen 443 ssl;
# Warn: Please *MAKESURE* that default avatar file is exists
set $default_avatar default.png;
# Change the avatar_dir
# Recommended absolute path
set $avatar_dir /cargo/avater;
add_header cache-control "public, max-age=7200";
index $default_avatar;
root $avatar_dir;
ssl_certificate /cargo/Peace/nginx/cert/cert.cer;
ssl_certificate_key /cargo/Peace/nginx/cert/key.pem;
proxy_intercept_errors on;
error_page 497 500 403 404 =200 /$default_avatar;
# Disable direct access to files:
# Attempts to access with a file suffix (such as /1.png /1.jpg...)
# will be redirected to an address with no suffix (/1)
location ~(.*)\.(.*)$ {
rewrite ^/(.*)\.(.*)$ $1 permanent;
}
# Access with image name (No suffix, player id only)
location / {
try_files $uri.png $uri.jpg $uri.jpeg $uri.gif /$default_avatar break;
}
}
公网环境
本机
内网运行时,一切正常,于是我准备把服务端提到公网环境,按照项目运行架构,Peace可以不对外公开,仅通过Nginx转发请求。于是我将Hosts修改为本机公网IP
再通过osu.ppy.sh测试转发情况 ,成功
经过上面的设置,按理来说应该已经成功了啊?可是此项目是运行在个人电脑。ISP给的公网IP默认封禁了80端口,意思是说,只有我自己能连进来,别人改了hosts是访问不到本机的。
所以为了解决问题,我准备将项目迁移到阿里云服务器上
阿里云
在经过一系列配置后,在阿里云上配置的结构是这样的
Peace换成了8081,因为Tomcat占了8080。Nginx配置也对应更换。Hosts直接将osu.ppy.sh一系列域名转发到阿里云IP。
阿里云运行Peace+Nginx,一切正常(忽略那个数据库版本问题-w-)
本以为大功告成,可是接下来碰见的这个Bug困扰了我整整一天。。。
在浏览器中输入osu.ppy.sh发现无法访问
EDGE直接访问显示出错
火狐出现这个错误
问题是我直接访问IP是可以成功访问的,Https也成功握手。
但如果我从Hosts劫持的域名访问就失败。
查看Nginx日志,压根没有输出错误,也就是说在Nginx之前就出错了。。
看了好久SSL证书+Nginx配置仍然没有解决问题。
无奈的我开始排除法慢慢寻找问题的根源。
BUG
我修改了Hosts的域名,换成百度或者别的发现竟可以成功访问了
直接访问百度
出现这个错误是因为证书不匹配,但是证明已经成功握手。
也就是说其他域名可以转发到我的服务器,但是osu.ppy.sh不行,于是我以为是域名有问题,继续排除
我又修改了hosts里的IP,用osu.ppy.sh转发到其他的IP比如百度,发现也可以访问
也就是说,其他的域名都可以通过hosts访问我的服务器,只有osu.ppy.sh访问不到
并且osu.ppy.sh可以访问到别的IP,就访问不到我的服务器。
简直怪了
通过Wireshark抓包发现发送了Client Hello后服务端莫名其妙直接扔回来一个RST(???)
通过除osu.ppy.sh以外的域名访问服务器
就可以握手成功
Openssl尝试验证出现以下错误
另外我尝试将hosts域名修改为我未备案的域名,发现也不能访问,估计是没有备案的原因80和443无法访问吧。
另辟蹊径
这下坏了,游戏是通过hosts劫持*.ppy.sh一系列域名来切换私服的,可是这些域名却访问不到我的服务器,这可怎么办。
想了想,还有别的方法。
OSU!连接私服的方法除了安装证书劫持域名外还有一个方法
通过给程序增加参数,修改游戏连接的服务器
可是我不太清楚这个参数的具体作用,我在这里修改成我服务器的域名(未备案),发现无法连接到我的bancho,我并不知道这个参数具体改变了什么。
最后我从另一个使用Python写Bancho实现的项目那里,发现了下面的nginx配置
在这个配置的下面,还有一些注释掉的代码
server switcher support,这个server switcher就是私服一键修改hosts并安装证书的小程序,也就是说如果是-devserver方式运行的私服就是通过上面没注释的代码运行的。
看了一下最大的差别就在这一行了
通过hosts转发则是
发现两者server_name抓取的后半部分域名不同,一个是ppy.sh,另一个是自己的顶级域名。
所以我推断,-devserver参数会将游戏输出的包修改为**.你的参数*
比如-devserver后跟的参数为abc.com
那么游戏会将自己的包修改为osu.abc.com a.abc.com c1.abc.com等等。具体有什么包就可以看上面的hosts来确定。
这下可以通过这个方式来绕过osu.ppy.sh这个域名了,可是我自己的域名还没有备案。没办法,火速备案。但备案之前我就想先试验一下我的想法是否是正确的。
我将-devserver后添加一个虚拟域名 abc.com
然后再将nginx配置修改为匹配abc.com
修改证书生成配置
本机安装证书
hosts 增加abc.com的转发
成功访问!
来看一下游戏是否将信息发到了这个域名(想法是否出错)
客户端成功连接到服务端检测到登录行为
抓包显示也握手成功
总结
成功用-devserver参数的方式绕过了osu.ppy.sh这个域名,再使用hosts转发虚拟域名到服务器上来成功访问私服。
虽然解决了bug,但没有完全解决。
等域名备案下来,就可以删掉自签名证书和hosts内容了,只通过-devserver+自己的顶级域名即可访问。
但是我们仍未知道那天的bug是什么原因QAQ,为什么osu.ppy.sh就是转发不到我的服务器,仍然是个谜;w;