资讯专栏INFORMATION COLUMN

Node.js 部署免费/自动续订 HTTPS

seanlook / 961人阅读

摘要:当时结合本站的部署经验,给大家详细介绍了部署免费。截止年月日,由实时统计报告显示,在统计的多万活跃网站中,已经有万约的站点部署了证书服务。

随着互联网快速发展,互联网信息安全越来越受到大家重视,HTTPS 应该是近两年各大厂商都在尽力普及的技术之一。国内大厂基本上已经全面普及了 HTTPS。

本文首发于我的个人网站:听说 - https://tasaid.com/,建议在我的个人网站阅读,拥有更好的阅读体验。

前端开发 QQ 群:377786580
HTTPS 现状

早在 2016 年底,我就写过 《 从 HTTP 到 HTTPS 系列 》文章来讲解 HTTPS。当时结合本站的部署经验,给大家详细介绍了 《 IIS 部署免费 HTTPS 》。

这篇文章就跟大家介绍一下 Node.js 如何部署免费 HTTPS 以及简单的部署 HTTP/2

截止 2018 年 03 月 13 日,由 Let"s Encrypt 实时统计报告 显示,在统计的 6930 多万活跃网站中,已经有 5350 万(约 77%)的站点部署了 HTTPS 证书服务。

同时 Google 透明度报告 - 网络上的 HTTPS 加密 中,统计了使用 Chrome 浏览器,访问的站点统计中,HTTPS 使用率的增长情况:

而在今年 2 月份,Chrome 团队也宣布,将在 2018 年 7 月份发布的 Chrome 68 中,将没有部署 HTTPS 的网站标记为 "不安全"。

简而言之,HTTPS 大势所趋。

Node.js 部署 HTTPS

早在 《 从 HTTP 到 HTTPS - IIS 部署免费 HTTPS 》一文中,我就指出了 Let"s Encrypt 免费证书的优势:

由 ISRG(Internet Security Research Group,互联网安全研究小组)提供服务,免费、访问速度快,稳定等。

所以这次部署的证书也是围绕 Let"s Encrypt 展开。

greenlock-express

由于 js 生态圈的繁华,所以想找一个现有的包是件很轻松的事情,greenlock-express 这个包就帮助我们封装了 Let"s Enctrypt 证书的部署,只需要引入这个包并使用,就可以:

自动注册 Let"s Encrypt 证书

自动续订( 80 天左右),且服务器无需重启

支持虚拟主机

并且 greenlock 相关的证书生态圈十分完善,同样有支持 koa 的 greenlock-koa。

安装和使用

通过 npm 安装 greenlock-express

$ npm install --save greenlock-express@2.x

使用起来非常简单,这是 greenlock-express 默认提供的 demo:

const greenlock = require("greenlock-express")

require("greenlock-express").create({
  // 测试
  server: "staging",
  // 联系邮箱
  email: "john.doe@example.com",
  // 是否同意 Let"s Encrypt 条款... 这必须为 true 啊,不然走不下去
  agreeTos: true,
  // 申请的域名列表,不支持通配符
  approveDomains: [ "tasaid.com", "www.tasaid.com" ],
  // 绑定 express app
  app: require("express")().use("/", function (req, res) {
    res.end("Hello, World!");
  })
}).listen(80, 443)

证书存在 ~/letsencrypt

当然上面代码只能用于测试/开发环境,因为它并没有申请一个有效的证书,而是生成了一个自签名的证书(跟以前的 12306 自签证书一样),用于在开发环境中调试。

API

greenlock-expresscreate(options) 函数参数签名如下:

