用自签名 SSL 证书配合 CloudFlare 免费 SSL 构建全站 HTTPS
2016-10-23

之前一段时间,本博客一直在用 letsencrypt 的 SSL 证书。这个证书的优点是免费,然而缺点也很明显,就是使用起来比较麻烦,而且有效期只有 3 个月。 我是个懒人,所以能一劳永逸的事,我都会一次性做完。很早之前就了解到 CloudFlare 有免费的 SSL 证书,但是假如仅在 CloudFlare 后台中开启它的话,并不能做到全站加密,只能开启 Flexible 模式,而不是 Full 模式。

进入 CloudFlare 后台->Crypto,可以看到第一项就是免费提供的 SSL。 这里有4种模式可选:Off(关闭 SSL)、Flexible(视情况而定)、Full(全部加密,需要在服务器上部署证书,但 CloudFlare 不会检查证书的有效性)、Full(Strict)(严格模式,也就是全部加密,而且 CloudFlare 会检查服务器上的证书是否有效)。 在这里,我们的目标是开启 Full 模式,实现方式是:首先自签一个泛域名的证书,然后在 Nginx 中设置通过 HTTPS 访问网站,最后到 CloudFlare 中设置 SSL 模式。 当然,如果你想要开启 Full(Strict) 模式,也是可以的,但服务器上就不能部署自签名的证书了,而需要一个有效机构颁发的证书,例如 letsencrypt 的证书,然而怎么做的缺点就是需要定期续期。

使用自签名证书就不存在这个问题了,你想签多长时间的有效期就可以签多长时间~~(我签了 20 年,2333333)~~,更换服务器时,也仅需要把证书文件拷到新服务器上。

准备工作

第一步,当然是确保你的 DNS 是 CloudFlare 的!

第二步,安装 OpenSSL

debian 系:

# apt-get install openssl

rhel 系:

# yum install openssl

签发自签名证书

首先建立一个生成、存放证书的目录:

# mkdir certificate

进入该目录,然后签发一个根域名的 CA 证书,第一步创建一个私钥 ca.key

# openssl genrsa -des3 -out ca.key 2048

第二步,生成 CA 根证书(公钥):

# openssl req -new -x509 -days 7305 -key ca.key -out ca.crt

命令中,-days 后面的 7305 是指证书的有效期,以天为单位,这里设置成了 20 年,手动滑稽。

执行命令后会让你填一堆地区、组织什么的东西,随便填就好,但注意期间会让你填写 common name,也就是域名,这里填入的是你的根域名,例如 eaimty.com。最后,你就得到了一个根域的 CA 证书。

之后生成一个给泛域名用的私钥:

# 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 要填入泛域名,如 *.eaimty.com,这样生成的证书可以供所有子域使用。

下一步还不能直接执行签名,否则会报错,要先修改一下 openssl 的配置文件:

# vi /etc/pki/tls/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

这一步中的参数和上一步中的意义相同。 最后你会得到一个 yourdomain.com.crt 文件,把 ca.crt 中的内容粘贴到 yourdomain.com.crt 的最后,证书就签发完成了。

准备好 yourdomain.com.crt(网站证书)和 yourdomain.com.key(网站私钥),开始配置 Nginx!

配置 Nginx

这一步很简单,找到你的网站(所签发泛域名的所有子域名都可以用)的 Nginx 配置文件(通常是 /etc/nginx/conf.d/ 下的 XXX.conf)

修改 server{}listen 443 ssl,并在其下添加:

ssl_certificate /path/to/yourdomain.com.crt;
ssl_certificate_key /path/to/yourdomain.com.key;

测试 Nginx 的配置文件是否有错:

# nginx -t

注意看是否报错。

没有问题的话,重启 Nginx。

设置 CloudFlare

开启 CloudFlare SSL

进入 CloudFlare 管理界面,将 Crypto->SSL 改为“Full”。

现在通过浏览器进入 https://你的网站/,你就会发现小绿锁出现了!就说明我们成功了!

设置 HTTP 请求的重定向

虽然小绿锁出现了,但是假如访客直接输入没有声明协议的网址访问网站,默认走的仍是没有 SSL 保护的 HTTP。

我们可以通过 Nginx 来设置,也可以通过 CloudFlare 来设置。我的所有子域名都开启了 SSL,所以我是用 CloudFlare 设置的,更方便。

进入 CloudFlare 后台中的 Page Rules 选项卡,新建如下规则:

这样就可以一次性为所有子域设置重定向了。

然后记得关闭服务器上的 80 端口,以使强制通过 HTTP 协议时无法访问网站。

想要更加安全的话,CloudFlare 的后台中也有 HSTS 的设置,配置好后去 https://hstspreload.org 提交你的域名,就完成全站 HSTS 啦!