Apache&SSL

最终目的是建立https,为了能在这个系统上启用安全链接。其实也是个老东西了,很多人都做过类似的配置。但是我这次没有简单的按部就班。参考了一些资料,从openssl做起。

网上大部分的资料都是做自签名证书,做法也各有不同。不过我这次是从openssl开始,做了一个自己的CA证书,再从这个证书生成Apache所要求证书和签署生成的证书。这样做的好处是,我可以在从自己的CA生成客户端证书,如果将来需要这样的强加密的话。

openssl几乎是所有Linux发行版的必装组件。但是真正好好使用它的人未必很多,很多都是靠第三方程序直接调用openssl模块。openssl自带了一个很好用的脚本,用来进行各种各种证书操作。

SSL Certificates HOWTO记录了一些关于openssl方面的资料,感觉也就前面几页有用,后面几乎没说什么实际的应用。其中主要针对CA.pl这个自带的使用进行了比较实际的讲解。

我所使用的系统是centos,其实也就是redhatAS。它的rpm默认安装了CA在如下位置

/usr/share/ssl/misc/CA

需要对原来的脚本进行修改,才可以正常使用。主要是要指明openssl.cnf的位置,此外因为我想把自己的CA保存在特定的地方,所以对CATOP变量也进行了修改。

CA脚本的修改如下

#添加SSLEAY_CONFIG变量
SSLEAY_CONFIG="-config /etc/openssl.cnf"
#对CATOP进行修改,位置转换到/var/ssl
CATOP=/var/ssl

进行如上设置之后,这个CA脚本就被定制过了,实际上在环境变量上设置SSLEAY_CONFIG应该也是可以的。为了区别原来的脚本,我把这个CA拷到自己的目录里。因为进行了改动,所以需要拷贝openssl.cnf到/etc/下面,同时进行必要的设置,并创建/var/ssl目录。

cp /usr/share/ssl/openssl.cnf /etc/

对openssl.cnf进行了一些修改,除了目录位置的变动,其他的都是为了创建证书时能偷懒一点,进行的修改。

因为文件太长,仅列举修改过的地方

openssl.cnf wrote:

...
[ CA_default ]
dir = /var/ssl
...
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = CN
...
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = ZheJiang

localityName = Locality Name (eg, city)
localityName_default = WenZhou

0.organizationName = Organization Name (eg, company)
0.organizationName_default = mllm.org

曾经看到帖子,如果把openssl.cnf中的commonName重复多行,可以设置多个域名,但是这样的做法,可以在IE中使用,但不能在其他一些浏览器中使用。在不兼容的浏览器中,只会识别第一个commonName。不过按照协议设计,按道理是应该只能做一个才对。

说到这里,apache的官方文档上说,ssl是不支持NameVirtualHost的,因为协议上的一些限制。如果要做虚拟主机,要不开在非443端口,要不就是绑多个IP,这两种做法。

做完了上面这些步骤,CA脚本应该能够顺利执行了。CA脚本实际上就是把证书生成,根证书生成,证书请求生成,签名这些都做到一个脚本里。而以前的文档都没有见过使用CA脚本的做法。虽然直接输openssl命令会有很多机会选择不同的参数,不过CA脚本便利了操作流程。

[root@abc abc]# /allblue/ssl/CA -h
usage: CA -newcert|-newreq|-newca|-sign|-verify

首先是生成根证书。按照CA的默认配置,它生成的证书的年限是一年,但是根证书,一般还是设置得久一点比较好。要不就临时改一下openssl.cnf的配置,用来生成大于一年的根证书,要不就直接用openssl命令。

SSL Certificates HOWTO 2.2 wrote:

CA -newcert 
(openssl req -config /etc/openssl.cnf \
-new -x509 -keyout newreq.pem \
-out newreq.pem -days 365) 

creates a self signed certificate (for Certificate Authority). The resulting file goes into newreq.pem. For the common Name (CN) use something like “ACME root Certificate”. This file needs to be split into 2 files cacert.pem and private/cakey.pem. The part -RSA PRIVATE KEY- goes into private/cakey.pem while the part -CERTIFICATE- goes into cacert.pem. Delete newreq.pem when finished.

