正式启用全站 SSL

本来这篇博客应该在几个月前就写完的,不过工作一直太忙,最近电信的国际出口又卡得厉害,因此拖到现在才开始动笔记录。

事情的起因算是我个人的心血来潮吧,毕竟 SSL 加密是大势所趋。

而一开始的时候,我一直没有找到比较好的免费 SSL 证书颁发机构(其实是我孤陋寡闻)。无奈之下暂时选择了沃通的免费证书。

然而沃通近几个月似乎风评不佳,而且听闻 Firefox 也即将不信任沃通签署的证书,因此更换证书颁发机构是早晚的事。

经过一番搜索,最终决定采用 Let’s Encrypt 的免费证书,因为它们的证书签署过程非常简单,完全可以在 VPS 的服务器端完成。

具体的证书申请和签署过程如下:

1、首先安装 Let’s Encrypt 的证书部署客户端,以我服务器的 Arch 为例:

# pacman -S certbot certbot-apache

2、然后针对自己的域名相应签署证书(每个虚拟主机单独签署一次)。这里我采用的是 webroot 模式,-w 参数指定主机或虚拟主机的根目录(必须要和虚拟主机的配置文件保持一致,否则会报错),-d 参数指定主机或虚拟主机的域名。

# certbot certonly --webroot -w /home/woodelf/public_html/www -d woodelf.org -d www.woodelf.org

3、证书签署完成后,会在 /etc/letsencrypt/live 下为各个虚拟主机生成单独的证书目录,其中包含以下四个文件:

cert.pem - Apache 服务器端证书

chain.pem - Apache 根证书和中继证书

fullchain.pem - Nginx 所需要的 ssl_certificate 文件

privkey.pem - 安全证书 key 文件

4、在 Apache 配置文件中进行如下设置,比如我的配置文件是 /etc/httpd/conf/httpd.conf

#启用 SSL 配置文件
Include conf/extra/httpd-ssl.conf
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

5、在 httpd-ssl.conf 中针对每个虚拟主机进行类似如下设置:

#采用 /dev/urandom 作为 SSL Seed
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512

#监听 443 端口
Listen 443

#设置虚拟主机
<VirtualHost *:443>
    ServerAdmin wood_elf@126.com
    DocumentRoot "/home/woodelf/public_html/www"
    ServerName woodelf.org
    ServerAlias www.woodelf.org
    ErrorLog "/var/log/httpd/woodelf.org-error_log-ssl"
    LogLevel warn
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES
    SSLCertificateFile /etc/letsencrypt/live/woodelf.org/cert.pem
    SSLCACertificateFile /etc/letsencrypt/live/woodelf.org/chain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/woodelf.org/privkey.pem
    <Files ~ "\.(cgi|shtml|phtml|php3?)$">
        SSLOptions +StdEnvVars
    </Files>
    <Directory "/var/www/cgi-bin">
        SSLOptions +StdEnvVars
    </Directory>
    SetEnvIf User-Agent ".*MSIE.*" \
             nokeepalive ssl-unclean-shutdown \
             downgrade-1.0 force-response-1.0
    CustomLog logs/ssl_request_log \
              "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

然后重启 Apache 服务即可。

这样设置以后,所有 Http 请求都会发往虚拟主机指定的 webroot,但是如果不对每个虚拟主机指定 webroot,那么就会默认发往上一个已定义的 webroot。

因此,为了方便管理,我们需要把所有虚拟主机的 webroot 映射到一个固定目录,如 /var/lib/letsencrypt

为此,需要在 Apache 配置文件中加入以下内容:

# Enable ACME redir
Include conf/extra/httpd-acme.conf

另外,在 httpd-acme.conf 中进行如下设置:

Alias /.well-known/acme-challenge/ "/var/lib/letsencrypt/.well-known/acme-challenge/"
<Directory "/var/lib/letsencrypt/">
    AllowOverride None
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS
</Directory>

到这里就大功告成了。