interface Options {
  /**
   * Express app
   */
  app: Express
  /*
   * 远程服务器
   * 测试环境中可用为 staging
   * 生产环境中为 https://acme-v01.api.letsencrypt.org/directory
   */
  server: string
  /**
   * 用于接收 let"s encrypt 协议的邮箱
   */
  email: string
  /**
   * 是否同意协议
   */
  agreeTos: boolean
  /**
   * 在注册域名获取证书前,会执行这个回调函数
   * string[]: 一组需要注册证书的域名
   * 函数: 第一个参数跟 Options 格式差不多,第二个参数是当前自动获取的域名信息,第三个参数是在处理完之后传递的回调函数
   */
  approveDomains: string[] | (opts, certs: cb) => any
  /**
   * 更新证书最大天数 (以毫秒为单位)
   */
  renewWithin: number
  /**
   * 更新证书的最小天数(以毫秒为单位)
   */
  renewBy: number
}

经过测试,在真实的生产环境中, approveDomains 必须为函数,传数组的话不会生效。

生产环境

生产环境中部署还需要做一些配置改动和引入一些包。

更新包:

$ npm i --save greenlock-express@2.x
$ npm i --save le-challenge-fs
$ npm i --save le-store-certbot
$ npm i --save redirect-https

生产代码:

const greenlock = require("greenlock-express")
const express = require("express")

const app = express()


const lex = greenlock.create({
  // 注意这里要成这个固定地址
  server: "https://acme-v01.api.letsencrypt.org/directory",
  challenges: { 
    "http-01": require("le-challenge-fs").create({ webrootPath: "~/letsencrypt/var/acme-challenges" }) 
  },
  store: require("le-store-certbot").create({ 
    webrootPath: "~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge" 
  }),
  approveDomains: (opts: any, certs: any, cb: any) => {
    appLog.info("approveDomains", { opts, certs })
    if (certs) {
      /*
       * 注意这里如果是这样写的话,一定要对域名做校验
       * 否则其他人可以通过将域名指向你的服务器地址,导致你注册了其他域名的证书
       * 从而造成安全性问题
       */
      // opts.domains = certs.altnames
      opts.domains = [ "tasaid.com", "www.tasaid.com" ]
    } else {
      opts.email = "你的邮箱@live.com"
      opts.agreeTos = true
    }
    cb(null, { options: opts, certs: certs })
  },
})

