基于OpenSSL自建CA和颁发SSL证书
openssl是一个开源程序的套件、这个套件有三个部分组成:一是libcryto,这是一个具有通用功能的加密库,里面实现了众多的加密库;二是libssl,这个是实现ssl机制的,它是用于实现TLS/SSL的功能;三是openssl,是个多功能命令行工具,它可以实现加密解密,甚至还可以当CA来用,可以让你创建证书、吊销证书。
默认情况ubuntu和CentOS上都已安装好openssl。CentOS 6.x 上有关ssl证书的目录结构:
1. 颁发证书
1.1 修改CA的一些配置文件
CA要给别人颁发证书,首先自己得有一个作为根证书,我们得在一切工作之前修改好CA的配置文件、序列号、索引等等。
vi /etc/pki/tls/openssl.cnf:
[ policy_match ]中的设定的匹配规则,是有可能因为证书使用的工具不一样,导致即使设置了csr中看起来有相同的countryName,stateOrProvinceName等,但在最终生成证书时依然报错:touch index.txt serial:在CA目录下创建两个初始文件:
1.2 生成根密钥
为了安全起见,修改cakey.pem私钥文件权限为600或400,也可以使用子shell生成( umask 077; openssl genrsa -out private/cakey.pem 2048 ),下面不再重复。
1.3 生成根证书
使用req命令生成自签证书:
# openssl req -new -x509 -key private/cakey.pem -out cacert.pem
会提示输入一些内容,因为是私有的,所以可以随便输入(之前修改的openssl.cnf会在这里呈现),最好记住能与后面保持一致。上面的自签证书cacert.pem应该生成在/etc/pki/CA下。
1.4 为我们的nginx web服务器生成ssl密钥
以上都是在CA服务器上做的操作,而且只需进行一次,现在转到nginx服务器上执行:
这里测试的时候CA中心与要申请证书的服务器是同一个。
1.5 为nginx生成证书签署请求
同样会提示输入一些内容,其它随便,除了Commone Name一定要是你要授予证书的服务器域名如awsok.com或主机名,challenge password不填。
1.6 私有CA根据请求来签署证书
接下来要把上一步生成的证书请求csr文件,发到CA服务器上,在CA上执行:
上面签发过程其实默认使用了-cert cacert.pem -keyfile cakey.pem,这两个文件就是前两步生成的位于/etc/pki/CA下的根密钥和根证书。将生成的crt证书发回nginx服务器使用。
到此我们已经拥有了建立ssl安全连接所需要的所有文件,并且服务器的crt和key都位于配置的目录下,剩下的是如何使用证书的问题。
二、使用付费证书配置步骤
由于只有浏览器或者系统信赖的 CA 才可以让所有的访问者通畅的访问你的加密网站,而不是出现证书错误的提示。所以我们跳过自签证书的步骤,直接开始签署第三方可信任的 SSL 证书吧。
OpenSSL 在 Linux、OS X 等常规的系统下默认都安装了,因为一些安全问题,一般现在的第三方 SSL 证书签发机构都要求起码 2048 位的 RSA 加密的私钥。
同时,普通的 SSL 证书认证分两种形式,一种是 DV(Domain Validated),还有一种是 OV (Organization Validated),前者只需要验证域名,后者需要验证你的组织或公司,在安全性方面,肯定是后者要好。
无论你用 DV 还是 OV 生成私钥,都需要填写一些基本信息,这里我们假设如下:
域名,也称为 Common Name,因为特殊的证书不一定是域名:example.com
组织或公司名字(Organization):Example, Inc.
部门(Department):可以不填写,这里我们写 Web Security
城市(City):Beijing
省份(State / Province):Beijing
国家(Country):CN
加密强度:2048 位,如果你的机器性能强劲,也可以选择 4096 位
按照以上信息,使用 OpenSSL 生成 key 和 csr 的命令如下
openssl req -new -newkey rsa:2048 -sha256 -nodes -out example_com.csr -keyout example_com.key -subj "/C=CN/ST=Beijing/L=Beijing/O=Example Inc./OU=Web Security/CN=example.com"
PS:如果是泛域名证书,则应该填写 *.example.com
你可以在系统的任何地方运行这个命令,会自动在当前目录生成 example_com.csr 和 example_com.key 这两个文件
接下来你可以查看一下 example_com.csr,得到类似这么一长串的文字
-----BEGIN CERTIFICATE REQUEST-----
MIICujCCAaICAQAwdTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAO
BgNVBAcTB0JlaWppbmcxFTATBgNVBAoTDEV4YW1wbGUgSW5jLjEVMBMGA1UECxMM
V2ViIFNlY3VyaXR5MRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAPME+nvVCdGN9VWn+vp7JkMoOdpOurYMPvclIbsI
iD7mGN982Ocl22O9wCV/4tL6DpTcXfNX+eWd7CNEKT4i+JYGqllqP3/CojhkemiY
SF3jwncvP6VoST/HsZeMyNB71XwYnxFCGqSyE3QjxmQ9ae38H2LIpCllfd1l7iVp
AX4i2+HvGTHFzb0XnmMLzq4HyVuEIMoYwiZX8hq+kwEAhKpBdfawkOcIRkbOlFew
SEjLyHY+nruXutmQx1d7lzZCxut5Sm5At9al0bf5FOaaJylTEwNEpFkP3L29GtoU
qg1t9Q8WufIfK9vXqQqwg8J1muK7kksnbYcoPnNgPx36kZsCAwEAAaAAMA0GCSqG
SIb3DQEBBQUAA4IBAQCHgIuhpcgrsNwDuW6731/DeVwq2x3ZRqRBuj9/M8oONQen
1QIacBifEMr+Ma+C+wIpt3bHvtXEF8cCAJAR9sQ4Svy7M0w25DwrwaWIjxcf/J8U
audL/029CkAuewFCdBILTRAAeDqxsAsUyiBIGTIT+uqi+EpGG4OlyKK/MF13FxDj
/oKyrSJDtp1Xr9R7iqGCs/Zl5qWmDaLN7/qxBK6vX2R/HLhOK0aKi1ZQ4cZeP7Mr
8EzjDIAko87Nb/aIsFyKrt6Ze3jOF0/vnnpw7pMvhq+folWdTVXddjd9Dpr2x1nc
y5hnop4k6kVRXDjQ4OTduQq4P+SzU4hb41GIQEz4
-----END CERTIFICATE REQUEST-----
你需要提交 CSR 文件给第三方 SSL 认证机构,通过认证后,他们会颁发给你一个 CRT 文件,我们命名为 example_com.crt
这个 CSR 文件就是你需要提交给 SSL 认证机构的,当你的域名或组织通过验证后,认证机构就会颁发给你一个 example_com.crt
而 example_com.key 是需要用在 Nginx 配置里和 example_com.crt 配合使用的,需要好好保管,千万别泄露给任何第三方。
2. 使用ssl证书
2.1 一般浏览器
浏览器作为客户端去访问https加密的服务器,一般不用去手动做其他设置,如https://www.google.com.hk,这是因为Chrome、FireFox、Safari、IE等浏览器已经内置了大部分常用的CA的根证书,但自建CA的根证书就不再浏览器的信任列表中,访问时会提示如下:
IE浏览器

