数字证书、SSL、HTTPS及在Nginx中的配置
一、什么是 RSA、SSL、HTTPS
RSA:它是非对称加密算法的一种,而且是最常用的一种。它的理论基础是:计算两个大质数的乘积非常简单,而对该乘积进行因子分解就非常困难。而且
这两个质数越大,对其乘积的分解就越困难。RSA生成的密钥对有公钥和私钥之分,不过,貌似密钥对中的任何一个当公钥都行,公钥是可以公开的,
私钥只有自己知道,公钥加密的数据只有私钥才能解密,反之私钥加密的数据也只有公钥才能解密。目前,公开声明破解的密钥位数是768位,因此
长度为1024的RSA密钥是有一定危险的,建议密钥用2048位的。量子计算机对破解RSA比较有效。
SSL:全称是Secure Sockets Layer,是介于TCP层协议和HTTP协议之间的协议,如果用TCP/IP五层协议来考察,那SSL属于应用层,与HTTP在同一层。
SSL协议与HTTP协议没任何关系,它是一个安全协议,用于对数据包(有应用层协议头)进行加密,因此,我们也可以对FTP、SMTP等协议用SSL协议
加密,即FTPS、SMTPS。SSL采用非对称加密算法,比如可以选择RSA算法。
HTTPS:它其实只是SSL协议+HTTP协议的组合而已,类似的还有FTPS、SMTPS等等。HTTPS 不同于 HTTP 的端口,HTTP默认端口为80,而HTTPS默
认端口为443。
数字签名:用私钥对发送的信息的hash值进行加密,得到的加密数据就是数字签名,我们最常见到的是CA对数字证书进行签名。数字签名的作用是可以检查
数据在传输过程中是否被人篡改了,因为如果篡改了,那hash值必定会变化,就与数字签名解密后的值不一样了,而由于篡改者没有CA私钥,所以没
法重新生成数字签名。你可能会问,为什么不直接对信息加密,而是要对其hash值进行加密呢?从效力上讲,两者是等效的,都可以验证信息是否被人
篡改过。当信息量大时,直接对信息加密(以及客户端收到信息后解密)太耗时,所以用信息的hash值。
数字证书:里面包含服务器公钥、其它信息、还会附加服务器公钥和证书信息的数字签名。这里的其它信息包含颁发者、有效期、使用者common name-简称CN,
签名算法,签名哈希算法等。一般来说,我们会使用权威CA认证颁发的数字证书,该证书中附加的数字签名就是CA用自己的私钥对“证书中的公钥和
证书信息“的hash值加密后得到的。我们可以看到,数字证书本身是没有加密的,只是附加了一个数字签名而已,因此,在传输过程中别人是可以窃听
的,不过没有关系,我们在传输数字证书时,主要是防止别人的篡改和冒充,保证公钥就是客户端所访问的服务器发来的公钥,而没有被人篡改,也
没有被冒充,关于冒充,见下面的SSL实现的功能第3点。我们可以通过检查数字签名来保证没有被篡改,通过该证书的颁发者是否为权威CA以及
common name是否为http request header中的host(不包括端口)来保证没有被别人冒充。
使用SSL可以实现下面的功能:
1、数据加密传输,防止窃听。SSL常用的非对称加密算法是RSA,RSA基于的理论是:两个大质数相乘计算非常容易,但对该乘积进行因子分解非常困难,
而且该乘积越大,破解越难。目前公开声明破解的密钥位数是768,因此密钥长度为1024的RSA是有一定危险的,建议密钥长度用2048位。量子计算
机对破解RSA有效,目前还不确定美国国安局NSA是否已经掌握了长密钥RSA的破解方法。
2、可以进行数据完整性检查,防篡改。
3、可以进行身份验证,防冒充。比如客户端给服务端发请求时,先要DNS查找服务器的IP,而DNS时被一个黑客拦截,返回了黑客指定的IP,该IP的服务
给客户端返回了一个证书,为了使客户端验证通过,该证书必须是权威CA机构颁发的,而且证书中的服务器域名必须与客户端请求的域名相同,为了保
证这两点,那黑客要有某个权威CA颁发的该域名的证书,如果该黑客想直接在权威CA上申请该域名的证书,那是不可行的,因为CA会用一些办法(比
如给注册域名时所用的邮箱发一封确认邮件)验证该域名是否属性黑客,显然,黑客无法通过验证。另一种方法是黑客直接用浏览器等客户端去从服务
端获取,这是可以得到的。但是黑客无法获取到服务器私钥,这样即使它将服务器的IP定向到自己的服务器,但客户端发来的对称密钥由于是用证书中
包含的公钥加密的,黑客是无法解密的。
二、SSL通信过程
这里只是一个简化的通信过程(主要简化了生成对称密钥的过程),目的只是方便理解SSL原理。
首先,要向CA申请证书,也可以是自签的证书。在证书请求文件中,包含服务端的公钥,还有域名、Email、地址等信息。CA用自己的私钥将这些信息
加密生成一个证书,该证书会注明CA名称。我们向CA申请证书基于一个假设:即认为CA的证书是可靠的,可信的。我们可以看到,其实SSL通信过程中,
涉及到两对非对称密钥和一对对称密钥。两对非对称密钥是指CA自己的非对称密钥和我们服务器的非对称密钥,简单说一下他们的作用,如下
CA非对称密钥对的作用:简单点说吧,CA用私钥对证书进行加密(注:证书中包含服务器的公钥),这样可以做到黑客无法篡改证书中的公钥,保证公钥
只能是域名服务器发来的。如果不用CA私钥加密证书,那证书传输过程中,黑客可以劫持并篡改证书中的公钥为自己的公钥,并通过DNS劫持和修改,指向自己
的服务器IP,这是非常危险的。CA的非对称密钥中,私钥由CA自己保存,当用户申请CA证书时,CA会用该私钥对证书进行数字签名,这样可以保证黑客无法修
改证书,因为黑客修改证书信息后,必须重新计算hash,重新生成加密生成数字签名,但黑客没有CA的私钥,所以没法对该hash加密。在SSL通信过程中,当
客户端收到服务器发来的证书后,先计算出该证书信息的hash,然后用CA公钥解密证书上的数字签名,得到hash,如果两个hash相同,那就说明证书没有被篡
改过。
服务器非对称密钥对的作用:加密解密对称密钥,在SSL通信过程中,客户端将对称密钥发给服务器时,要用服务器的非对称密钥加密的,这样保证对称密钥
的传输安全。
SSL握手过程如下:
1、客户端向服务器发请求,请求证书
2、服务器把证书发给客户端
3、客户端一般会有大部分CA的公钥,客户端收到证书后,检查该颁发者是否是客户端认可的CA,如果是,就用该CA的公钥解密数字签名,然后再计算
证书中的”公钥和证书信息“的hash值,比较两者,如果相同,那就说明该证书没有被人篡改过,而且是该CA机构颁发的。当然,还会进行其它验证,
如证书的common name与http request header中的host(不包括端口)是否相同,等等,如果有哪项检查不通过,会有告警,如果所有检查通过,
那进入第4步。
4、客户端生成对称密钥,用证书中的公钥加密,发给服务器
5、服务器收到对称密钥后保存,给客户端一个应答。
6、客户端接收响应,这样就完成了SSL连接,后面的通信用对称密钥加密数据传输。
因为非对称加密相对对称加密来说比较耗时,所以正式的数据传输是用对称加密算法。非对称加密只是用于建立SSL时对称密钥的安全传输。我们可以设置
HTTPS长连接,这样建立好SSL+HTTP连接后,可以用这个连接发多次HTTPS请求,而不用每次请求都建立连接。
三、什么网站需要使用SSL证书
这块我还没完全搞懂,因为很多网站在登陆时用HTTPS,而登陆后用的HTTP,我有些不解,因为登陆时用HTTPS可以防止别人截获用户名和
密码,那登陆后用HTTP就不怕被人截获cookie吗?莫非可以使用HTTPS中的对称密钥对HTTP中的数据进行加密?
四、自签SSL证书
需要先安装openssl,使用openssl给服务器生成RSA密钥及证书。如果是用权威的CA,在你申请CA证书过程中,他会帮你生成私钥,这样你就不需要用openssl生成了。
startssl就提供了这个功能。
# 生成一个RSA私钥,1024是加密强度,一般是1024或2048 $ openssl genrsa -out private.key 1024 # 生成一个证书请求 $ openssl req -new -key private.key -out cert_req.csr # 自己签发证书,如果要权威CA签发的话,要把cert_req.csr发给CA $ openssl x509 -req -days 365 -in cert_req.csr -signkey private.key -out server_cert.crt
第2个命令是生成证书请求,会提示输入省份、城市、域名(图中的Common Name)、Email等,这里主要是保证Common Name用网站域名,
如果没有申请域名,客户端直接通过服务器IP访问,那这里就输入服务器IP。另外,对于自签名的证书,建议生成的私钥不要加密。生成的证
书请求文件cert_req.csr中除了包含这些手动输入的信息外,它还包含private.key对应的公钥,你可能会有一个疑问,根据私钥就能生成公钥吗?
当然不是,如果只单纯的知道私钥,可以认为是无法计算出公钥的,关键在于Putty在产生私钥时,还会在内存中保存必要的公钥参数。最后由该证
书生成自签的证书,见图1.
编辑配置文件nginx.conf,给站点加上HTTPS协议,重启Nginx后即可通过https访问网站了。
server { server_name 192.168.1.100; # 客户端直接用IP来访问 # 这是默认的SSL端口,可以修改为其它端口,浏览器用https访问url时,默认就是用这个端口, # 如果下面listen修改成其它端口,那浏览器用https访问时,就要指定端口了。 listen 443; ssl on; ssl_certificate /home/xiaobai/server_cert.crt;
#使用无密码私钥 ssl_certificate_key /usr/xiaobai/private.key; }
在SSL握手的过程中,客户端收到服务端的证书后,会对证书进行多项检查,如果检查不通过,就会用告警,不过这些也只是告警而已,他不会
禁止你访问。常用的浏览器(如FireFox、Chrome)会给你提供两种方案:第一种方案是你可以选择继续访问,这样在你关闭浏览器之前,可以
访问包含该根URL下的所有URL,但是当你关闭浏览器后,再次打开时还会有警告,我们可以认为,浏览器只是临时把证书添加到了受信任的证书
颁发机构,关闭浏览器后,就把它删除了。第二种方案是允许你永久将该证书添加到受信任的证书颁发机构,这样,即使你关闭浏览器,再次打开后
该证书还有效。一般来说,我们会先尝试第一种方案,检验一下URL是否可以正常访问,如果还是无法访问,那就要看一下服务器的web服务器软件
是否设置有问题。
下面我们说一下其中的两个检查:
(1)证书是否是客户端信任的CA签发
检查证书的签发机构是否是自己信任的CA,在客户端有一个信任CA机构列表,如果不是,告警如图2所示,这是FireFox的警告,在警告
的技术细节中提示了原因:该证书因为其自签名而不被信任,如果想继续访问,那就选择”添加例外...",点击添加例外,会出现图3,可以看
到一个选项“永久保存此例外”,如果不选,就是上面说到的浏览器提供的第一种方案,如果选中,那就是第二种方案。
(2)证书中的Common Name与HTTP Request Header中的host(不包括端口)是否相同
如果不同,警告如图4所示,这是Chrome的警告。比如,我的证书的Common Name是主机的局域网IP=192.168.1.100,而我使用服务器的域名
www.xiaobai.net进行的访问,这时就会提示提示“您尝试访问的是 www.xiaobai.net,但实际上访问的却是标识为 192.168.1.100 的服务”。
(注:如果局域网内的主机通过192.168.1.100访问服务器,它会出现(1)中的警告,该证书不是受信任的证书颁发机构颁发的。)
前面提到Chrome对于不信任的证书会有告警,但也提供了两种方案使用他们:第一种方案是选择”继续www.xiaobai.net(不安全)",它是临时性
将证书添加到受信任的证书颁发机构;第二种方案是将证书导出,添加到受信任的证书颁发机构,见http://www.cnblogs.com/ajianbeyourself/p/3899729.html
图4
五、找一家CA机构
要获取受浏览器信任的证书,则需要到证书提供商处申请。证书授证中心,又叫做CA机构,为每个使用公开密钥的用户发放一个数字证书。浏览器在默认情况下内置了一些CA机构的证书,
使得这些机构颁发的证书受到信任。VeriSign即 是一个著名的国外CA机构,工行、建行、招行、支付宝、财付通等网站均使用VeriSign的证书,而网易邮箱等非金融网站采用的是中国互
联网信息中心CNNIC颁发的SSL证书,不过知乎上有人说CNNIC的证书不可信,呵呵,我同意。一个证书的价格从一百到数千,以VeriSign的证书为例,价格在每年8000元人民币左右。
也有免费的证书可以申请,StartSSL就是,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。后来StartSSL竟然
搞定了微软:在升级补丁中,微软更新了通过Windows根证书认证(Windows Root Certificate Program)的厂商清单,并首次将StartCom公司列入了该认证清单。现在,在Windows 7
或安装了升级补丁的Windows Vista或Windows XP操作系统中,系统会完全信任由StartCom这类免费数字认证机构认证的数字证书,从而使StartSSL也得到了IE浏览器的支持。
(来源及申请步骤)。在StartSSL提供了免费和收费两种证书,见https://www.startssl.com/?app=37,其中Class1就免费的,它只验证域名所有者,其它的都是收费的。这里我们只说一
下这种免费的证书的申请,在Class1中需要验证你是域名的所有者:"Domain Name Validation",在你输入域名后,它会弹出一个邮箱列表,如下,前三个邮箱是postmaster@你的域名,
hostmaster@你的域名,webmaster@你的域名,还有一个是你注册域名时提供的邮箱,选择一个,点击“Continue”,它会给你邮箱把一个验证码
详细的申请过程见http://www.live-in.org/archives/1296.html
六、只针对注册、登陆进行https加密处理
既然HTTPS能保证安全,为什么全世界大部分网站都仍旧在使用HTTP呢?使用HTTPS协议,对服务器来说是很大的负载开销。从性能上考虑,我 们无法做到对于每个用户的每个访问请求都进行安全加密(当然,Google这种大神除外)。作为一个普通网站,我们所追求的只是在进行交易、密码登陆等操 作时的安全。通过配置Nginx服务器,可以使用rewrite来做到这一点。
在https server下加入如下配置:
if ($uri !~* "/logging.php$")
{
rewrite ^/(.*)$ http://$host/$1 redirect;
}
|
在http server下加入如下配置:
if ($uri ~* "/logging.php$")
{
rewrite ^/(.*)$ https://$host/$1 redirect;
}
|
这样一来,用户会且只会在访问logging.php的情况下,才会通过https访问。
更新:有一些开发框架会根据 $_SERVER['HTTPS'] 这个 PHP 变量是否为 on 来判断当前的访问请求是否是使用 https。为此我们需要在 Nginx 配置文件中添加一句来设置这个变量。遇到 https 链接重定向后会自动跳到 http 问题的同学可以参考一下。
server {
...
listen 443;
location \.php$ {
...
include fastcgi_params;
fastcgi_param HTTPS on; # 多加这一句
}
}
server {
...
listen 80;
location \.php$ {
...
include fastcgi_params;
}
}
|
参考链接:
http://www.lovelucy.info/nginx-ssl-certificate-https-website.html
http://zou.lu/nginx-https-ssl-module
http://blog.s135.com/startssl/
http://www.baalchina.net/2008/08/nginx-https-rewrite/