开启https的过程遇到了比较多的问题,这里梳理一下。

Document Server开启https

首先按官方的流程创建一个容器

  1. sudo docker run -i -t -d -p 443:443 --restart=always \
  2. -v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data onlyoffice/documentserver-de

onlyoffice默认会在容器的 /var/www/onlyoffice/Data 目录下查找SSL证书,通过 -v 我们把电脑上的 /app/onlyoffice/DocumentServer/data 映射给容器的 /var/www/onlyoffice/Data。然后我们根据官方指引生成证书到 /app/onlyoffice/DocumentServer/data 目录下

  1. openssl genrsa -out onlyoffice.key 2048
  2. openssl req -new -key onlyoffice.key -out onlyoffice.csr
  3. openssl x509 -req -days 365 -in onlyoffice.csr -signkey onlyoffice.key -out onlyoffice.crt
  4. openssl dhparam -out dhparam.pem 2048
  5. mkdir -p /app/onlyoffice/DocumentServer/data/certs
  6. cp onlyoffice.key /app/onlyoffice/DocumentServer/data/certs/
  7. cp onlyoffice.crt /app/onlyoffice/DocumentServer/data/certs/
  8. cp dhparam.pem /app/onlyoffice/DocumentServer/data/certs/
  9. chmod 400 /app/onlyoffice/DocumentServer/data/certs/onlyoffice.key

按照官方指引完成之后,看似一切正常,但是访问 https://localhost 直接失败。。。通过查看docker的日志发现是 /var/www/onlyoffice/Data/certs 目录,即 /app/onlyoffice/DocumentServer/data/certs 没有权限导致的。通过以下命令可以查看对应文件权限:

  1. docker exec -it 09 bash
  2. ll /var/www/onlyoffice/Data/certs

image.png
修改权限

  1. exit
  2. chmod -R 755 /app/onlyoffice/DocumentServer/data/certs
  3. docker exec -it 09 bash
  4. ll /var/www/onlyoffice/Data/certs

image.png
重启容器,访问https://localhost,成功。

node example开启https

直接上代码吧,修改 /bin/www

  1. #!/usr/bin/env node
  2. var debug = require("debug")("OnlineEditorsExampleNodeJS");
  3. var app = require("../app");
  4. var path = require("path");
  5. var config = require('config');
  6. var fileSystem = require("fs");
  7. var https = require('https');
  8. var privateCrt = fileSystem.readFileSync(path.join(process.cwd(), 'https/onlyoffice.crt'), 'utf8');
  9. var privateKey = fileSystem.readFileSync(path.join(process.cwd(), 'https/onlyoffice.key'), 'utf8');
  10. var HTTPS_OPTOIN = {
  11. key: privateKey,
  12. cert: privateCrt
  13. };
  14. var SSL_PORT = 3001;
  15. var HTTP_PORT = process.env.PORT || config.get('server.port') || 3000;
  16. app.set("port", HTTP_PORT);
  17. var server = app.listen(app.get("port"), function() {
  18. debug("Express server listening on port " + server.address().port);
  19. });
  20. var httpsServer = https.createServer(HTTPS_OPTOIN, app);
  21. httpsServer.listen(SSL_PORT, function() {
  22. console.log(`HTTPS Server is running on ${SSL_PORT}`);
  23. });

启动后通过3001端口访问https页面,在浏览器正常打开,再创建个文档试试,提示文档无法保存且报错文件下载失败。。。
再看下docker日志,发现以下报错:
image.png
自签证书导致的
可以通过修改容器的 /etc/onlyoffice/documentserver/default.json 文件内的 rejectUnauthorized 为 false 来取消这个证书的验证。
你可能需要先通过以下命令先安装vim

  1. apt-get update
  2. apt-get install vim

如果docker内无法安装可以把docker内的文件复制出来修改

  1. docker cp CONTAINER_ID:/etc/onlyoffice/documentserver/default.json /home
  2. docker cp /home CONTAINER_ID:/etc/onlyoffice/documentserver/default.json

修改完成后重启容器,一切正常运行~
解决办法很简单,寻找办法过程确很痛苦,痛苦的主要来源:对docker和SSL证书了解程度不够。

怎样的证书才被信任?

打开百度可以看到以下三级的证书结构
image.png
其中, Global Root CA 是根证书。它已经在我们的客户端本地存储,以 macos 为例,可以通过 keychain 查找到。
在中间的这一个证书,称为中级证书
最底下的证书就是在服务端配置好的证书。

服务器的证书由中级证书负责签名,而其中级证书又由根证书负责签名。根证书通常是值得信任的机构,因为其必须遵守严格要求、审计、公众审查等。这一切都是为了保持证书颁发机构的社会信任。

在我们访问 https 的站点资源时,虽然服务器配置好的相关的证书,但我们如何能够验证该证书的有效性呢?浏览器会收到证书本身以及与证书关联的公共密钥。它使用公钥验证数字签名,并查看签名者是由什么证书签名,并且超上一个链接移动,继续对上一个签名进行身份验证,并跟踪签名它的证书的链——直到最终它到达浏览器信任库中的根证书之一。如果无法将证书链接回其受信任的根目录之一,则它将不信任该证书。

整个过程就是一个证书链。
即 Server certificate -> Intermediate certificate(中级证书, 这中间可能会链接到另一个中级证书)-> Root certificate 。

中级证书

为什么会产生中级证书,直接从服务端的证书到最后的根证书不是更高效么?
原因是根证书太宝贵了,而颁发证书的风险太大。于是根证书颁发了很多中级证书,即 CA (证书颁发机构)用自己的私钥进行签名,使中级证书可信任。CA 有了中级证书之后,以后就都用中级证书自己的私钥来签名并颁发给最终用户 SSL 证书(即服务端配置的证书)。

所以,
根证书: 受权威机构信任,已经在用户设备中存储;
中级证书:由根证书签名而得到信任,负责给下一级的证书签名;
服务端证书:由中级证书签名而得到信任。

通过颁发中级证书并使用中级证书签署证书,增加根证书的安全性。这有助于在发生误发或安全事件时最小化和划分损害,当安全事件发生时,不需要撤销根证书,只需撤销中级证书,使从该中级证书发出的证书组不受信任。