给网站增加 SSL 证书
现在的 Chrome 浏览器会将非 https 的网站标记为 不安全 ,https 的则是显示一把锁的样子,之前一直觉得升级很麻烦还要申请证书,这次因为放在七牛云上的图片需要以 https 访问,进行了所有站点的 https 的升级,本文记录升级遇到的一些问题和解决办法
七牛云的 ssl 证书
七牛云的域名开启 https ,我在自己的服务器上操作了半天,上传的本地证书各种不合格,后来发现直接用七牛云提供的免费证书就可以了,申请只花了 15 分钟。
而且最后发现之前的那个问题是我理解错了,并不需要用 https 链接的图片,但是既然开了就留着用吧
其他域名的 ssl 证书
熟悉我网站的伙伴都知道,我的站点系列有四五个左右,子域名使用的比较多,针对这样的情况我想用的方式是申请一涨通配符证书,这样我的子域名都可以使用这张证书,如果为每个子域名都申请一个的话太麻烦了,而且维护也不方便。
获取证书
通过调研发现 Let's Encrypt
可以提供免费的 ssl 证书,由于只是小网站,用付费的一年几千的证书大可不必,这种免费的就足以满足我的需求,但是它的缺点是只有 90 天的有效期,过了 90 天就得重新申请,以前我觉得麻烦的点也是在这里,然后最近在寻找这块的消息的时候发现了一个比较好用的脚本 acme.sh ,它的作用就是可以从 Let's Encrypt
生成免费证书,而且每隔一段时间(在当前证书失效前)会自动更新证书,这样就解决了 90 天有效期的麻烦。
安装 acme.sh
curl https://get.acme.sh | sh -s email=my@example.com
执行成功后这个脚本就被安装到了 home 目录下,地址为 ~/.acme.sh/
生成证书
生成证书我这里是采用的 dnsapi 的方式, 文档链接 ,这个方式是最简单方便的方式,其他的方式我试过之后发现如果要生成多域名的就总是有问题,最后采用这个方式是可以成功的。上面文档中列出了十几种 dns 服务商的处理方式,可以根据自己域名提供商的实际情况选用,我的域名是买自阿里云的
按照操作先去生成 Ali_Key 和 Ali_Secret ,这里有一点要注意的是,进去 账户设置 阿里云会推荐你使用子账户来进行后续的操作,这个安全性我觉得是必要的,生成了子账户之后,根据提示,将账户信息保存一下,然后要给这个子账户添加权限,要添加上对应的权限才能调用 dnsapi 的,不是生成就可以调用的 。
权限添加的弹窗这里,在策略的搜索框输入 dns 可以帮助我们快速的过滤出我们想要找的策略,选择 管理云解析(DNS) 这项,我这里因为已经添加过了所以是不可选的,选择之后会出现在右边的框里,然后点击确定按钮,你的子账户的 key 和 secret 就可以操作 dnsapi 了。
依次输入命令并执行后,执行完成后会有 success 的相应提示,然后把证书给你放在什么位置了等等,这里的可以输入多个 -d 和域名,最后只会生成一个证书,生成证书的时候可以按通配符生成,以第一个输入的域名为名字
export Ali_Key="AccessKey ID"
export Ali_Secret="AccessKey Secret"
cd ~/.acme.sh/
acme.sh --issue --dns dns_ali -d jjdxb.top -d *.jjdxb.top
安装证书
新建目录 /etc/nginx
,文件不用新建,执行命令的时候会自动创建,安装证书的时候使用生成证书时的名字
acme.sh --install-cert -d jjdxb.top --key-file \
/etc/nginx/key.pem --fullchain-file /etc/nginx/cert.pem \
--reloadcmd "nginx -s reload"
查看证书
查看已生成的证书的信息,同理也是要输入证书名字
./acme.sh --info -d jjdxb.top -d blog.jjdxb.top -d blog.lovem.fun -d code.jjdxb.top
配置 nginx
首先确定下自己当前的 nginx 是否安装了 ssl 模块 --with-http_ssl_module
,通过命令 nginx -V
,从执行结果可以看到对应的模块是已安装的,如果没有安装该模块的话需要先安装一下,
[ali-server ~]# nginx -V
nginx version: nginx/1.8.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
built with OpenSSL 1.0.1j 15 Oct 2014
TLS SNI support enabled
configure arguments: --user=nobody --group=nobody --prefix=/service/nginx --with-pcre=/service/pcre-8.33 --with-zlib=/service/zlib-1.2.11 --with-openssl=/service/openssl-1.0.1j --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-http_sub_module --with-http_ssl_module
原先我的配置都是监听 80 端口,然后根据不同的域名给他们做不同的配置,开启 ssl 即访问 https 的话是访问 443 端口,所以我们可以很自然的想到,只要把原来的 80 端口换成 443 端口,按照 ssl 配置要求配置上就可以实现我们的效果了,访问 80 端口(以 http 的方式访问)的时候将他们都转发到 https 的链接上,这样保证了用户访问的一定是 https 的链接。OK,接下来看下具体的配置
首先因为我所有的域名用的是一个证书,也就是说他们的 ssl 配置是相同的,我将这个配置单独写入一个文件,然后通过 include 的方式引入,便于后续的维护,这是我能想到的比较好的解决办法,如果有更简便的方法还请在评论区不吝赐教
# 在 vhosts 下新建 ssl.configure 文件,放置 ssl 公共配置
# 因为在 vhosts 下所有 .conf 后缀的都会被引入 nginx 配置中,所以文件后缀写为 configure
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/key.pem;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# jjdxb.top, www.jjdxb.top 站点的配置
# 其他几个子域名的配置改动和这个基本一致
server {
listen 80;
server_name jjdxb.top;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 443 ssl;
server_name jjdxb.top www.jjdxb.top;
charset utf-8;
access_log logs/home_jjdxb_top.access.log;
error_log logs/home_jjdxb_top.error.log;
include vhosts/ssl.configure; # 引入 ssl 公共配置
location / {
try_files $uri $uri/ /index.html;
root /service/nginx/html/home/;
index index.html index.htm;
}
}
配置到这里就 OK 了,访问网站就都是 https 了
小结
- 通配符这种写法还是看 issues 里看到的,想着试一下,发现真的可行
- 子账户还要再添加一下权限才能用