申请Let's Encrypt免费SSL证书并在Node.js建立HTTPS服务

前言

  为了更安全地传输,我们往往需要建立HTTPS连接。我们可以利用OpenSSL创建自签名的证书,但创建自己的CA机构并不安全也不被各大浏览器承认。目前有不少免费SSL证书提供商,其中最流行的便是Let’s Encrypt(官网),下面是关于如何申请Let’s Encrypt免费SSL证书并用Node.js建立一个HTTPS服务器。

申请Let’s Encrypt免费SSL证书

Let’s Encrypt官方推荐使用Certbot ACME客户端。它可以自动执行证书颁发和安装,无需停机且易于使用。

  • 首先安装certbot
    通过SSH连接到你的VPS或云服务器,确保已经安装了Python及Git。本文以CentOS为例,其他发行版大同小异。

    1
    $ sudo yum install certbot
  • 获取证书
    首先停止你服务器上的服务,保证80端口没有被占用并且你的域名被正确解析到你的服务器,否则在证书获取过程中会出现错误。

    1
    $ sudo certbot certonly --standalone -d diunar.tk -d www.diunar.tk    #把diunar.tk换成你的域名

当看到“Congratulations”字样时,代表你已经成功申请到Let’s Encrypt的免费SSL证书,证书有效期是90天,后面会讲如何 续命 延期。
证书文件被保存到了/etc/letsencrypt/live/你的域名/,其中的fullchain.pemprivkey.pem是我们接下来需要用到的完整证书链及私钥


如果你希望在Nginx或Apache等Web服务器上应用你的SSL请在Certbot的官网上查看方法。下面我们用Node.js编写服务器建立HTTPS服务

通过Node.js建立HTTPS服务

  • 为了方便,我们使用Express框架,因此需要安装Express

    1
    $ npm install express
  • 创建index.js

    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
    const express = require('express')
    const fs = require('fs')
    const http = require('http')
    const https = require('https')

    const app = express()
    const port = 80 //HTTP访问端口号,默认80,可更改为你希望的端口号
    const SSLport = 443 //HTTPS访问端口号,默认443,可更改为你希望的端口号

    const options = {
    key: fs.readFileSync('/etc/letsencrypt/live/diunar.tk/privkey.pem'), //异步读取私钥文件
    cert: fs.readFileSync('/etc/letsencrypt/live/diunar.tk/fullchain.pem'), //异步读取证书文件
    requestCert: false, //是否请求客户端证书
    rejectUnauthorized: false //是否拒绝无信任CA颁发的证书的客户端连接请求
    }

    http.createServer(app).listen(port, () => console.log(`HTTP server is listening on port ${port}`)) //创建http服务监听
    https.createServer(options, app).listen(SSLport, () => console.log(`HTTPS server is listening on port ${SSLport}`)) //创建https服务监听

    app.get('/', function(req, res) {
    if (req.protocol == 'https') {
    res.send("This is HTTPS Server")
    } else {
    res.send("This is HTTP Server")
    }
    })

如果不需要HTTP服务可以删除http.createServer(app),只保留HTTPS服务

  • 运行Node.js服务
    1
    2
    3
    $ node index.js
    HTTP server is listening on port 80
    HTTPS server is listening on port 443

在浏览器分别通过http://https://协议访问你的域名,看看有什么区别:


通过浏览器可以看到我们与服务器建立的是密文传输连接:


大功告成之后,别忘了每隔90天通过certbot renew命令进行证书的续订。你也可以设置自动续订,具体方法请见Certbot官网