Apache服务器访问过慢分析及解决
起因:线上的一台服务器,最近总是出现 访问 很慢的情况发生,点击一个链接要2秒钟以上才能打开,按照我们对于访问人数的估计,服务器应该不至于响应这么慢,从而需要针对这个问题进行分析,来解决网站访问过慢。
分析:
1、首先,在页面访问变慢情况发生时,使用 top 命令查看了服务器的负载情况,发现负载并不高,初步估计不是程序的问题。
2、然后,查看了线程中的 httpd 的数量, ps -aux | grep httpd | wc -l 发现,线程数已经达到了 apache 设置的最大值。由此断定是网站访问人数过多造成了访问过慢。
3、为了验证,查看了连接数和当前的连接数,分别是
netstat -ant | grep $ip:80 | wc -l netstat -ant | grep $ip:80 | grep EST | wc -l发现果然,连接数特别多,远远超过我们的估计值。
4、刚开始的时候,对于服务器的 MPM 配置方式不是特别的熟悉,认为修改服务器配置可以解决问题。主要的配置部分包括 prefork 模式 或者 work 模式的配置,下面是一些简单的介绍。
prefork 模式:
以 prefork 模式工作的 apache 的默认配置:
<IfModule mpm_prefork_module> ServerLimit 2000 StartServers 5 #指定服务器启动时建立的子进程数量 MinSpareServers 5 #指定空闲子进程的最小数量 MaxSpareServers 10 #指定空闲子进程的最大数量 MaxClients 150 #指定同一时间客户端最大接入请求的数量(单个进程并发线程数),任何超过该限制的请求都将进入等候队列,一旦一个连接被释放,队列中的请求将得到服务 MaxRequestsPerChild 0 #指定每个子进程在其生存周期内允许伺服的最大请求数量,默认为10000,0表示子进程永远不结束 </IfModule>
prefork 控制进程在最初建立“StartServers”个子进程后,为了满足 MinSpareServers 设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。
MaxSpareServers 设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比 MinSpareServers小,Apache会自动把其调整为 MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxClients是这些指令中最为重要的一个,设定的是 Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grephttpd|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。在 apache2 中通过ServerLimit指令无须重编译Apache就可以加大MaxClients。
虽然通过设置ServerLimit,我们可以把MaxClients加得很大,但是往往会适得其反,系统耗光所有内存。以一台服务器为例:内存2G,每个apache进程消耗大约0.5%(可通过ps aux来确认)的内存,也就是10M,这样,理论上这台服务器最多跑200个apache进程就会耗光系统所有内存,所以,设置MaxClients要慎重。
worker 模式:
以 worker 模式工作的 apache 的默认配置为:
<IfModule mpm_worker_module> StartServers 2 MaxClients 150 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 </IfModule>
Worker 由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,
MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients 设置了同时连入的clients最大总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。
MinSpareThreads和 MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大,可以按照实际情况相应调节。
ThreadsPerChild是worker MPM中与性能相关最密切的指令。
ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用 ThreadLimit指令,它的最大缺省值是20000。
Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。需要注意的是,如果显式声明了ServerLimit,那么它乘以 ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则 Apache将会自动调节到一个相应值。
服务器的apache采用的是 prefork 的工作模式,对 MaxClients 进行了相应的调整,发现服务启动后很短时间,连接数就能够达到最大。
5、后来想到需要查看用户都是访问的那些页面,将配置中的 access_log 打开,发现85%以上的访问都是直接访问的资源文件,由此判定,用户可能使用了多线程的下载工具,或者这些资源遭受了盗链。
6、找到了问题所在,进行解决也就比较好办了。想到了两个方法:
A、对单个IP进行连接的线程限制,不允许多线程连接资源。
对于IP限制,我采用了 mod_limitipconn 这个模块。这个模块的好处是比较简单,缺点是不能够针对单独的文件夹或者文件进行设置,而且不支持虚拟主机。
在 apache 中安装了这个模块后,在配置文件中添加如下几段就可以生效了:
ExtendedStatus On <IfModule mod_limitipconn.c > < Location / > # 所有虚拟主机的/目录 MaxConnPerIP 3 # 每IP只允许3个并发连接 NoIPLimit image/* # 对图片不做IP限制 < /Location > <Location /mp3 > # 所有主机的/mp3目录 MaxConnPerIP1 # 每IP只允许一个连接请求 OnlyIPLimitaudio/mpeg video # 该限制只对视频和音频格式的文件 < /Location > </IfModule >
B、添加URL重写,防止盗链。
防止盗链,一个重要的方法就是判断请求的 refer,但是如果使用一些浏览器发出请求的时候将 refer 去掉,或者伪装,这个办法就无能为力了。但是貌似还有更高级的方法,还是可以实现这个功能。
安装apache的 mod_rewrite 模块后,在apache配置文件中添加
RewriteEngine On RewriteCond %{HTTP_REFERER} !^http://abc.com/.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://abc.com$ [NC] RewriteCond %{HTTP_REFERER} !^http://www.abc.com/.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://www.abc.com$ [NC] RewriteRule .*.(gif|jpg|swf)$ http://www.abc.com/about/nolink.png [R,NC]
这样盗链的请求会被重定向到一个错误页面,从而减少下载带给服务器的压力。
参考资料:
1、部署Apache 的一些技巧。
2、Apache Server 负载能力测试
3、Apache AB
4、Apache的参数设置
5、Ab的用法
6、Apache限制连接数和并发数
7、Apache安装mod_rewrite模块
8、Apache防盗链的简单实现
Windows系统下如果优化Apache的性能主要是通过专门针对Windows NT优化的MPM(多路处理模块)-mpm_winnt.c来优化的,它使用一个单独的父进程产生一个单独的子进程,在这个子进程中轮流产生多个线程来处理请求。也就是说mpm_winnt只能启动父子两个进程, 不能像Linux下那样同时启动多个进程。 mpm_winnt主要通过ThreadsPerChild和MaxRequestsPerChild两个参数来优化Apache。 ThreadsPerChild 这个参数用于设置每个进程的线程数, 子进程在启动时建立这些线程后就不再建立新的线程了.一方面因为mpm_winnt不能启动多个进程, 所以这个数值要足够大,以便可以处理可能的请求高峰;另一方面该参数以服务器的响应速度为准的, 数目太大的反而会变慢。因此需要综合均衡一个合理的数值。mpm_winnt上的默认值是64, 最大值是1920. 这里建议设置为100-500之间,服务器性能高的话值大一些,反之值小一些。 MaxRequestsPerChild 该参数表示每个子进程能够处理的最大请求数, 即同时间内子进程数目.设置为零表示不限制, mpm_winnt上的默认值就是0. 官方参考手册中不建议设置为0, 主要基于两点考虑: (1) 可以防止(偶然的)内存泄漏无限进行,从而耗尽内存; (2) 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。 因此这个参数的值更大程度上取决于服务器的内存,如果内存比较大的话可以设置为0或很大的数字,否则设置一个小的数值。需要说明的是,如果这个值设置的太小的话会造成Apache频繁重启,在日志文件中会看到如下的文字:Processexiting because it reached MaxRequestsPerChild. Signaling the parent,这样一来降低了Apache的总体性能。 另外,可以通过查看Apache提供的server-status(状态报告)来验证当前所设置数值是否合理,在httpd.conf文件中做如下设置来打开它: # 首先需要加载mod_status模块 LoadModule status_module modules/mod_status.so # 然后设置访问的地址 <Location /server-status> SetHandler server-status Orderdeny,allow Deny from all # 如果限制某个IP访问则设置为 Allow from 192.168.1.1 Allow from all </Location> 综合来说,因为Windows NT下Apache只能启动父子两个进程,因此只能通过增大单个进程的线程数以及单个进程能够处理的最大请求数来进行优化。其他优化的参数同Linux系统下是一样的,大家可以加以参考。下面针对上述两个参数给出一个建议的设置: <IfModule mpm_winnt.c> ThreadsPerChild 250MaxRequestsPerChild 5000 </IfModule> 用上面的方法优化了一下windows+apache+php后,发现响应速度快了很多,一般最多只延迟3秒左右,但对于美国的主机来说应该是个正常的状态吧!
大型网站HTTPS实践三:基于协议和配置的优化
1 前言
上文讲到 HTTPS对用户访问速度的影响。
本文就为大家介绍HTTPS在访问速度,计算性能,安全等方面基于协议和配置的优化。
2 HTTPS 访问速度优化
2.1 Tcp fast open
HTTPS 和 HTTP使用 TCP 协议进行传输,也就意味着必须通过三次握手建立 TCP连接,但一个 RTT 的时间内只传输一个 syn 包是不是太浪费?能不能在 syn 包发出的同时捎上应用层的数据?其实是可以的,这也是 tcp fast open的思路,简称TFO。具体原理可以参考rfc7413。
遗憾的是TFO需要高版本内核的支持,linux从 3.7以后支持TFO,但是目前的windows系统还不支持 TFO,所以只能在公司内部服务器之间发挥作用。
2.2 HSTS
前面提到过将用户HTTP请求 302 跳转到HTTPS,这会有两个影响:
1、不安全,302跳转不仅暴露了用户的访问站点,也很容易被中间者支持。
2、降低访问速度,302跳转不仅需要一个 RTT,浏览器执行跳转也需要执行时间。
由于 302跳转事实上是由浏览器触发的,服务器无法完全控制,这个需求导致了 HSTS的诞生:
HSTS(HTTP Strict Transport Security)。服务端返回一个HSTS的 httpheader,浏览器获取到HSTS头部之后,在一段时间内,不管用户输入www.baidu.com还是http://www.baidu.com,都会默认将请求内部跳转成https://www.baidu.com。
Chrome, firefox, ie 都支持了HSTS(http://caniuse.com/#feat=stricttransportsecurity)。
2.3 Session resume
Session resume 顾名思义就是复用session,实现简化握手。复用session的好处有两个:
1、减少了 CPU消耗,因为不需要进行非对称密钥交换的计算。
2、提升访问速度,不需要进行完全握手阶段二,节省了一个 RTT和计算耗时。
TLS 协议目前提供两种机制实现 session resume,分别介绍一下。
2.3.1 Session cache
Session cache 的原理是使用client hello中的 session id查询服务端的 session cache,如果服务端有对应的缓存,则直接使用已有的 session信息提前完成握手,称为简化握手。
Session cache 有两个缺点:
1、需要消耗服务端内存来存储 session内容。
2、目前的开源软件包括 nginx,apache只支持单机多进程间共享缓存,不支持多机间分布式缓存,对于百度或者其他大型互联网公司而言,单机 session cache几乎没有作用。
Session cache 也有一个非常大的优点:
session id是 TLS 协议的标准字段,市面上的浏览器全部都支持 session cache。
百度通过对TLS握手协议及服务器端实现的优化,已经支持全局的 session cache,能够明显提升用户的访问速度,节省服务器计算资源。
2.3.2 Session ticket
上节提到了session cache的两个缺点,session ticket能够弥补这些不足。
Session ticket 的原理参考RFC4507。简述如下:
server将 session 信息加密成 ticket 发送给浏览器,浏览器后续握手请求时会发送 ticket,server端如果能成功解密和处理 ticket,就能完成简化握手。
显然,sessionticket的优点是不需要服务端消耗大量资源来存储 session内容。
Session ticket 的缺点:
1、session ticket只是 TLS 协议的一个扩展特性,目前的支持率不是很广泛,只有 60%左右。
2、session ticket需要维护一个全局的key来加解密,需要考虑KEY的安全性和部署效率。
总体来讲,sessionticket的功能特性明显优于session cache。希望客户端实现优先支持 session ticket。
2.4 Ocsp stapling
Ocsp 全称在线证书状态检查协议 (rfc6960),用来向 CA站点查询证书状态,比如是否撤销。通常情况下,浏览器使用 OCSP协议发起查询请求,CA返回证书状态内容,然后浏览器接受证书是否可信的状态。
这个过程非常消耗时间,因为CA站点有可能在国外,网络不稳定,RTT也比较大。那有没有办法不直接向CA站点请求OCSP 内容呢?ocspstapling 就能实现这个功能。
详细介绍参考RFC6066第 8 节。简述原理就是浏览器发起 client hello时会携带一个certificate status request的扩展,服务端看到这个扩展后将 OCSP内容直接返回给浏览器,完成证书状态检查。
由于浏览器不需要直接向CA站点查询证书状态,这个功能对访问速度的提升非常明显。
Nginx 目前已经支持这个 ocsp stapling file,只需要配置ocsp stapling file的指令就能开启这个功能:
· ssl_staplingon;ssl_stapling_file ocsp.staple;
2.5 False start
通常情况下,应用层数据必须等完全握手全部结束之后才能传输。这个其实比较浪费时间,那能不能类似 TFO一样,在完全握手的第二个阶段将应用数据一起发出来呢?google提出了 false start来实现这个功能。详细介绍参考https://tools.ietf.org/html/draft-bmoeller-tls-falsestart-00。
简单概括False start的原理就是在 client_key_exchange发出时将应用层数据一起发出来,能够节省一个 RTT。
False start 依赖于 PFS(perfect forward secrecy完美前向加密),而PFS又依赖于DHE 密钥交换系列算法(DHE_RSA,ECDHE_RSA, DHE_DSS, ECDHE_ECDSA),所以尽量优先支持 ECDHE密钥交换算法实现 false start。
2.6 使用SPDY或者 HTTP2
SPDY 是 google推出的优化 HTTP 传输效率的协议(https://www.chromium.org/spdy),它基本上沿用了HTTP协议的语义, 但是通过使用帧控制实现了多个特性,显著提升了 HTTP协议的传输效率。
SPDY 最大的特性就是多路复用,能将多个 HTTP请求在同一个连接上一起发出去,不像目前的 HTTP协议一样,只能串行地逐个发送请求。Pipeline虽然支持多个请求一起发送,但是接收时依然得按照顺序接收,本质上无法解决并发的问题。
HTTP2 是 IETF 2015年 2 月份通过的 HTTP 下一代协议,它以 SPDY 为原型,经过两年多的讨论和完善最终确定。
本文就不过多介绍SPDY和 HTTP2 的收益,需要说明两点:
1、SPDY和 HTTP2 目前的实现默认使用 HTTPS 协议。
2、SPDY和 HTTP2 都支持现有的 HTTP 语义和API,对 WEB应用几乎是透明的。
Google 宣布 chrome浏览器 2016 年将放弃 SPDY 协议,全面支持 HTTP2,但是目前国内部分浏览器厂商进度非常慢,不仅不支持 HTTP2,连 SPDY 都没有支持过。
百度服务端和百度手机浏览器现在都已经支持 SPDY3.1协议。
3 HTTPS 计算性能优化
3.1 优先使用ECC
ECC 椭圆加密算术相比普通的离散对数计算速度性能要强很多。下表是 NIST推荐的密钥长度对照表。
表格 2 NIST推荐使用的密钥长度
对于 RSA算法来讲,目前至少使用2048位以上的密钥长度才能保证安全性。ECC只需要使用224位长度的密钥就能实现RSA2048位长度的安全强度。在进行相同的模指数运算时速度显然要快很多。
3.2 使用最新版的 openssl
一般来讲,新版的openssl相比老版的计算速度和安全性都会有提升。比如 openssl1.0.2采用了intel 最新的优化成果,椭圆曲线p256 的计算性能提升了 4倍。(https://eprint.iacr.org/2013/816.pdf)
Openssl 2014 年就升级了 5次,基本都是为了修复实现上的 BUG或者算法上的漏洞而升级的。所以尽量使用最新版本,避免安全上的风险。
3.3 硬件加速方案
现在比较常用的TLS硬件加速方案主要有两种:
1、SSL专用加速卡。
2、GPU SSL加速。
上述两个方案的主流用法都是将硬件插入到服务器的 PCI插槽中,由硬件完成最消耗性能的计算。但这样的方案有如下缺点:
1、支持算法有限。比如不支持 ECC,不支持 GCM等。
2、升级成本高。
a) 出现新的加密算法或者协议时,硬件加速方案无法及时升级。
b) 出现比较大的安全漏洞时,部分硬件方案在无法在短期内升级解决。比如 2014年暴露的 heartbleed漏洞。
3、无法充分利用硬件加速性能。硬件加速程序一般都运行在内核态,计算结果传递到应用层需要 IO和内存拷贝开销,即使硬件计算性能非常好,上层的同步等待和 IO开销也会导致整体性能达不到预期,无法充分利用硬件加速卡的计算能力。
4、维护性差。硬件驱动及应用层 API大部分是由安全厂家提供,出现问题后还需要厂家跟进。用户无法掌握核心代码,比较被动。不像开源的 openssl,不管算法还是协议,用户都能掌握。
3.4 TLS 远程代理计算
也正是因为上述原因,百度实现了专用的 SSL硬件加速集群。基本思路是:
1、优化 TLS协议栈,剥离最消耗 CPU资源的计算,主要有如下部分:
a) RSA中的加解密计算。
b) ECC算法中的公私钥生成。
c) ECC算法中的共享密钥生成。
2、优化硬件计算部分。硬件计算不涉及协议及状态交互,只需要处理大数运算。
3、Web server到 TLS 计算集群之间的任务是异步的。即 web server将待计算内容发送给加速集群后,依然可以继续处理其他请求,整个过程是异步非阻塞的。
4 HTTPS 安全配置
4.1 协议版本选择
SSL2.0 早就被证明是不安全的协议了,统计发现目前已经没有客户端支持 SSL2.0,所以可以放心地在服务端禁用 SSL2.0协议。
2014 年爆发了 POODLE攻击,SSL3.0 因此被证明是不安全的。但是统计发现依然有 0.5%的流量只支持 SSL3.0。所以只能有选择地支持 SSL3.0。
TLS1.1 及 1.2目前为止没有发现安全漏洞,建议优先支持。
4.2 加密套件选择
加密套件包含四个部分:
1、非对称密钥交换算法。建议优先使用 ECDHE,禁用 DHE,次优先选择 RSA。
2、证书签名算法。由于部分浏览器及操作系统不支持 ECDSA签名,目前默认都是使用 RSA签名,其中 SHA1 签名已经不再安全,chrome 及微软 2016 年开始不再支持 SHA1签名的证书(http://googleonlinesecurity.blogspot.jp/2014/09/gradually-sunsetting-sha-1.html)。
3、对称加解密算法。优先使用 AES-GCM算法,针对 1.0 以上协议禁用 RC4( rfc7465)。
4、内容一致性校验算法。Md5和 sha1 都已经不安全,建议使用 sha2 以上的安全哈希函数。
4.3 HTTPS 防攻击
4.3.1 防止协议降级攻击
降级攻击一般包括两种:加密套件降级攻击 (cipher suite rollback)和协议降级攻击(version roll back)。降级攻击的原理就是攻击者伪造或者修改 client hello消息,使得客户端和服务器之间使用比较弱的加密套件或者协议完成通信。
为了应对降级攻击,现在server端和浏览器之间都实现了SCSV功能,原理参考https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00。
一句话解释就是如果客户端想要降级,必须发送 TLS_SCSV的信号,服务器如果看到 TLS_SCSV,就不会接受比服务端最高协议版本低的协议。
4.3.2 防止重新协商攻击
重新协商(tlsrenegotiation)分为两种:加密套件重协商 (cipher suite renegotiation)和协议重协商(protocolrenegotiation)。
重新协商会有两个隐患:
1、重协商后使用弱的安全算法。这样的后果就是传输内容很容易泄露。
2、重协商过程中不断发起完全握手请求,触发服务端进行高强度计算并引发服务拒绝。
对于重协商,最直接的保护手段就是禁止客户端主动重协商,当然出于特殊场景的需求,应该允许服务端主动发起重协商。
5 结束语
HTTPS 的实践和优化涉及到了非常多的知识点,由于篇幅关系,本文对很多优化策略只是简单介绍了一下.如果想要了解协议背后的原理,还是需要详细阅读 TLS协议及 PKI 知识。对于大型站点来说,如果希望做到极致,HTTPS的部署需要结合产品和基础设施的架构来进行详细的考虑,比起部署支持 HTTPS的接入和对它的优化,在产品和运维层面上花费的功夫会更多。
大型网站的HTTPS实践一:HTTPS协议和原理
1 前言
百度已经于近日上线了全站HTTPS的安全搜索,默认会将HTTP请求跳转成HTTPS。本文重点介绍HTTPS协议, 并简单介绍部署全站HTTPS 的意义。
2 HTTPS 协议概述
HTTPS 可以认为是 HTTP + TLS。HTTP协议大家耳熟能详了,目前大部分 WEB应用和网站都是使用 HTTP协议传输的。
TLS 是传输层加密协议,它的前身是 SSL协议,最早由 netscape公司于 1995 年发布,1999 年经过 IETF讨论和规范后,改名为 TLS。如果没有特别说明,SSL和 TLS 说的都是同一个协议。
HTTP 和 TLS在协议层的位置以及 TLS协议的组成如下图:
图 1 TLS协议格式
TLS 协议主要有五部分:应用数据层协议,握手协议,报警协议,加密消息确认协议,心跳协议。
TLS 协议本身又是由 record协议传输的,record协议的格式如上图最右所示。
目前常用的HTTP协议是HTTP1.1,常用的TLS协议版本有如下几个:TLS1.2,TLS1.1, TLS1.0和 SSL3.0。其中 SSL3.0由于 POODLE 攻击已经被证明不安全,但统计发现依然有不到 1%的浏览器使用 SSL3.0。TLS1.0也存在部分安全漏洞,比如 RC4和 BEAST 攻击。
TLS1.2 和 TLS1.1暂时没有已知的安全漏洞,比较安全,同时有大量扩展提升速度和性能,推荐大家使用。
需要关注一点的就是TLS1.3将会是TLS 协议一个非常重大的改革。不管是安全性还是用户访问速度都会有质的提升。不过目前没有明确的发布时间。
同时 HTTP2也已经正式定稿,这个由SPDY协议演化而来的协议相比HTTP1.1又是一个非常重大的变动,能够明显提升应用层数据的传输效率。
3 HTTPS 功能介绍
百度使用HTTPS协议主要是为了保护用户隐私,防止流量劫持。
HTTP 本身是明文传输的,没有经过任何安全处理。例如用户在百度搜索了一个关键字,比如“苹果手机”,中间者完全能够查看到这个信息,并且有可能打电话过来骚扰用户。也有一些用户投诉使用百度时,发现首页或者结果页面浮了一个很长很大的广告,这也肯定是中间者往页面插的广告内容。如果劫持技术比较低劣的话,用户甚至无法访问百度。
这里提到的中间者主要指一些网络节点,是用户数据在浏览器和百度服务器中间传输必须要经过的节点。比如 WIFI热点,路由器,防火墙,反向代理,缓存服务器等。
在 HTTP协议下,中间者可以随意嗅探用户搜索内容,窃取隐私甚至篡改网页。不过 HTTPS是这些劫持行为的克星,能够完全有效地防御。
总体来说,HTTPS协议提供了三个强大的功能来对抗上述的劫持行为:
1、内容加密。浏览器到百度服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。
2、身份认证。保证用户访问的是百度服务,即使被 DNS劫持到了第三方站点,也会提醒用户没有访问百度服务,有可能被劫持
3、数据完整性。防止内容被第三方冒充或者篡改。
那 HTTPS是如何做到上述三点的呢?下面从原理角度介绍一下。
4 HTTPS 原理介绍
4.1 内容加密
加密算法一般分为两种,对称加密和非对称加密。所谓对称加密(也叫密钥加密)就是指加密和解密使用的是相同的密钥。而非对称加密(也叫公钥加密)就是指加密和解密使用了不同的密钥。
图 2对称加密
图 3非对称加密
对称内容加密强度非常高,一般破解不了。但存在一个很大的问题就是无法安全地生成和保管密钥。假如客户端软件和服务器之间每次会话都使用固定的,相同的密钥加密和解密,肯定存在很大的安全隐患。如果有人从客户端端获取到了对称密钥,整个内容就不存在安全性了,而且管理海量的客户端密钥也是一件很复杂的事情。
非对称加密主要用于密钥交换(也叫密钥协商),能够很好地解决这个问题。浏览器和服务器每次新建会话时都使用非对称密钥交换算法协商出对称密钥,使用这些对称密钥完成应用数据的加解密和验证,整个会话过程中的密钥只在内存中生成和保存,而且每个会话的对称密钥都不相同(除非会话复用),中间者无法窃取。
非对称密钥交换很安全,但同时也是HTTPS性能和速度严重降低的“罪魁祸首”。想要知道HTTPS为什么影响速度,为什么消耗资源,就一定要理解非对称密钥交换的整个过程。
下面重点介绍一下非对称密钥交换的数学原理及在 TLS握手过程中的应用。
4.1.1 非对称密钥交换
在非对称密钥交换算法出现以前,对称加密一个很大的问题就是不知道如何安全生成和保管密钥。非对称密钥交换过程主要就是为了解决这个问题,使得对称密钥的生成和使用更加安全。
密钥交换算法本身非常复杂,密钥交换过程涉及到随机数生成,模指数运算,空白补齐,加密,签名等操作。
常见的密钥交换算法有RSA,ECDHE,DH,DHE等算法。它们的特性如下:
· RSA:算法实现简单,诞生于1977 年,历史悠久,经过了长时间的破解测试,安全性高。缺点就是需要比较大的素数(目前常用的是 2048 位)来保证安全强度,很消耗 CPU 运算资源。RSA 是目前唯一一个既能用于密钥交换又能用于证书签名的算法。
· DH:diffie-hellman密钥交换算法,诞生时间比较早(1977年),但是1999 年才公开。缺点是比较消耗 CPU性能。
· ECDHE:使用椭圆曲线(ECC)的 DH 算法,优点是能用较小的素数(256 位)实现 RSA相同的安全等级。缺点是算法实现复杂,用于密钥交换的历史不长,没有经过长时间的安全攻击测试。
· ECDH:不支持 PFS,安全性低,同时无法实现false start。
· DHE:不支持 ECC。非常消耗 CPU资源。
建议优先支持RSA和 ECDH_RSA密钥交换算法。原因是:
1、ECDHE支持 ECC 加速,计算速度更快。支持 PFS,更加安全。支持 false start,用户访问速度更快。
2、目前还有至少 20%以上的客户端不支持 ECDHE,我们推荐使用
RSA