本文探讨了如何为同一个 VPS 上使用不同端口的 web 应用配置 https。
背景
我在自己的一台 VPS 上部署了多个 web 应用,包括 commafeed,leanote,h5ai,还有 webdav 应用等等。这些应用监听的端口不同,可以通过域名+端口的形式访问。但是这样的访问形式显然不够简洁。另外在全民https的现在,还通过这样的形式访问网站太落伍了。因此,我在网上做了一些搜索,主要参考下列文章:
经过对自己 nginx 配置文件的一番魔改,目前实现的情形如下:
- 可以通过 https 访问二级域名,若通过 http 访问会跳转到 https
- 直接访问域名+端口会出错
未解决的问题是
- 还是可以通过ip+端口访问
在 Cloudflare 上的配置
- 修改域名的 Nameserver 为 Cloudflare 提供的 Nameserver
- 在 Cloudflare 的 DNS 选项下添加自己所需的二级域名的 A 记录,并开启 CDN。

- 在 Crypto 选项下将 SSL 选项修改Full,之后 Cloudflare 就会开始给你分配证书,可能要等挺久的,然后再将下面的 Always use https 选项打开。
- 在 Page Rules 选项下添加 Rule,比如我想要我的所有二级域名都自动跳转到 https

至此,需要在 cloudflare 上配置的地方就结束了。
在 VPS 上的配置
生成自签名的 ssl 证书
- 安装 openssl,例如我用的 archlinux
pacman -S openssl
- 签发证书 (以下内容完全来自用自签名 SSL 证书配合 CloudFlare 免费 SSL 构建全站 HTTPS 加密)
mkdir -p <DIR>/cert //建立制作存放证书的目录
cd <DIR>/cert
# 签发一个根域名的 CA 证书
openssl genrsa -des3 -out ca.key 2048 //创建一个私钥 ca.key
openssl req -new -x509 -days 7305 -key ca.key -out ca.crt //生成 CA 根证书(公钥)
# 其中 days 后面的参数是有效期。执行后会让你填相关信息,common name 填根域名,即 yourdomain.com
openssl genrsa -des3 -out yourdomain.com.pem 1024 //生成一个给泛域名用的私钥
openssl rsa -in yourdomain.com.pem -out yourdomain.com.key //解密私钥
openssl req -new -key yourdomain.com.pem -out yourdomain.com.csr //生成签名请求
# 这一步中的 common name 填入泛域名,即*.yourdomain.com ,这样生成的证书可以供所有子域名使用
vi /etc/openssl.cnf
# 这里修改 dir = 的值为./ca
mkdir -p ca/newcerts
touch ca/index.txt
touch ca/serial
echo "01" > ca/serial
openssl ca -policy policy_anything -days 7305 -cert ca.crt -keyfile ca.key -in yourdomain.com.csr -out yourdomain.com.crt //执行签名
cat ca.crt >> yourdomain.com.crt //把 ca.crt 中的内容粘贴到 yourdomain.com.crt 的最后,证书签发完成
配置 nginx
- 安装 nginx
pacman -S nginx-mainline
- 魔改 nginx,这里贴上自己的配置,写的很垃圾,大家明白意思就行,主要就是使用多个 server 块。
# 前面的配置参考了 cloudflare 和 Mozilla 推荐的配置
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECD$
ssl_prefer_server_ciphers on;
ssl_certificate <DIR>/cert/yourdomain.crt;
ssl_certificate_key <DIR>/cert/yourdomain.key;
server {
listen 443 ssl http2;
server_name note.yourdomain;
location / {
proxy_pass http://127.0.0.1:port1/; //通过 https://note.yourdomain 访问我的 leanote
}
}
server {
listen 443 ssl http2;
server_name rss.yourdomain ;
location / {
proxy_pass http://127.0.0.1:port2/; //通过 https://rss.yourdomain 访问我的 commafeed
}
}
server {
listen 443 ssl http2;
server_name file.yourdomain;
location / {
proxy_pass http://127.0.0.1:port3/; //通过 https://file.yourdomain 访问我的 h5ai
}
location /webdav {
proxy_pass http://127.0.0.1:port4/; //通过 https://file.yourdomain/webdav 访问我的 webdav
}
location /zotero {
proxy_pass http://127.0.0.1:port5/; //通过 https://file.yourdomain/zotero 访问我的另一个 webdav
}
}
}
一些坑
- 在 cloudflare 上的证书生效之前网站会无法访问,chrome 报错ERR_SSL_VERSION_OR_CIPHER_MISMATCH
本文地址 https://blog.liuwm.work/2017/11/05/VPS 上多个 web-server 配置 ssl/
