摘要:
第一次写博客,为读书笔记,参考书目如下:
《HTTP权威指南》
《图解HTTP》
《大型分布式网站架构设计与实践》 作者:陈康贤
一、 HTTP+SSL=HTTPS
1. HTTP是不安全的
在linux系统上,网络上的通信实现由用户空间和内核空间共同实现,内核以模块的方式(tcp ip协议栈)提供通信子网,而资源子网由用户程序实现。
TCP/IP是可能被窃听的网络,而HTTP是不加密的传输,可以用一些例如Packet Capture或者Sniffer工具很轻易的进行抓包,窃听。HTTP在安全上主要有以下不足:
- 通信使用明文
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,有可能收发的报文是遭到篡改
而针对于以上不足,网上的攻击大致有以下几种类型:
- 窃听,通信量分析,威胁保密性
- 更改,伪装,重做,否认等威胁内容完整性
- 拒绝服务(Dos)威胁网站可用性
解决方案: SSL Security Layer
由于之前在应用层已经有各种各样的协议HTTP, FTP等等,为了让之前已经存在的程序可以使用到安全通信,网景公司在应用层和传输层之间设计了半层SSL,任何以前的程序只要调用这半层库就可以安全套接字传输。
SSL中使用了大量的加密技术,在SSL的实现中会详细说明如何使用加密技术.这里只是简单描述,有兴趣可以参考《大型分布式网站架构设计与实践》中的Java代码实现。
2. Linux加密与解密简介
传统的加密技术: 替代加密,置换加密
现代的加密技术: 分块加密,比如使用XOR将密钥流的块与块进行特征运算,得到密文
SSL中用到的加密算法主要有单向加密,对称加密,公钥加密等,下面简单介绍这些常见的概念:
2.1 单向加密
即提出数据指纹,例如md5,sha等等,这些单向加密算法拥有以下特性:
定长输出,即加密后结果长度一般是固定的,例如md5是128bits
雪崩效应:源数据微小的改动会引起加密结果的巨大变化
2.2 对称加密算法
对称加密算法中加密和解密使用的是完全相同的密钥,这是应用较早的加密算法,技术成熟,这种加密算法算法公开,计算量小,加密效率高。不过依赖于密钥,密钥长度越长,安全性会大幅度上升。
常见的对称加密3DES,AES等,这都是现代的加密算法,即分块加密。
2.3 公钥加密算法
公钥加密的数据只有私钥能解密,私钥加密的数据同时也只有公钥能解密,私钥可以使用工具创建,但是必须保证其私密性,而公钥则可以从私钥中提取。
常见的有RSA,DSS等等,注意公钥加密一般用来加密密钥,因此使用公钥加密远比对称加密复杂,每次数据都使用公钥加密不合理。
2.4 密钥交换
假设有2台机器A和B,B生成了密钥,现在他要把密钥信息告知给A,直接在网上传输是不可靠的,因此以安全的方式进行密钥共享,我们把这称为密钥交换。
实现密钥交换的方法很多,比如可以使用公钥加密(非对称加密)
B使用A的公钥,注意B只能获取A的公钥去加密对称密钥,再传给A,此时要想解密必须拥有A的私钥,因此只有A才能解密,考虑上加密后的密钥依旧在网络上传输,不可否认依旧拥有一定风险。
因此现在更倾向于用DH(Deffie-Helllman)算法进行密钥交换,大体思路如下(理解不深):
服务器A:使用协商的2个素数p,g
服务器B:使用2个协商的素数p,g
((p^y)%g)^x = ((p^x)%g)^y 这就是协商后的密钥
现在出现了DH算法的一些变种,比如ECDH
3. 如何在通信中使用加密技术
假设有服务器A和服务器B进行通信,B如何安全把数据传输给A,假设要传输的数据为data
服务器B如何加密数据,并且发送:
- 第一步:服务器B计算出data的特征码,使用单向加密算法,假设是md5,得到结果code
- 第二步:服务器B使用公钥加密算法,生成pri_b_key(私钥)和pub_b_key(公钥),并且开放pub_b_key
- 第三步:服务器B使用自己的私钥pri_b_key加密code得到en_code(加密之后的特征码),这被称为数字签名
- 第四步:服务器B使用熵池中的随机数生成对称加密算法的临时密钥,这里的随机性很重要,一定要保证不能是伪随机,加密整段数据,包括en_code,data
- 第五步:服务器B使用密钥交换将对称加密的临时密钥key共享给服务器A
服务器A如何解密数据,并且验证:
- 第一步:服务器A得到key,进行解密,得到en_code,data
- 第二步:服务器A通过“可靠手段”获取服务器B的公钥pub_b_key
- 第三步:服务器A使用pub_b_key解密en_code得到code,如果可以解密,说明确实是服务器B发送的,因为能用公钥解密的只能是私钥加密的数据
- 第四步:服务器A使用相同的单向加密算法md5,加密data和code进行比较,如果相同,说明数据data的完整性可以得到保障,因为特征码的计算是单向的,只有这个data能得到这个code
总结:
以上便是安全通信的基本原理,引入了概念数字签名,利用数字签名可以验证数据的来源可靠和数据完整,但是以上依旧存在漏洞,就是服务器A如何通过可靠的手段获取服务器B的公钥,一个服务器有这么多客户端,如何保证这些客户端都能够简单轻易而又可靠的获取到公钥,因此,需要第三方机构的介入
4. 安全证书
什么是安全证书?如何证明收到的公钥就是原本预想的那台服务器的公钥,获取在传输的过程中已经被第三方给篡改了,为了解决该问题,可以使用由数字证书认证机构(CA,Cerificate Authority)和其相关结构颁发的公开密钥证书。
数字证书认证机构处于客户端和服务器双方都信赖的第三方结构立场上。威力信(VeriSign)就是其中一家。数字认证机构的业务流程:
- 首先,服务器的运营人员向数字证书机构提出公开密钥的申请。
- 数字证书认证机构在判明提出申请者的身份之后,会对已经申请的公开密钥做数字签名,然后分配这个已经已经签名的公开密钥,将公开密钥放入公钥证书,然后绑定在一起
- 服务器会将这份公钥证书发送给客户端
- 客户端收到之后会对这份公钥做验证,验证上面的数字签名,一旦验证通过可以确认:1.认证服务器的公开密钥的是真实有效大的数字认证机构;2.服务器公开的密钥是值得信赖的
注意:此处认证机关的公开密钥必须安全的交给客户端,比如多数浏览器开发商发布版本时,会事先植入。认证机构信誉第一~!
CA的证书都包含哪些内容?在X.509 V3中定义了证书的结构认标准:
版本号
序列号
签名算法
发行者名称
有效期限
主体名称 如果是https://www.baidu.com 则必须是www.baidu.com这样的名称,否则验证不通过
主体公钥 就是为了传递这东西
发行者的唯一标识
主题的唯一标识
扩展
发行者的签名
如何验证证书? 根据以下步骤
验证发行者的唯一标识
使用发行者的公钥开验证数字签名来源是否可靠
使用相同的特征算法验证数字签名内容是否完整
验证主体名称
验证证书是否过期
验证证书是否被吊销
ok,安全的获取到了证书上主体公钥
5. HTTPS详解
5.1 Handshake的大致流程
某些特殊场景,可能需要客户端验证身份,比如银行的转账,网银啊,此时客户端的证书密钥在你的电子狗(外部)或者其他可靠设备中,这里不加讨论!
步骤1:客户端发送Client hello报文开始SSL通信,报文中含有客户端支持的SSL版本,加密组件(Cipher Suite)列表(使用的加密算法,密钥长度等等)
步骤2:服务器端进行SSL通信时,会以Server Helllo进行回应,和客户端一样,在报文中有SSL版本和加密组件,服务器的加密组件是从客户端报文中筛选出来的,即要使用的不一定是最新的版本和算法,一定是服务端和客户端都支持的
步骤3:服务器发送Certificate报文,报文中含有公开密钥证书
步骤4:服务器端发送Server Hello Done报文通知客户端,最初阶段的SSL握手协商部分完成
步骤5:SSL第一次握手完整之后,客户端验证证书,提取公钥并且以Client Key Exchange报文作为回答。报文中包含通信加密中使用的一种被称为Pre-master secret的随机密码串。该报文已经使用步骤三中的公钥进行加密
步骤6:客户端继续发送Change Cipher Spec报文。该报文会提示服务器,之后的通信都是使用Pre-master secret密钥加密
步骤7:客户端发送Finished报文,该报文中含有连接至今全部报文的整体校验值,这次握手协商能否成功,要以服务器能否正确解密该报文作为判定标准。
步骤8:服务器端同样发送Change Cipher Spec报文
步骤9:服务器同样发送Finished报文
步骤10:服务器端和客户端的Finished报文交换完毕,代表SSL连接建议完成,以后的通信都受SSL的安全保护
步骤11:开启HTTP应用层的通信,此时应用层还会附加MAC(Message Authentication Code)的报文摘要,该摘要可以查知报文是否篡改,从而保护报文的完整性
5.2 SSL和TLS
HTTPS中使用SSL(Secure Socket Layer)和TLS(Transport Layer Security)这2个协议。
一般我们说的SSL不是指个狭义上的SSL协议,SSL技术是由网景公司开发的,目前主导权在IETF手中,有1.0,2.0,3.0 即使是3.0 谷歌也发现了其中依然有安全隐患,IETF以SSL3.0为基准,制定了tls1.0,1,1,1.2版本,我们说的SSL一般统称这2种协议
现在主流版本应该是TLS1.2
5.3 HTTPS性能问题
首先,https确实有性能问题,SSL慢有两种:
一种是通信慢,和使用HTTP相比,网络负载会变为2-100倍...,除去和TCP连接,发送HTTP请求响应以外,还必须进行SSL通信,因此必须会慢
另一种是处理慢,客户端和服务端都要进行额外的处理,比如说进行加密和解密,确实会占用更多的系统资源
该问题无法解决,但是可以改善,比如有一种SSL加速器(专用服务器)可以改善该问题,该硬件确实可以提高数倍SSL的计算速度...
二、演示:Openssl httpd实现https管理静态资源
这里使用开源软件openSsl,即SSL协议的开源实现来演示,并用httpd简单静态资源服务器模拟一下
这里使用vmware虚拟机,有2台服务器,系统是Centos6.5,ysz202(192.168.1.202)和ysz204192.168.1.204),其中ysz202作为CA证书服务器,ysz204作为httpd服务器
httd是2.2
第一步: 自建私有CA服务器
模拟一个CA服务器,只要在服务器上生成一个自签证书,并为CA提供所需要的目录以及文件即可
首先简要介绍一下openssl服务器,在ysz202服务器上
# 查看httpd的配置文件
~]# rpm -qc httpd
# 看一下里面的内容
~]# vim /etc/pki/tls/openssh.cnf
内容大概如下:
[ ca ] ca子命令,下面这样一段表示一个子命令,比如说[ req ]等等
default_ca = CA_default # The default ca section ####################################################################
[ CA_default ] dir = /etc/pki/CA # Where everything is kept 工作目录
certs = $dir/certs # Where the issued certs are kept 证书放置位置
crl_dir = $dir/crl # Where the issued crl are kept 吊销证书放置位置
database = $dir/index.txt # database index file. 数据库文件在哪
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate CA自签证书位置
serial = $dir/serial # The current serial number 递增的证书序列号
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key CA自己的私钥
RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert # Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options # Extension copying option: use with caution.
# copy_extensions = copy # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
按照上面的配置文件来建立文件和目录...
# .生成私钥命令,使用umask077; 表示在下面子shell中指定文件掩码
# 这样生成的密钥别人不允许访问
(umask ; openssl genrsa -out /etc/pki/CA/private/cakey.pem )
# .生成自签证书
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days
# . 为CA创建所需要的目录以及文件
mkdir -pv /etc/pki/CA/{certs,crl,newcerts}
touch /etc/pki/CA/{serial,index.txt}
echo > /etc/pki/CA/serial
说明:
1.openssl命令:
-new: 表示创建新证书
-x509:表示是测试自签证书,创建私有CA用
-key:生成请求时候用到的私钥路径
-out:输出文件列表
-days:证书有效时长
然后会进入一个交互式窗口,注意输出的主体名称必须是互联网上的主机名,这里我用的是www.ysz202.com和www.ysz204.com
2.创建的文件就是配置文件中指定的内容
第二步:在ysz204上创建公钥,并且请求ysz202签名
#没有httpd,yum安装
yum install -y httpd
#. 在ysz204,即httpd服务器上,创建私钥
mkdir /etc/httpd/ssl
cd /etc/httpd/ssl
(umask ; openssl genrsa -out /etc/httpd/ssl/httpd.key )
#.生成证书
openssl req -new -key /etc/httpd/ssl/httpd.key -out /etc/httpd/ssl/httpd.csr -days
#.通过可靠方式发送给ysz202
scp httpd.csr root@192.168.1.202:/tmp/
#.在ysz202上执行签署证书,按两下yes同意签署
openssl ca -in /tmp/httpd.csr -out /etc/pki/CA/certs/httpd.crt -days
#.将签署之后的证书cp到机器ysz204上
scp /etc/pki/CA/certs/httpd.crt root@192.168.1.204:/etc/httpd/ssl/
#.ysz204上配置httpd支持使用ssl,及使用的证书;
yum -y install mod_ssl
第三步:在ysz204上配置https
~]# rpm -lc mod_ssl 查看yum包生成的所有文件
发现mod_ssl自动在/etc/httpd/conf.d中生成了配置文件ssl.conf,所有/etc/httpd/conf.d中以.conf结尾的文件都是httpd主配置文件的一部分,一般模块文件在这里目录,例如mod_ssl
~]# vim /etc/httpd/conf.d/ssl.conf
# 文件根目录
DocumentRoot "/var/www/html"
# 主体名字必须和域名一致
ServerName www.ysz204.com
# 证书文件路径
SSLCertificateFile /etc/httpd/ssl/httpd.crt
# 私钥路径
SSLCertificateKeyFile /etc/httpd/ssl/httpd.key
保存退出,测试httpd配置文件
~]# httpd -t
~]# service httpd start
~]#netstat -tunpl 查看443端口是否被监听
此时同时监听http和https,如果想要关闭http,直接关闭监听80端口即可
第四步:测试https效果
可以使用 openssl s_client [-connect host:port] [-cert filename] [-CApath directory] [-CAfile filename]命令测试,在ysz202上主机测试
~]# openssl s_client -connect 192.168.1.204:443 -CAfile /etc/pki/CA/cacert.pem
发现结果是ok表示使用https测试成功
下面在windows主机上使用chrome浏览器测试
修改windows host文件 192.168.1.204 www.ysz204.com
修改chrome设置,使用xftp工具从ysz202下载根证书/etc/pki/CA/cacert.pem文件导入chrome浏览器高级设置->证书管理,我们必须相信我们的测试CA服务器,导入这个自签证书
重启Chrome,访问https://www.ysz204.com/,可以直接访问
再访问https://192.168.1.204提示你的连接不是私密连接,原因是在验证主体名称证书上的www.ysz204.com
三、nginx上使用https
参考http://www.cnblogs.com/carl10086/p/5926281.html中关于ssl的模块
四、tomcat中使用https
暂无