引入

之前在应用hexo-blog-encrypt插件实现博客内容加密时,仅仅在本地服务器调试成功就自认为成功了,然而并非如此。当我按流程将更新后的项目推送到云服务器后,在访问云服务器上部署的项目,并试图验证博文加密的功能能否运行时,发现存在问题。输入密码并按回车并没有反应,检查console发现下面的报错:

1
2
3
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')
at getKeyMaterial (hbe.js:98:29)
at HTMLDivElement.<anonymous> (hbe.js:271:35)

这意味着在执行importKey操作时,试图访问一个未定义的属性。

在Github翻看了hexo-blog-encrypt的issues,找到了相同的问题,链接如下:

https://github.com/D0n9X1n/hexo-blog-encrypt/issues/129

浏览其中的内容可以得知,必须使用HTTPs访问才能应用本插件,而HTTP页面无法完整支持。这迫使我尽快获取SSL证书,以便我的网页可以使用HTTPs协议访问。

实现

获取SSL证书的方式有很多,我起初尝试在阿里云的控制台申请并应用,但这样需要手动修改Nginx的配置文件内容,并且是在我使用并不熟练的Vim环境下。幸好还有更加便捷的方式,就是直接在云服务器的终端安装并运行Certbot。

Certbot 是一个自动化工具,它帮助你从 Let’s Encrypt 获取和续期 SSL/TLS 证书。Let’s Encrypt 是一个提供免费 SSL/TLS 证书的非营利证书颁发机构。

我的云服务器操作系统是Ubuntu,以下是安装Certbot并安装SSL证书的过程:

Certbot安装SSL证书

  1. 安装CertBot
1
2
sudo apt install certbot python3-certbot-nginx

  1. 生成SSL证书
1
sudo certbot --nginx

执行指令后要输入邮箱和域名。

  1. 写入配置文件

    这不需要操作,由Certbot自动完成。可以检查nginx配置文件的内容来更深入地理解操作的原理。下面的指令用vim编辑器打开nginx.conf:

1
sudo vim /etc/nginx/sites-available/default

其中包括下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;

root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name aaronwu.fun; # managed by Certbot


location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}


listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/aaronwu.fun/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/aaronwu.fun/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

其中“managed by Certbot”的部分就是由Certbot添加的,其在HTTPs连接的标准端口443监听连结。

防火墙引发的问题

上面的操作完成后,我打开自己的网址,却发现无法打开了,没想到为了个SSL证书把网站搞崩了😰

经过GPT老师的提示,排查了多个可能存在的问题(比如nginx服务关闭,配置文件有误等),终于定位到了出现问题的地方。

我尝试检查我的443端口是否正确开启:

1
sudo ufw status

发现并没有。

我尝试打开443端口,并再次检查443端口是否打开:

1
2
sudo ufw allow 443
sudo ufw status

发现443端口无法打开。

于是我想到应该在阿里云的云服务器控制台上对安全组进行设置,添加的内容如下:

添加后再次访问网址,发现网站终于活了过来。

Certbot定期续签SSL证书

由于整数的有效时间仅有90天,因此需要定期续签才能保证其正常工作。可以在服务器上设置定期自动执行的指令,来实现自动化续签。

首先需要在服务器上打开cron编辑器:

1
sudo crontab -e

添加下面内容,在每个月的第一天的凌晨两点执行certbot renew命令,尝试续签证书。

1
0 2 1 * * /usr/bin/certbot renew --quiet

背景知识补充

HTTP与HTTPs

HTTP 是 HyperText Transfer Protocol(超文本传输协议)的缩写,是用于从 World Wide Web(WWW)服务器传输超文本到本地浏览器的传输协议。

HTTPS 是 HTTP over SSL(或HTTP Secure),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。

HTTP 和 HTTPS 的主要区别在于安全性:

  • HTTP 传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输的信息可以被任何抓包的人获取到,这样的情况下如果传输的内容是重要信息,如账号密码等,那么就会被不法分子获取并利用。
  • HTTPS 是经过 SSL 加密的 HTTP,通过 SSL 证书来验证服务器的身份,并为客户端和服务器之间的通信加密。这样即使信息在传输过程中被拦截,由于其是经过加密的,拦截者也无法读懂真实的内容,从而保证了信息的安全。

SSL证书 是一种采用 SSL(Secure Sockets Layer,安全套接层)协议来保障网站数据传输安全的数字证书。一个 SSL 证书在技术上是一个数据文件,这个文件在安装到服务器后会把 HTTP(不安全)转为 HTTPS(安全)。

Unix-Like操作系统中的 cron 任务

cron 是一个长期运行的进程,它在特定的日期、时间或时间间隔执行命令或脚本。在 Ubuntu 系统中,crontab 是用来创建、编辑、安装、卸载和列出 cron 任务的工具。

可以使用 crontab 命令来设置定期执行的任务,如每天备份文件、每小时检查系统状态等。