我使用了-newca参数,直接生成了下面两个文件,一个是根证书文件cacert.pem,一个是证书的私钥cakey.pem

/var/ssl/cacert.pem
/var/ssl/private/cakey.pem

如果没有更改过openssl.cnf中的day设置,则默认有效期为一年。

#直接使用openssl,设置证书和私钥在两个地方,并且设置有效期10年
openssl req -config /etc/openssl.cnf -new \
-x509 -keyout private/cakey.pem \
-out cacert.pem -days 3650

接下来是生成apache所使用的证书,这个可以用-newcert来生成,并且用-signcert来签名生成的证书。因为对openssl.cnf已经进行了正确的设置,签名的时候,会自动引用生成的根证书。

#生成newreq.pem文件,私钥和证书都在这个文件里
[root@abc]#CA -newcert

#签名证书,默认对当前目录下的newreq.pem进行签名,
#生成newcert.pem证书,并且会更新相关文件,如
#index.txt,拷贝新证书到newcerts目录里,命名为
#01 02之类的文件
[root@abc]#CA -signcert

因为CA脚本把私钥和证书都存在newreq.pem文件里,所以要把newreq.pem里面BEGIN RSA PRIVATE KEY和-----END RSA PRIVATE KEY-----覆盖的部分另外保存为key文件。这样就得到了apache所要求的一个证书,一个私钥文件两者。

这样下来配置apache ssl的两个关键文件就有了。我这样做,不同于以前的直接自签名证书文件的好处在于,还可以生成客户端证书,并用自己的根证书签名。这样就可以配置客户端认证部分。如果应用需要这样的强加密的话,仅用以前的办法似乎是不行的。

这篇文章没有提及证书创建里面的一些填空,其中有一个很重要的东西就是pass-phrase。这个是用来保护私钥的。如果私钥被盗,这个密码就是用来做最后一道防线的。不过如果这样的话,配置好apache之后,每次启动都会询问pass-phrase。其实我感觉如果在一个成熟的应用当中,这样做还是有必要的,至少安全。但对于经常变动的服务,这样就太麻烦了。apache可以设置一个外部程序,在启动时调用这个程序来获得密码。我看过国外论坛的一个做法,就是一个简单的echo代码。其实apache有这样的设置,其实意思在于用其他的更强加密来保护pass-phrase,如果只是简单的echo出来,那还不如不要算了,对于我的环境,能进得了系统有能的人,基本上也能搞定这个文件了。不过倒也是一条思路。

因为我只是用在个人网站上,感觉没有太必要,就用官方文档的办法,去掉了pass-phrase。

官方文档里去掉pass-phrase的办法

$cp server.key server.key.org
$openssl rsa -in server.key.org -out server.key
$chmod 400 server.key

apache的配置就不罗嗦了,附上几个文件改动的地方,以作备用。

httpd.conf wrote:

...
Listen 80
Listen 443
LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so

SSLRandomSeed startup builtin
SSLRandomSeed connect builtin

ServerName allblue.mllm.org
SSLEngine On
SSLCertificateFile conf/ssl/allblue.mllm.org.crt
SSLCertificateKeyFile conf/ssl/allblue.mllm.org.key
...

...

博客日志: 

Submitted by 游客 (not verified) on 2006, May 14 - 19:38

很多站点只是认证的时候用https,其他部分仍旧使用http。
是否因为ssl占用资源的缘故?

顺便问一下,drupal下的ssl运行情况如何?

Submitted by allblue on 2006, May 15 - 04:38

大多商业站点的确只用于认证时使用,但是基于中国目前的情况,当你查看某些内容时,使用https会更有效。整站使用https的也不少,特别是对于个人这种博客站点,访问量不会太大的情况下,多一种安全选择未为一种好事。

ssl的确占多占用一些资源,不过在流量不是太大的情况下,基本上还是感觉不到的。

drupal只是一个php程序,而ssl是作为apache的一个mod架构的,理论上只有你的https够快,drupal应该和原先的没有任何差别才对。

Copyright © 2004-2012 allblue All Rights Reserved