背景
看到chrome地址栏旁边的不安全很刺眼,就一直想给网站上一个https,虽然五月份就申请了证书,但由于自身的 procrastination,到了今天才开始动手。
然而,本身是一件非常简单的事情,却整整搞了我一天。。。。
2022 8.12 周五
晚上9.30,我拖着疲惫的身躯从字节下班,回到家开始摆烂一会会,便着手准备给我的博客上一个https。
上网搜了搜资料,看了一遍大概的流程,感觉也没什么难度,就是 下载证书到服务器,配一下nginx就完事了。
于是我信心满满地登上许久没有登陆的腾讯云,点到服务器内部,然后打开 iterm,打算用ssh来连接服务器。然后致命的来了,密码给忘了,因此我只能用腾讯云自带的webshell。
有一说一,这个webshell起初用的还不错,还支持上传和下载的功能,省去了用ftp来上传文件的功夫,就是有点卡。
于是下载好证书,传到服务器上,只需要传红色框框里的两个。
然后修改nginx的配置文件。
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 真正的https端口
server {
listen 443 ssl;
server_name garfieldz.cn;
ssl_certificate garfieldz.cn_bundle.crt;
ssl_certificate_key garfieldz.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
root /app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html last;
index index.html;
}
}
# http web端口进行一个重定向
server {
listen 80;
server_name garfieldz.cn;
return 301 https://$host$request_uri;
}
# 这个是管理后台的
server {
listen 8081;
server_name localhost;
root /blogAdmin/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html last;
index index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
然后我觉得并没有什么问题,于是执行 nginx -t 来检测配置文件。但是死活过不了检测,一直说无法加载证书,证书有问题,我寻思这我就原封不动下载的证书还能有问题??然后我用cat命令去看了下那俩证书,好家伙,不知道为什么,这个webshell给我传上去的时候给我自动加了几行字符串还是啥玩意的东西(忘记截图了),然后就一直过不了检测。于是我将多余的东西给删掉了,然后再检测,没啥问题了,于是执行了 nginx -s reload。
然后去访问 garfieldz.cn,看到地址栏左边没有了「不安全」的红色字样,安心多了。但是问题又来了,文章列表的数据没有请求到,我意识到是不是后端没有用https导致的浏览器安全问题,然后打开控制台一看,果然。
到这里已经凌晨12:30了,想想还是明天再搞吧,反正已经定位到问题了,应该很快就能解决。
2022 8.13 周六
接着昨天存在的问题,今天就继续解决问题。
由于吃了那个坑爹的webshell的亏,我想用ssh和ftp来连接服务器和上传文件了。
但是又有问题来了,密码忘了。。。。。。因此我点击了重置密码,按往常来说应该是没有任何问题的,但偏偏这次不太往常。重置密码要求重启服务器,我想这也没啥大不了的,但是。。。。
我重启几遍之后,怎么连服务器都连不上,甚至用腾讯云自带的webshell都连接不上,ping也ping不通。我窒息了,想着这怎么办呢?于是就到处搜,死活定位不到问题所在。然后我发现腾讯云有一个服务器自测功能,我自测了一下,发现panic了。。。我只能请求技术支持oncall,然后等待他们来修复。好在他们的回复很快,没过多久就帮我解决了问题。问了下是因为 CPU带宽出现了Panic导致内核启动异常。
这个问题解决了就想着继续解决昨天遗留的问题,但是我发现我的网站登不上去了,直接访问ip都不行。我也已经进行了nginx的重启和后端服务的重启,但这时候我ping是能ping通的,说明服务器那边的链路是正常的,但是访问就直接拒绝服务了。用telnet来测试也是无法连接。
这时候我的第一反应是我的安全组是不是应该也重新设置一下,因此我就这么干了,把一个个安全组删除了又添加上。
但是,还是经过这么一番无用努力,还是没有解决。我又想了想,是不是我nginx的配置问题呢?但是nginx服务正常启动了,也没有报错,能有啥问题呢。我纠结了几个小时还是没能解决问题,就又找了oncall,回复如下:简单来说就是安全组要开,防火墙也要关(但是我从来没有对防火墙进行过操作,之前也是一切正常。。。。。。
好了,终于要开始解决昨天遗留的问题了。昨天的问题是啥来着?哦,是后端没有https。那简单我后端也加一个https不就行了吗(其实这一步就已经错了)?
const Koa = require('koa');
const https = require('https');
const fs = require('fs');
const enforceHttps = require('koa-sslify').default;
const app = new Koa();
app.use(enforceHttps());
// 其他中间件......
const options = {
key: fs.readFileSync('./public/cert/garfieldz.cn.key'),
cert: fs.readFileSync('./public/cert/garfieldz.cn_bundle.crt')
};
https.createServer(options, app.callback()).listen(3333);
好,改完,部署。完事。咦?怎么还是没解决问题,昨天的问题依旧存在啊?于是我又苦思冥想,哦,是不是前端发请求的时候发的依旧是http请求?于是一看代码果然
baseUrl = 'http://xxx.xxx.xx.x:3333'
简单,那改成https的不就完事了么。好,改,部署。很好,还是无用功,我想是不是浏览器自动把这个请求转成http的了?于是我又搜到了以下答案:就是将http请求转成https的。
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
好,改完,部署。完事。咦?怎么还没解决?我心态有点小崩。但是刷新之后,我发现数据能请求了,但是重新变回了不安全的状态。但请求都是https的呀,这我就懵了。
我又苦思冥想啊...无意中我点了一下后端的api链接,我突然意识到,这不是我前端的问题!证书是和域名捆绑的,并不是和ip捆绑的,我给后端上证书有个p用啊!
于是我又想了解决方案,我前端的 baseUrl 设置为 '/api', 然后通过nginx做转发,这样就应该没问题了。好说干就干,改代码,部署,改nginx配置。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 443 ssl;
server_name garfieldz.cn;
ssl_certificate garfieldz.cn_bundle.crt;
ssl_certificate_key garfieldz.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
root /app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html last;
index index.html;
}
location /api/ {
# 这里还是https,因为其实并不会影响,
# 反而改成http的话会报错,因为这样后端也要改回http
proxy_pass https://localhost:3333/;
proxy_cookie_path / /api;
rewrite "^/api/(.*)" /$1 break;
}
}
server {
listen 80;
server_name garfieldz.cn;
return 301 https://$host$request_uri;
}
# ... 其他server
}
好了,终于没有问题了,garfieldz.cn 满血复活!!!
就在我准备发一篇博文的时候,我又意识到了问题,我的后台管理系统并不是同一个域名下的,但是用的后端是一个后端。哎。。。改吧,和展示端一样,做一个路由转发吧。。。这时候意识到其实设计的时候就不该这么设计。
worker_processes 2;
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 443 ssl;
server_name garfieldz.cn;
ssl_certificate garfieldz.cn_bundle.crt;
ssl_certificate_key garfieldz.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
root /app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html last;
index index.html;
}
location /api/ {
proxy_pass https://localhost:3333/;
proxy_cookie_path / /api;
rewrite "^/api/(.*)" /$1 break;
}
}
server {
listen 80;
server_name garfieldz.cn;
return 301 https://$host$request_uri;
}
server {
listen 8081;
server_name localhost;
root /blogAdmin/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html last;
index index.html;
}
location /api/ {
proxy_pass https://localhost:3333/;
proxy_cookie_path / /api;
rewrite "^/api/(.*)" /$1 break;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
终于,现在是 2022 8.14 00:31分,终于。。。。。。