以CentOS为例,在VPS上通过nginx工具实现反向代理,部署并访问网站。


nginx是轻量级高性能的网络服务器代表。本文将以安装带有SSL模块的nginx1.20.0为例,配合acme.sh生成的泛域名证书,在基于CentOS 8的Linux服务器上实现一级域名及其二级域名的全站https加密访问。

1 安装必要工具

1
dnf install wget curl

2 安装带有SSL模块的nginx

虽然可能使用CentOS 8的dnf install nginx可以直接安装,但是默认是不带SSL模块的,所以在这里需要手动安装。

2.1 下载解压

1
2
3
cd ~
wget http://nginx.org/download/nginx-1.20.0.tar.gz
tar -zxvf nginx-1.20.0.tar.gz

2.2 配置SSL模块

1
2
cd nginx-1.20.0
./configure --prefix=/usr/local/nginx --with-http_ssl_module

2.3 安装nginx

(1) 如果是首次安装或者重装nginx(务必备份nginx.conf

1
make install

(2) 如果是已有nginx需要升级

1
2
make
cp ./objs/nginx /usr/local/nginx/sbin/

2.4 检查安装结果

1
/usr/local/nginx/sbin/nginx -V

输出应该类似下面这样:

1
2
3
4
5
nginx version: nginx/1.20.0
built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
built with OpenSSL 1.1.1g FIPS  21 Apr 2020
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module

注意:nginx的配置文件位于/usr/local/nginx/conf/nginx.conf

3 在域名服务商处获取API Token

此处以DNSPod购买的域名http://hello.com为例,介绍API token的获取方法和注意事项。

首先登录并打开DNSPod的控制台https://console.dnspod.cn/,点击右上角头像后,选择密钥管理: ssl-1

然后点击创建密钥: ssl-2

注意:在创建后一定要及时地复制到其他位置,因为这个窗口关了就再看不到你的Token了

接下来,安全起见,建议白名单仅仅添加自己的VPS地址: ssl-3

完成: ssl-4

4 利用acme.sh生成泛域名证书

acme.sh实现了ACME协议, 可以从Let’s Encrypt生成免费的证书.

4.1 获取acme.sh

1
curl https://get.acme.sh | sh

注意

  1. 如果国内VPS直接执行不好使,你可以在网络较好的Linux主机上执行这条命令,然后把~/.acme.sh/这个目录直接拷贝到远程VPS的相同位置上,也可以生效。
  2. 可以创建一个bash的alias, 方便使用: alias acme.sh=~/.acme.sh/acme.sh

4.2 导出API Token

注意

  1. 不同的域名服务商的命令不同,此处仅以DNSPod为例,更多的参考acme.sh官方Wiki
  2. DP_IdDP_Key参考本文第3节
1
2
export DP_Id="xxxxxxxx"
export DP_Key="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

4.3 生成泛域名证书

注意

  1. 需要在bash下执行命令,zsh测试无法识别*.hello.com语法
  2. --force即强制生成证书(会刷新掉旧的)
  3. --debug会打印详细的日志,方便出错定位
1
~/.acme.sh/acme.sh --issue --dns dns_dp -d hello.com -d *.hello.com --force --debug 2

4.3 安装证书

注意:此处将证书放在了自定义的位置/root/ssl-keys/

1
/root/.acme.sh/acme.sh --installcert -d hello.com --key-file /root/ssl-keys/hello.com.key --fullchain-file /root/ssl-keys/hello.com.cer

5 编辑nginx配置并重新载入

5.1 实现强制https代理

1
vim /usr/local/nginx/conf/nginx.conf

nginx.conf示例如下:

 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
58
http {
  # http强制跳转https
  server {
    listen       80;
    server_name hello.com a.hello.com b.hello.com www.hello.com;
    rewrite ^(.*) https://$host$1 permanent;
  }

  # 一级域名
  server {
    listen       443;
    server_name  hello.com;

    # ssl证书地址
    ssl_certificate      /root/ssl-keys/hello.com.cer;  # crt文件的路径
    ssl_certificate_key  /root/ssl-keys/hello.com.key;  # key文件的路径
    # ssl验证相关配置
    ssl_session_timeout  5m;              # 缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  # 加密算法
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  # 安全链接可选的加密协议
    ssl_prefer_server_ciphers on;         # 使用服务器端的首选算法
    # 防止nginx代理websocket时,每隔75秒自动中断
    proxy_connect_timeout 7d;
    proxy_send_timeout 7d;
    proxy_read_timeout 7d;
    # 防止nginx代理websocket报错
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    location / {
      proxy_pass  http://127.0.0.1:8000;
    }
  }

  # 第一个子域名
  server {
    listen       443;
    server_name  a.hello.com;

    # ssl设置同 hello.com,直接复制过来即可
    
    location / {
      proxy_pass  http://127.0.0.1:8001;
    }
  }
  
  # 第二个子域名
  server {
    listen       443;
    server_name  b.hello.com;

    # ssl设置同 hello.com,直接复制过来即可
    
    location / {
      proxy_pass  http://127.0.0.1:8002;
    }
  }
}

5.3 重新载入nginx配置

1
/usr/local/nginx/sbin/nginx  -s reload

注意:务必打开防火墙的443端口

大功告成,至此已实现hello.com的全站强制https访问。

参考资料

  1. Nginx安装SSL配置HTTPS超详细完整全过程:https://segmentfault.com/a/1190000022673232
  2. 全站HTTPS升级系列(一)升级前的科普工作:https://juejin.cn/post/6844904143291678734
  3. 全站HTTPS升级系列(二)基于acme.sh从Letsencrypt生成免费的泛域名证书:https://juejin.cn/post/6844903759756132360
  4. 全站HTTPS升级系列(三)nginx配置全站HTTPS:https://juejin.cn/post/6844903759764520973
  5. 什么是ACME协议?:https://www.ssl.com/zh-CN/faqs/what-is-the-acme-protocol/
  6. acme.sh官方GitHub仓库:https://github.com/acmesh-official/acme.sh
  7. acme.sh中文Wiki:https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E
  8. acme.sh的DNS API说明:https://github.com/acmesh-official/acme.sh/wiki/dnsapi
  9. Let’s Encrypt官网:https://letsencrypt.org/
  10. nginx官网:http://nginx.org/
  11. nginx离线下载页面:http://nginx.org/en/download.html
  12. DNSPod控制台地址:https://console.dnspod.cn/