安装网站证书后(同时也有信任的根证书),地址栏一般会显示绿色小锁

导入证书到浏览器
2.2 为linux系统添加根证书
这一步不是必须的,一般出现在开发测试环境中,而且具体的应用程序应该提供添加证书的方法。
curl工具可以在linux上模拟发送请求,但当它去访问https加密网站时就会提示如下信息:
curl --insecure来不验证证书的可靠性,这只能保证数据是加密传输的但无法保证对方是我们要访问的服务。使用curl --cacert cacert.pem可以手动指定根证书路径。我们也可以把根证书添加到系统(CentOS 5,6)默认的bundle:2.3 nginx
在nginx配置文件(可能是/etc/nginx/sites-available/default)的server指令下添加:
同时注意 server_name 与证书申请时的 Common Name 要相同,打开443端口。当然关于web服务器加密还有其他配置内容,如只对部分URL加密,对URL重定向实现强制https访问,请参考其他资料。
检测配置文件没问题后重新读取 Nginx 即可
nginx -t && nginx -s reload
但是这么做并不安全,默认是 SHA-1 形式,而现在主流的方案应该都避免 SHA-1,为了确保更强的安全性,我们可以采取迪菲-赫尔曼密钥交换
首先,进入 /etc/ssl/certs 目录并生成一个 dhparam.pem
cd /etc/ssl/certs
openssl dhparam -out dhparam.pem 2048 # 如果你的机器性能足够强大,可以用 4096 位加密
生成完毕后,在 Nginx 的 SSL 配置后面加入
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
同时,如果是全站 HTTPS 并且不考虑 HTTP 的话,可以加入 HSTS 告诉你的浏览器本网站全站加密,并且强制用 HTTPS 访问
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
同时也可以单独开一个 Nginx 配置,把 HTTP 的访问请求都用 301 跳转到 HTTPS
server {
listen 80;
listen [::]:80 ipv6only=on;
server_name example.com;
return 301 https://example.com$request_uri;
}
3 关于证书申请
注意,如果对于一般的应用,管理员只需生成“证书请求”(后缀大多为.csr),它包含你的名字和公钥,然后把这份请求交给诸如verisign等 有CA服务公司(当然,连同几百美金),你的证书请求经验证后,CA用它的私钥签名,形成正式的证书发还给你。管理员再在web server上导入这个证书就行了。如果你不想花那笔钱,或者想了解一下原理,可以自己做CA。从ca的角度讲,你需要CA的私钥和公钥。从想要证书的服 务器角度将,需要把服务器的证书请求交给CA。
如果你要自己做CA,别忘了客户端需要导入CA的证书(CA的证书是自签名的,导入它意味着你“信任”这个CA签署的证书)。而商业CA的一般不用,因为它们已经内置在你的浏览器中了。
四、可靠的第三方 SSL 签发机构
众所周知,前段时间某 NIC 机构爆出过针对 Google 域名的证书签发的丑闻,所以可见选择一家靠谱的第三方 SSL 签发机构是多么的重要。
目前一般市面上针对中小站长和企业的 SSL 证书颁发机构有:
Comodo / 子品牌 Positive SSL
GlobalSign / 子品牌 AlphaSSL
其中 Postivie SSL、AlphaSSL、RapidSSL 等都是子品牌,一般都是三级四级证书,所以你会需要增加 CA 证书链到你的 CRT 文件里。
以 Comodo Positive SSL 为例,需要串联 CA 证书,假设你的域名是 example.com
那么,串联的命令是
cat example_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > example_com.signed.crt
在 Nginx 配置里使用 example_com.signed.crt 即可
如果是一般常见的 AplhaSSL 泛域名证书,他们是不会发给你 CA 证书链的,那么在你的 CRT 文件后面需要加入 AlphaSSL 的 CA 证书链
五、针对企业的 EV SSL
EV SSL,是 Extended Validation 的简称,更注重于对企业网站的安全保护以及严格的认证。
最明显的区别就是,通常 EV SSL 显示都是绿色的条,比如本站的 SSL 证书就是 EV SSL。
如果贵公司想获取专业的 EV SSL,可以随时联系我们