// 这里的 redirect-https 用于自动将 HTTP 请求跳到 HTTPS 上
require("http").createServer(
  lex.middleware(
    require("redirect-https")()
   )
  ).listen(80, function () {
    console.log("Listening", `for ACME http-01 challenges on: ${JSON.stringify(this.address())}`)
})
// 绑定 HTTPS 端口
require("https").createServer(
    lex.httpsOptions, 
    lex.middleware(app)
  ).listen(443, function () {
    console.log(("App is running at http://localhost:%d in %s mode"), app.get("port"), app.get("env"))
    console.log("Press CTRL-C to stop
")
})

如果没有生效,可以检查下 ~/letsencrypt 的证书信息,和 443 端口是否打开。

部署 HTTP/2

HTTP/2 是 HTTP/1.1 的升级版,主要来说改进了这些地方:

二进制协议:采用二进制流

多路复用:一次请求多次复用管道

服务器推送:解决 HTTP/1.x 时代最大的痛点

值的注意的是,HTTP/2 是支持 HTTP 协议的,只不过浏览器厂商都不愿意支持 HTTP,所以基本上可以认为,用上 HTTP/2 的前置条件是必须部署 HTTPS。

SPDY

早在 2009 年,Google 开发了一个实验性协议,叫做 SPDY,目的解决 HTTP/1.x 中的一些设计缺陷。在 SPDY 发布几年后,这个新的实验性协议得到了 Chrome、Firefox 和 Opera 的支持,应用越来越广泛。然后 HTTP 工作组 (HTTP-WG) 在这个 SPDY 的基础上,设计了 HTTP/2,所以可以说 SPDY 是 HTTP/2 的前身。

关于 HTTP/2 的详情可以参考 这篇文章。

部署 HTTP/2

引入 HTTP/2Node.js 中也十分简单,只需要引入 spdy 包即可:

$ npm i --save spdy

然后我们把上一节的代码做一点修改即可支持 HTTP/2:

const greenlock = require("greenlock-express")
const express = require("express")
// HTTP/2
const spdy = require("spdy")

const app = express()


const lex = greenlock.create({
  // 注意这里要成这个固定地址
  server: "https://acme-v01.api.letsencrypt.org/directory",
  challenges: { 
    "http-01": require("le-challenge-fs").create({ webrootPath: "~/letsencrypt/var/acme-challenges" }) 
  },
  store: require("le-store-certbot").create({ 
    webrootPath: "~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge" 
  }),
  approveDomains: (opts: any, certs: any, cb: any) => {
    appLog.info("approveDomains", { opts, certs })
    if (certs) {
      /*
       * 注意这里如果是这样写的话,一定要对域名做校验
       * 否则其他人可以通过将域名指向你的服务器地址,导致你注册了其他域名的证书
       * 从而造成安全性问题
       */
      // opts.domains = certs.altnames
      opts.domains = [ "tasaid.com", "www.tasaid.com" ]
    } else {
      opts.email = "你的邮箱@live.com"
      opts.agreeTos = true
    }
    cb(null, { options: opts, certs: certs })
  },
})

// 这里的 redirect-https 用于自动将 HTTP 请求跳到 HTTPS 上
require("http").createServer(
  lex.middleware(
    require("redirect-https")()
   )
  ).listen(80, function () {
    console.log("Listening", `for ACME http-01 challenges on: ${JSON.stringify(this.address())}`)
})

// HTTP/2
spdy.createServer(lex.httpsOptions, lex.middleware(app)).listen(443, function () {
  console.log("Listening https", `for ACME tls-sni-01 challenges and serve app on: ${JSON.stringify(this.address())}`)
})

至于 HTTP/2 相关的技术应用,会在后续篇幅中再为大家讲解。

本文首发于我的个人网站:听说 - https://tasaid.com/,建议在我的个人网站阅读,拥有更好的阅读体验。

前端开发 QQ 群:377786580

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/11345.html

相关文章

  • 10分钟搭建ubuntu+nodejs+pm2自动部署+nginx+永久免费SSL证书+mongod

    摘要:将第二步中的安装源换成阿里云的镜像安装会比较快,如下将上面的部分替换如下更新源正式安装常用命令本地和服务器使用公钥免密访问仓库在使用协议访问项目仓库之前,需要先配置好账户项目的公钥。 如果你对nodejskoa2vuejs等感兴趣,请加QQ群:732189938 或者直接点击链接加入群聊【Node.js/Koa2/vuejs】:https://jq.qq.com/?_wv=1027&k...

    godlong_X 评论0 收藏0
  • 10分钟搭建ubuntu+nodejs+pm2自动部署+nginx+永久免费SSL证书+mongod

    摘要:将第二步中的安装源换成阿里云的镜像安装会比较快,如下将上面的部分替换如下更新源正式安装常用命令本地和服务器使用公钥免密访问仓库在使用协议访问项目仓库之前,需要先配置好账户项目的公钥。 如果你对nodejskoa2vuejs等感兴趣,请加QQ群:732189938 或者直接点击链接加入群聊【Node.js/Koa2/vuejs】:https://jq.qq.com/?_wv=1027&k...

    YuboonaZhang 评论0 收藏0
  • cdhelasticsearch介绍

      cdhelasticsearch是Amazon Elasticsearch Service的命令行界面(CLI)工具。它可以帮助您在本地系统上管理和使用您的Amazon Elasticsearch集群cdhelasticsearch是一个开源工具,可以在GitHub上免费下载。它使用Node.js开发,并在命令行中运行。  使用cdhelasticsearch,您可以执行以下操作:  创建、...

    白马啸西风 评论0 收藏0

发表评论

0条评论

seanlook

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<