后台管理网站的时候希望能够加密数据,特别是密码、加密文章之类的数据需要加密传输。为了安全咱也赶赶新潮在 VPS 上部署了 SSL 加密服务,以后登录和管理 WordPress 以及 phpMyAdmin 的时候就可以使用 HTTPS 加密链接访问了。木有money,只好用 OpenSSL 自己签发(Self-Signed)个证书了。
至于部署加密链接的好处,可以参考之前转发的一篇文章 Google 加密链接,这里就不啰嗦了。下面直接记录部署过程。
0. 准备工作¶
在安装之前还是要声明一下我的前期工作,也就是目前这个 VPS 的状态。
这个 VPS 上部署了 LAMP + phpMyAdmin 来提供服务。当然 VPS 使用的是 Linode 的,这个应该没有关系。因为是 CentOS,下面的操作记录就把参考资料中提到的其它 Linux 发行版的命令行剔除了,如有需要可参考文后提供的参考资料。
1. 安装 openssl¶
对于前面描述的需要,就不值当去购买商业 SSL 证书了,GoDaddy 的 SSL 证书标准版也要 $69.99/年呢,虽然第一年只要 $12.99(如果你不小心点了这个链接,注意看打开页面导航菜单下面的提示信息 :D)。所以下面安装的是自己用 openssl 生成的证书(自己签发,Self-Signed)。
以 root 身份登录 VPS,执行下述命令行,
yum install openssl
也许收到的提示是 Nothing to do,那说明早就安装好了。
2. 使用 Apache 自己签发一个 SSL 证书¶
- 首先为 Apache 安装 mod_ssl 模块,
yum install mod_ssl
- 创建保存证书的目录,
mkdir /etc/httpd/ssl
- 为了生成 2048 bit 的 SSL 证书,我们先用下面的命令设定加密等级:
openssl genrsa -out mydomain.key 2048
-out 指定输入的文件为 mydomain.key。输出类似于:
# openssl genrsa -des3 -out mydomain.key 2048 Generating RSA private key, 2048 bit long modulus ........................+++ ...............................................................................................+++ e is 65537 (0x10001)
这里用域名作为文件名是为了方便区分哪个子域名用了哪个证书。
- 然后使用下面的指令生成证书签发请求(certificate signing request (CSR))和证书密钥(certificate key),
openssl req -new -nodes -sha256 -key mydomain.key -out mydomain.csr
运行上述命令后会被询问几个配置参数,如下所示。比如组织所在地、名称,服务器名称等。地址等可以留空。如果要留空的话可以直接输入一个 .(英文圆点)。因为这个证书将用于通用的 SSL 服务,这里使用 FQDN(fully qualified domain name,完全认证域名,比如我的 cnzhx.net )作为 “Common Name” 条目(注意下面空行前的最后两行)。例如,([ ] 中的内容是程序根据服务器配置自动填充的,可能有所不同,没关系)
# openssl req -new -nodes -key cnzhx.net.key -out cnzhx.net.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:CnZhx Locality Name (eg, city) [Default City]:CnZhx Organization Name (eg, company) [Default Company Ltd]:CnZhx Organizational Unit Name (eg, section) []:CnZhx Common Name (eg, your name or your server's hostname) []:cnzhx.net Email Address []:support@cnzhx.net Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
上面最后两个是附加信息,也可以不填,直接回车即可。
需要特别注意的是:Common Name 这里输入的是 cnzhx.net,则这个证书只对 cnzhx.net 有效,而对 www.cnzhx.net 无效。实际上 www.cnzhx.net 应该归到 *.cnzhx.net 里面,重新针对 *.cnzhx.net 生成一个证书即可。即,Common Name 那里填入 *.cnzhx.net(支持通配符的)。如果需要的话,也可以针对所有的子域名生成一个“通配符”的:openssl req -new -nodes -sha256 -key cnzhx.net.key -out sub.cnzhx.net.csr
只不过,针对这个 sub.cnzhx.net.csr,请记得在 Common Name 那里输入 *.cnzhx.net(当然记得换成自己的域名)。我这里是懒得麻烦,直接用刚才那个 cnzhx.net.key 来签发自己的所有证书了。也可以针对不同的应用设置不同的 key,只是对我来说没有必要。我仅仅是为了加密传输中的数据,穿着衣服就行了,不需要太多伪装。
不过,既然是自己签发的证书,这个其实也没所谓啦,反正是自个儿说了算,对 cnzhx.net 和所有子域名都使用同一个证书也没什么大不了的。 - 下面使用刚才产生的证书签发请求(CSR)来生成一个证书,还是以我的根域名 cnzhx.net 为例。我这里指令和输出为:
# openssl x509 -req -days 3650 -sha256 -in mydomain.csr -signkey mydomain.key -out mydomain.crt Signature ok subject=/C=CN/ST=CnZhx/L=CnZhx/O=CnZhx/OU=CnZhx/CN=cnzhx.net/emailAddress=support@cnzhx.net Getting Private key
上面的命令中,
- x509 表示 X.509 Certificate Data Management;
- 使用 -days 来指定有效期,我写了 3650 天,可以随意更改,反正长些比较省事儿;
- 详细参数说明请参考 OpenSSL 文档。
- 现在我们已经得到了需要的证书 mydomain.crt,mydomain.csr 已经没用了,可以删除。
# rm mydomain.csr -f
- 将生成的 mydomain.key 和 mydomain.crt 移动到前面创建的 Apache 服务器的 SSL 证书目录(前面创建的保存证书的目录),然后按照下面的介绍来配置服务器使用此证书即可。对了,刚才操作生成的 3 个文件都在刚才执行命令行的当前目录下,别找不到了。
3. 配置 Apache 使用自己签发的证书¶
Apache 目前还不支持使用基于名称的 SSL 虚拟主机配置。所以下面使用一个 IP 地址来给多个虚拟主机提供 SSL 服务。
编辑虚拟主机配置文件 vhost.conf(参考以前安装时的配置文件),当然也可以另外在相同目录下创建一个 vhostssl.conf 文件来单独放 SSL 服务的配置,设置希望启用 HTTPS 加密链接的网站的虚拟主机配置文件中的 VirtualHost。使用下面的模板来为每个需要使用 SSL 服务的网站创建配置,注意根据实际情况修改参数。
注:mozilla 有个很好的脚本可以用于产生较为通用的 HTTPS 配置文件,见 Mozilla SSL Configuration Generator。
# 安装 SSL 模块的时候已经 # 自动在 Apache 的配置中启用了这个监听端口 # #<IfModule mod_ssl.c> # Listen 443 #</IfModule> #<IfModule mod_gnutls.c> # Listen 443 #</IfModule> <IfModule mod_ssl.c> # If you add NameVirtualHost *:443 here, you will also have to change # the VirtualHost statement in /etc/apache2/sites-available/default-ssl # to <VirtualHost *:443> # Server Name Indication for SSL named virtual hosts is currently not # supported by MSIE on Windows XP. NameVirtualHost 12.34.56.78:443 # ipv6 地址需要用方括号 [ ] 括起来 NameVirtualHost [2400:8900::f03c:91ff:fedf:9b24]:443 <VirtualHost 12.34.56.78:443 [2400:8900::f03c:91ff:fedf:9b24]:443> SSLEngine On SSLProtocol all -SSLv3 Header add Strict-Transport-Security “max-age=31536000″ SSLHonorCipherOrder On SSLCompression off SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA SSLCertificateFile /etc/httpd/ssl/cnzhx.net.crt SSLCertificateKeyFile /etc/httpd/ssl/cnzhx.net.key ServerAdmin info@cnzhx.net ServerName cnzhx.net DocumentRoot /srv/www/cnzhx.net/html [...... 这里省略了很多其它配置没写 ......] ErrorLog /srv/www/cnzhx.net/logs/ssl.error.log CustomLog /srv/www/cnzhx.net/logs/ssl.access.log combined </VirtualHost> </IfModule>
# 之所以注释掉下面这行,是因为我采用的是新建一个文件:/etc/httpd/conf.d/vhostssl.conf 来放置 SSL 的配置。做法很简单:
- 将 vhost.conf 中的所有内容复制到新建文件 vhostssl.conf 中;
- 然后修改:
- 注意将上面标记为红色的部分对应修改一下(原来后面的端口是 80);
- 然后按照每个虚拟主机对应修改上面标记为蓝色的部分;
- 其它部分保持不变。
- 如果有不想启用 SSL 服务的虚拟主机,在新配置文件中将其对应的所有配置删除。
- 如果有非正常端口访问的网站,比如我用的非正常端口访问的 phpMyAdmin,这个情况就有点儿复杂了。因为 HTTP 和 HTTPS 不能使用同一个端口,所以解决方法有两种,
- 方法一:新开一个端口用于 HTTPS 访问 phpMyAdmin,比如 2084,那么就需要在 vhostssl.conf 中 NameVirtualHost 12.34.56.78:443 下面增加两行
Listen 2084 NameVirtualHost 12.34.56.78:2084
然后再对应修改 vhostssl.conf 中 phpMyAdmin 对应的部分(使用上面的新端口,而不是 443);
- 方法二:禁止使用 HTTP 非加密访问 phpMyAdmin,这样就可以把原来的端口 2082 用于 HTTPS 访问 phpMyAdmin,而不需要新用一个端口,剩下的与 A 的操作类似,但是特别要注意的是,此时必须删除 vhost.conf 中关于 phpMyAdmin 的配置。
- 方法一:新开一个端口用于 HTTPS 访问 phpMyAdmin,比如 2084,那么就需要在 vhostssl.conf 中 NameVirtualHost 12.34.56.78:443 下面增加两行
- 完成,先测试一下配置是否有参数错误,然后重启 Apache 服务,
apachectl configtest systemctl restart httpd
即可使用。
不过此时使用 HTTPS 加密连接访问网站的话会总是提示收到提示说网站使用的安全证书不是由受信任的机构发布的,很烦人的。所以干脆将安全证书添加为“受信任的根证书”吧。
4. 配置 WordPress¶
可以将 WordPress 配置为必须使用 HTTPS 加密连接来访问登陆页面和管理后台。
修改 wp-config.php,在
/* That's all, stop editing! Happy blogging. */
之前,加上
define('FORCE_SSL_ADMIN', true);
可以使得后台强制加密访问;而加入一行
define('FORCE_SSL_LOGIN', true);
可以使登录页面强制加密访问。
我是两个语句都加了。
5. 参考资料¶
- Linode Library: How to Make a Self-Signed SSL Certificate
- Linode Library: SSL Certificates with Apache 2 on CentOS 5 & 6
- OpenSSL Documents
- 为WORDPRESS配置后台/登录页面强制HTTPS加密
- Hardening Your Web Server’s SSL Ciphers
- 5 easy tips to accelerate SSL
更新于 2013.06.18,改为 2048 bit 的 SSL 证书。
更新于 2014.12.12,增加一些 conf 文件中增加 SSL 安全性的设置。
更新于 2015.10.05,SHA1 快要被完全废弃了,升级一下,使用 SHA2。尽管 Let’s Encrypt 都要出来了,我还是打算用自签名的作为 phpMyAdmin 的加密证书。©
本文发表于水景一页。永久链接:<https://cnzhx.net/blog/ssl-on-lamp-on-vps/>。转载请保留此信息及相应链接。
嘿嘿…
我没安装openssl,是在http://www.startssl.com/申请的…
自签名是红色的…
不错啊,还有免费的。
不过自己用的话,免费的和自己签的没什么分别。
P.S. StartSSL 的免费证书也是不给标记申请者网站域名的。
引用通告: 添加自签发的 SSL 证书为受信任的根证书 | 水景一页
引用通告: 将自签发的 SSL 证书添加为 Firefox 中受信任的根证书 | 水景一页
引用通告: CentOS / Redhat 上的 Iptables 防火墙配置简介 | 水景一页
引用通告: 更换 Linode VPS 数据中心 | 水景一页
引用通告: 最便宜的付费Https第三方证书PositiveSSL安装小记 | 绳墨
引用通告: 撕裂的 Gravatar 头像 | 水景微博
引用通告: 记一次粗心的 SSL 配置错误 | 水景一页
引用通告: Linlunson's Blog » VPS 安装SSL笔记
引用通告: Linode VPS 上 CentOS 6 安装 LAMP + phpMyAdmin 记录 | 水景一页
引用通告: CentOS 7 / RHEL 7 上安装 LAMP + phpMyAdmin | 水景一页
引用通告: linode debian lnmp nginx安装第三方Comodo PositiveSSL证书 | 一秒钟的梦
引用通告: 处理水景一页网页中 HTTP 与 HTTPS 链接混搭的问题 | 水景一页