阅读目录
- 简单介绍
- 环境介绍
- 环境安装
- 创建CA
- 签发服务端证书
- 配置文件编辑
- 测试单项认证
- 参考资料
笔者最近在研究Https,在半年前发现做的HTTPS都是错误的,总以为能实现访问就成功了,但是并不是这样!在网上搜索了很多资料发现讲得全面的并不多,所以笔者将配置的全过程都完整的记录下来,以提供参考
简单介绍
一般情况下,我们打开网站默认的是使用明文传输方式,但在日常生活中,当我们在登录或者支付交易时,网站就会自动跳转至SSL(Secure Sockets Layes)加密传输模式,SSL的功能就是提供加密数据
网络传输过程中的数据加密则是全部委托给SSL协议来完成,而TLS(Transport Layes Security)是对SSL的扩展与优化,它可以提供数据的安全,同时也保证数据的完整性
证书(Certificate)是HTTPS的核心,但是其实证书并不是一个单一的东西,而是几种技术的综合加密/解密
- 避免消息明文传输,对消息进行加密,早期一般是用对称加密算法,现在一般都是不对称加密,最常见的算法就是RSA
消息摘要
- 这个技术主要是为了避免消息被篡改,消息摘要是把一段信息,通过某种算法,得出一串字符串!这个字符串就是消息的摘要,如果消息被篡改"发生了变化",那么摘要也一定会发生变化"如果2个不同的消息生成的摘要是一样的,那么这就叫发生了碰撞"
数字签名
- 数字签名是为了验证双方的身份,避免身份伪造
单向认证和双向认证
- 单向认证:如百度、以及淘宝之内的网站
- 双向认证:如银行对安全要求很高的网站,也会采用双向认证,如U盾、安全控件什么的,其实就是固化的客户端证书
Apache Http Server通过mod_ssl模块来实现对SSL/TLS的支持,所以等下环境搭建的时候需要安装mod_ssl模块SSL涉及到的内容非常繁杂,包括各种术语、命令、算法等,所涉及到的我都没有完全理解,此篇随便笔者将会把自己理解的都尽量解释一下,如果需要深究,需要花大量的时间来完成
https协议默认的端口号为443
环境介绍
此篇随笔将搭建单向Https
本环境的安装默认使用yum源在线安装,笔者没有使用源码来安装是因为一直没有好一个模块,所以这里直接就用Yum安装,yum安装好过后不会去关心模块
- Linux CentOS 6.5
- Apache 2.2.15
- Openssl 1.0.1
环境安装
- 保证CentOS操作系统能够通外网
[[email protected] ~]# ping -c 3 www.baidu.com PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data. 64 bytes from 61.135.169.121: icmp_seq=1 ttl=52 time=40.3 ms 64 bytes from 61.135.169.121: icmp_seq=2 ttl=52 time=40.9 ms 64 bytes from 61.135.169.121: icmp_seq=3 ttl=52 time=39.7 ms --- www.a.shifen.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2042ms rtt min/avg/max/mdev = 39.705/40.339/40.920/0.497 ms
- 安装Apache httpd服务
[[email protected] ~]# yum -y install httpd
- 安装Openssl
[[email protected] ~]# yum -y install openssl
- 安装mod_ssl模块来实现对SSL的支持
[[email protected] ~]# yum -y install mod_ssl
[[email protected] ~]# ls -l /etc/httpd/conf.d/ssl.conf -rw-r--r--. 1 root root 9446 9月 19 11:08 /etc/httpd/conf.d/ssl.conf
创建CA(Certificate Authority)
CA也称为"根证书"
服务端做了一个证书,但是这是没有法律效力的,谁都可以自己做证书,就根本达不到安全的目的!所以就要有一个机构,负责来确认服务端的身份,然后统一的签发证书,这样才能有权威性
当用户用浏览器通过HTTPS协议访问一个网站,网站首先会发过来一个自己的证书(certificate),接下来浏览器就会到权威机构(CA),去验证一下这个证书是不是它签发的,如果是的话,就信任这个网站的证书,继续访问。如果不是的话,要怎么处理就依赖于实现了,一般的浏览器会弹出一个警告,让用户自己决定要不要继续访问,当然直接拒绝也是可以的
现在国际上有3大CA机构,如果是要自己做一个网站的话,如上所述,一般是需要请这些权威机构帮忙签发证书的!现在所有的主流浏览器,默认都安装了这些CA的根证书,所以如果网站的证书是这些权威机构签发的,浏览器就不会发出警告了。比如淘宝网证书是由GlobalSign签发的,所以访问淘宝网,浏览器不会发出警告
这里还有一个链条的关系,比如我有10个子网站,如果每个都要去找CA签发证书,就很麻烦,我可以找CA给我签发一个次级根证书,然后再用这个次级根证书给自己签发10个证书,那么只要客户的浏览器里有CA根证书就可以了,这10个证书都可以通过认证,不要求客户安装次级根证书
其实如果是企业应用,那完全可以自己给自己当CA,因为可以要求目标用户(操作系统)安装自己的CA根证书,效果是一样的,还可以省下请权威CA签发证书的费用(互联网应用分发自己的CA到无数的互联网用户上,难度非常大)
- 进入openssl的配置目录
[[email protected] ~]# cd /etc/pki/tls
[[email protected] tls]# ls -l 总用量 24 lrwxrwxrwx. 1 root root 19 9月 18 17:25 cert.pem -> certs/ca-bundle.crt drwxr-xr-x. 2 root root 4096 9月 18 19:42 certs //存放证书目录 drwxr-xr-x. 2 root root 4096 9月 18 19:30 misc -rw-r--r--. 1 root root 10906 6月 23 21:07 openssl.cnf //openssl配置文件 drwxr-xr-x. 2 root root 4096 9月 18 19:42 private //存放私钥和csr的目录
- 创建CA私钥
[[email protected] tls]# openssl genrsa -aes256 -out private/ca.key.pem 2048 //私钥文件名是ca.key.pem ,RSA的长度是2048,默认512 Generating RSA private key, 2048 bit long modulus ...+++ ..............................+++ e is 65537 (0x10001) Enter pass phrase for private/ca.key.pem: //创建一个私钥的密码 Verifying - Enter pass phrase for private/ca.key.pem: //再次输入密码
- 查看刚才创建的私钥信息
[[email protected] tls]# openssl rsa -noout -text -in private/ca.key.pem Enter pass phrase for private/ca.key.pem: //输入私钥密码 Private-Key: (2048 bit) ~~~看不懂啊~~~
最后的.pem扩展名,是表示该私钥用PEM编码,实际上私钥和证书都是用PEM编码的,PEM只是一种编码格式,httpd可以直接处理这种编码格式,但是浏览器和JAVA都不行,所以在需要的时候,会把编码从PEM改成PKCS,后面笔者会介绍,只要知道证书和私钥都有编码,只是编码是PEM还是PKCS的区别而已,就像编程中的"你好,世界"可以用UTF-8编码,也可以用GBK编码一样,内容是不变的
- 创建CA签名请求
[[email protected] tls]# openssl req -new -key private/ca.key.pem -out private/ca.csr -subj "/C=CN/ST=CQ/L=CQ/O=lansha/OU=lansha/CN=*.lansha.com" Enter pass phrase for private/ca.key.pem: //输入私钥密码
这里要注意的是,如果不用-subj参数,那么就会在命令行交互输入签发目标的身份识别信息,这叫DN(Distinguished Name),其中别的都不要紧,最重要的是CN那一行,因为我这里是根证书,所以我设置为*.lansha.com,这样我后面用这个CA签发的www.lansha.com、web.lansha.com ……,全都是有效的
- 生成的签名请求文件,ca.csr
[[email protected] tls]# openssl req -noout -text -in private/ca.csr Certificate Request: ~~~和上面一样,还是看不懂~~~
- 自己签发CA根证书
[[email protected] tls]# openssl x509 -req -days 365 -sha1 -extensions v3_ca -signkey private/ca.key.pem -in private/ca.csr -out certs/ca.cer //这里的参数非常复杂,x509证书格式,有效时间为1年,使用安全哈希算法 Signature ok subject=/C=CN/ST=CQ/L=CQ/O=lansha/OU=lansha/CN=*.lansha.com Getting Private key Enter pass phrase for private/ca.key.pem: //输入私钥密码
生成的ca.cer,就是最终的根证书了!这个文件非常重要,因为后续的服务端证书、客户端证书,都是用这个CA签发的,也要把它分发给客户,让他们导入到自己的浏览器或者系统中
- 把根证书从PEM编码转为PKCS编码
这步其实不是必选的,但是前面说过,JAVA环境是不能直接用PEM编码的证书的,很多浏览器也不行,所以有时候也需要转一下编码
得到的ca.p12就是转码后的CA根证书,在不能直接用ca.cer的时候,就用ca.p12代替
[[email protected] tls]# openssl pkcs12 -export -cacerts -inkey private/ca.key.pem -in certs/ca.cer -out certs/ca.p12 Enter pass phrase for private/ca.key.pem: //输入私钥密码 Enter Export Password: //可以新建一个密码 Verifying - Enter Export Password: //再次输入密码
签发服务端证书
现在CA根证书和私钥都有了,就可以开始签发服务端证书了(签发请求ca.csr是过程文件,有了cer就不再需要它了,要删掉也可以),下面的命令和签发CA证书时都差不多,但是参数上有区别
- 创建服务端私钥
[[email protected] tls]# openssl genrsa -aes256 -out private/server.key.pem 2048 Generating RSA private key, 2048 bit long modulus ...............................................+++ ........................................................................................................................................................................+++ e is 65537 (0x10001) Enter pass phrase for private/server.key.pem: //输入一个私钥密码 Verifying - Enter pass phrase for private/server.key.pem: //再次输入密码
- 创建服务端证书签发请求
[[email protected] tls]# openssl req -new -key private/server.key.pem -out private/server.csr -subj "/C=CN/ST=CQ/L=CQ/O=lansha/OU=lansha/CN=www.lansha.com" Enter pass phrase for private/server.key.pem: //输入私钥密码
和上面ca.csr的区别在于,这里的CN不是*.lansha.com,而是www.lansha.com,因为笔者现在是在为www.lansha.com申请证书
- 利用CA根证书,签发服务端证书
[[email protected] tls]# openssl x509 -req -days 365 -sha1 -extensions v3_req -CA certs/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/server.csr -out certs/server.cer Signature ok subject=/C=CN/ST=CQ/L=CQ/O=lansha/OU=lansha/CN=www.lansha.com Getting CA Private Key Enter pass phrase for private/ca.key.pem: //输入私钥密码
这里和前面自己签发CA证书时,参数区别就比较大了,最后得到的server.cer,就是服务端证书
配置文件编辑
- 编辑ssl.conf配置文件
[[email protected] tls]# cd /etc/httpd/conf.d/ [[email protected] conf.d]# vim ssl.conf <VirtualHost www.lansha.com:443> DocumentRoot "/var/www/html" ServerName www.lansha.com:443 ErrorLog logs/ssl_error_log TransferLog logs/ssl_access_log SSLEngine on SSLCertificateFile /etc/pki/tls/certs/server.cer SSLCertificateKeyFile /etc/pki/tls/private/server.key.pem #SSLCACertificateFile /etc/pki/tls/certs/ca.cer #SSLVerifyClient require #SSLVerifyDepth 10 </VirtualHost>
后面3个注释掉的,是双向认证才会用到
- 重启httpd服务
[[email protected] ~]# service httpd restart 停止 httpd: [确定] 正在启动 httpd:httpd: Could not reliably determine the server‘s fully qualified domain name, using www.lansha.com for ServerName Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog) Some of your private key files are encrypted for security reasons. In order to read them you have to provide the pass phrases. Server www.lansha.com:443 (RSA) //输入服务器私钥密码 Enter pass phrase: OK: Pass Phrase Dialog successful. [确定]
- 加入防火墙规则
[[email protected] ~]# iptables -I INPUT -p tcp --dport 443 -j ACCEPT [[email protected] ~]# service iptables save //保存防火墙规则 iptables:将防火墙规则保存到 /etc/sysconfig/iptables: [确定]
测试单向认证
- 写入一个Index.html 至网站默认目录
[[email protected] ~]# echo "<h1>Test Https</h1>" > /var/www/html/index.html
- 用 https://localhost尝试来访问,浏览器报警
上面配置文件中我只给 www.lansha.com 域名监听443端口
前面创建CSR时,输入的CN的作用,这个证书是为www.lansha.com申请的,这里请求的地址却是localhost,不匹配所以报错,为了能用www.lansha.com这个主机名来访问,可以使用搭建DNS或者修改Hosts文件
[[email protected] ~]# vim /etc/hosts 192.168.1.134 www.lansha.com
- 用 https://www.lansha.com 尝试访问
这次浏览器还是告警,但是告警信息变了
- 查看一下这个站点的证书信息
可以看到这个证书是由*.lansha这个CA颁发的,浏览器不认识,所以不信任由这个CA签发的所有证书
接下来就需要把ca.cer导入浏览器,这里直接导入server.cer也是可以的,但是后面如果又创建一个网站比如说www2.lansha.com、www3.lansha.com,那么又不行了,所以最好的办法是直接导入CA根证书,那么后续只要是用这个根证书签发的证书,浏览器都会信任
- 导入证书
浏览器-->编辑-->首选项-->高级-->加密-->查看证书-->证书机构--导入证书
- 再次访问,可以看到成功了,浏览器不告警,并且URL栏前面有一个小锁
到这里Https就搭建完成了,思路还是非常清晰的