摘要
本文主要是在測試https服務(wù)時(shí)對(duì)搭建https服務(wù)器的一些實(shí)踐總結(jié)瞭亮。TLS協(xié)議的介紹部分來源于對(duì)RFC5246的理解优幸,不當(dāng)之處,還請指出。后面包含一段對(duì)https的性能分析的工程實(shí)踐珠月。
1 TLS協(xié)議簡介
1.1 簡介
TSL是傳輸層安全協(xié)議(Transport Secure Protocol)的簡稱,它的前身是SSL(Secure Sockets Layer)楔敌。TLS的設(shè)計(jì)目標(biāo)是為互聯(lián)網(wǎng)通信提供安全保證啤挎,防止數(shù)據(jù)被竊聽,篡改卵凑。TLS協(xié)議由記錄層(TLS Record Layer)和握手層(TLS Handshake Layer)組成庆聘,記錄層處于協(xié)議的最低層,為TLS協(xié)議提供安全可靠的連接勺卢。TLS在協(xié)議棧中處于HTTP和TCP協(xié)議之間伙判,但是TLS協(xié)議是獨(dú)立于應(yīng)用層協(xié)議的,也就是說高層的應(yīng)用層協(xié)議黑忱,如HTTP宴抚,F(xiàn)TP等都可以創(chuàng)建在TLS之上勒魔,TLS的下層可以是任何可靠傳輸層協(xié)議,如TCP菇曲,SPX等冠绢。
1.2 TLS的版本演進(jìn)
發(fā)布時(shí)間 | 版本 | RFC地址 |
---|---|---|
N/A | SSL1.0 | |
1995 | SSL2.0 | rfc6176 |
1996 | SSL3.0 | |
1999 | TLS1.0 | |
2006 | TLS1.1 | |
2008 | TLS1.2 | rfc5246 |
TLS目前已發(fā)布的最新版本是TLS1.2,它在RFC5246中定義常潮,其前身SSL1.0弟胀,SSL2.0和SSL3.0。SSL由于安全漏洞喊式,已逐漸在被淘汰孵户;TLS1.0和SSL3.0差異很小,幾乎等同岔留,漸漸也不再使用延届,所以現(xiàn)在的話,只要注意TLS1.1以上的版本贸诚。
1.3 TLS握手過程
TLS分為記錄層協(xié)議和握手層協(xié)議:
記錄層協(xié)議(TLS Record Protocol):
記錄層協(xié)議負(fù)責(zé)將要發(fā)出的消息進(jìn)行分片方庭,壓縮,打上消息認(rèn)證碼(MAC)并最終交到傳輸層酱固;或?qū)⒔邮盏降臄?shù)據(jù)進(jìn)行解壓械念,解密,數(shù)據(jù)校驗(yàn)运悲,重新 組裝后傳到上一層龄减。
握手層協(xié)議(TLS Handshake Protocol):
握手層協(xié)議處于記錄層協(xié)議之上,握手層協(xié)議的作用是在真正的應(yīng)用數(shù)據(jù)傳輸之前班眯,使客戶端和服務(wù)器互相進(jìn)行身份認(rèn)證希停,協(xié)商加密算法以及生成加密密鑰。握手層用于協(xié)商出記錄層的參數(shù)署隘。這些參數(shù)將會(huì)被記錄層用于雙方的身份認(rèn)證宠能,實(shí)例化協(xié)商的安全參數(shù),錯(cuò)誤報(bào)告磁餐。
TLS在協(xié)議棧中的位置:
TLS的握手過程:
- 客戶端發(fā)送ClientHello消息违崇,包含可選密碼組件,一個(gè)客戶端生成的隨機(jī)數(shù)等诊霹,服務(wù)端接收后回一個(gè)ServerHello消息給客戶端羞延,確定密碼方案,并生成一個(gè)服務(wù)器隨機(jī)數(shù)脾还,發(fā)給客戶端伴箩。
這一步的數(shù)據(jù)傳輸在TCP上進(jìn)行,數(shù)據(jù)都是公開的鄙漏,中間人攻擊者可以很輕松的得到這些數(shù)據(jù)嗤谚。- 服務(wù)器發(fā)送證書棺蛛,服務(wù)器的身份確認(rèn)成功后;服務(wù)器可能會(huì)請求一個(gè)客戶端證書呵恢,要求客戶端進(jìn)行身份認(rèn)證鞠值,客戶端給服務(wù)器發(fā)出證書,驗(yàn)明身份渗钉。這一步不是必須的彤恶。
- 客戶端向服務(wù)器發(fā)出摘要認(rèn)證,確認(rèn)接收的消息的完整性鳄橘,保證沒有被第三方篡改声离。
- 雙方交換必需的加密參數(shù)。其中包括一個(gè)預(yù)主密鑰瘫怜,客戶端會(huì)用服務(wù)器證書中的公鑰將這個(gè)密鑰加密傳給服務(wù)器术徊,服務(wù)器使用私鑰進(jìn)行解密。
- 客戶端生成一個(gè)預(yù)主密鑰鲸湃,并使用服務(wù)器證書中的公鑰加密赠涮,服務(wù)器解密后生成一個(gè)主密鑰。雙方使用這個(gè)主密鑰(master secret)對(duì)應(yīng)用層數(shù)據(jù)進(jìn)行對(duì)稱加密(如AES256)暗挑。 主密鑰是客戶端和服務(wù)器共享的笋除。
- 最后,把這些準(zhǔn)備好的的安全參數(shù)交給記錄層協(xié)議炸裆。
下圖轉(zhuǎn)自維基百科TLS詞條 https://zh.wikipedia.org/wiki/%E5%82%B3%E8%BC%B8%E5%B1%A4%E5%AE%89%E5%85%A8%E5%8D%94%E8%AD%B0:
會(huì)話恢復(fù)過程:
客戶端服務(wù)器出于性能的考慮垃它,可能會(huì)恢復(fù)前面的會(huì)話,或復(fù)制一個(gè)當(dāng)前存在的會(huì)話烹看,而不是重新協(xié)商密碼參數(shù)国拇,建立新的會(huì)話(4.2部分使用tcpdump跟蹤發(fā)現(xiàn),這個(gè)過程確實(shí)是耗時(shí)占比很大)惯殊。
- 客戶端發(fā)出一個(gè)ClientHello消息酱吝,這個(gè)消息包含要恢復(fù)的會(huì)話的Session ID。
- 服務(wù)接到這個(gè)SessionID后靠胜,檢查它的緩存是否存在該會(huì)話ID掉瞳。如果找到了,服務(wù)器將使用該會(huì)話狀態(tài)重建連接浪漠,并發(fā)一個(gè)ServerHello給客戶端,其中包含一個(gè)和ClientHello消息一模一樣的SessionID霎褐。
- 此時(shí)址愿,協(xié)議規(guī)定,必須要雙方發(fā)出ChangeCipherSpec消息冻璃,并接著發(fā)出Finished消息確認(rèn)握手完成响谓。然后客戶端服務(wù)器就可以傳輸應(yīng)用層數(shù)據(jù)了损合。
- 如果服務(wù)器沒有在緩存中找到Session ID,那么新的SessionID將會(huì)建立娘纷,然后又會(huì)執(zhí)行一次完全握手嫁审。
2 使用nginx搭建https服務(wù)器
2.1 環(huán)境準(zhǔn)備
先搭建nginx,nginx的搭建在官網(wǎng)中可以找到 http://nginx.org/en/docs/install.html
注意如果是用源碼編譯赖晶,有的較老版本構(gòu)建編譯時(shí)需要帶上參數(shù)--with-http_ssl_module律适,最新的nginx版本是默認(rèn)有這個(gè)編譯參數(shù)的。
配置:
server {
listen 443 ssl;
server_name somehost;
ssl_certificate $somehost.crt;
ssl_certificate_key $somehost.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
** ssl_certificate** : 存放服務(wù)器證書的地址遏插,主要用于數(shù)字證書的身份認(rèn)證捂贿。所有連到服務(wù)器的客戶端都能拿到這個(gè)證書;
*** ssl_certificate_key*** : 是私鑰胳嘲,只能被服務(wù)器知道厂僧。
ssl_protocols, ssl_ciphers選項(xiàng)是可選的了牛。
2.2 詳細(xì)操作步驟
下面嘗試在本地搭建一個(gè)簡單的https服務(wù)器颜屠,在443端口監(jiān)聽。
步驟如下:
- 搭建一個(gè)nginx服務(wù)器鹰祸;
- 使用openssl生成服務(wù)器私鑰甫窟,客戶端私鑰,服務(wù)器公鑰福荸,客戶端公鑰蕴坪;
- 生成CA根證書,為服務(wù)器證書和客戶端證書(可選)提供簽名服務(wù);
- 生成服務(wù)器證書和客戶端證書敬锐,并請求CA的簽名背传;
- 在操作系統(tǒng)上信任我們偽造的服務(wù)器證書,這里沒有為客戶端生成證書台夺;
- 隨便寫一個(gè)web服務(wù)径玖,提供一個(gè)url返回一段靜態(tài)報(bào)文,讓nginx為它做一下代理颤介,然后啟動(dòng)這個(gè)web服務(wù)器梳星;
- 測試。
以下是這些步驟的操作命令:
****生成服務(wù)端私鑰****:
$ openssl genrsa -out server.key 2048
****生成服務(wù)端公鑰****:
$ openssl rsa -in server.key -pubout -out server.pem
****生成客戶端私鑰****:
$ openssl genrsa -out client.key 2048
****生成客戶端公鑰****:
$ openssl rsa -in client.key -pubout -out client.pem
****生成CA證書****:
$ openssl genrsa -out ca.key 2048
$ openssl req -new -key ca.key -out ca.csr
$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
生成客戶端服務(wù)端證書:
服務(wù)端:
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
客戶端:
$ openssl req -new -key client.key -out client.csr
向CA申請簽名:
$ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt
證書和私鑰生成完畢后滚朵,開始配置nginx(http部分從略)冤灾;
#HTTPS server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate ../ssl/certs/server.crt; #放置服務(wù)器證書的目錄
ssl_certificate_key ../ssl/private/server.key; #放置服務(wù)器私鑰的目錄
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8887;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
配置完后,保存辕近,在nginx根目錄下運(yùn)行命令:
$ ./sbin/nginx -t -c conf/https_server.conf
nginx會(huì)測試一下配置文件 conf/https_server.conf
如果輸出下面的東西韵吨,表示配置沒什么格式問題了:
啟動(dòng)nginx:
$ ./sbin/nginx -c conf/https_server.conf
這里我們搭建一個(gè)http服務(wù)器,在端口8887上監(jiān)聽移宅,使用nginx代理归粉,在瀏覽器中訪問:
https://localhost/hello
返回:
{
"user_id":1, "name":"Tom"
}
2.3 信任證書:
瀏覽器中輸入
https://localhost:443
因?yàn)槲覀兊母C書是自己簽發(fā)的椿疗,簽發(fā)機(jī)構(gòu)是偽造的,不在瀏覽器的信任列表中糠悼。對(duì)于這種情況届榄,不同的瀏覽器對(duì)此會(huì)有不同的表現(xiàn),但主流的瀏覽器都會(huì)發(fā)出警告倔喂。下面提供了一種辦法铝条,使瀏覽器信任證書。注意滴劲,這里只是為了測試攻晒,正常上網(wǎng)不要忽略瀏覽器的警告,輕易地信任不明來源的證書班挖。
下面是在Mac下的Google Chrome中信任證書的操作步驟:
. 當(dāng)瀏覽器提示連接不安全時(shí)鲁捏,在瀏覽器的抓包工具中點(diǎn)到如下的界面:
. 點(diǎn)按鈕:View Certificate
. 拖動(dòng)證書的icon,拉到本地桌面上并雙擊它:
雙擊它打開系統(tǒng)的鑰匙串给梅,將桌面證書拖拽到系統(tǒng)鑰匙串中,
雙擊打開双揪,選擇『始終信任』
注:截圖的證書為測試時(shí)隨意生成的根證書动羽;所有證書信任的辦法類似。
重啟瀏覽器后渔期,再訪問https://localhost/hello 运吓,會(huì)看到這樣的結(jié)果:
2.4 測試加密效果
現(xiàn)在,我們嘗試用抓包工具模擬中間人截取報(bào)文疯趟,看看能不能截取到報(bào)文:
在mac上我們使用charles進(jìn)行抓包拘哨,結(jié)果如下,報(bào)文已經(jīng)被加密信峻,看到的內(nèi)容都是亂碼:
嘗試用Charles進(jìn)行一次中間人攻擊:偽造證書倦青,在Charles上可以安全一個(gè)代理證書,具體操作參考這里:http://www.reibang.com/p/7a88617ce80b
盹舞,然后再訪問https://localhost/hello
這時(shí)瀏覽器會(huì)又提示我們連接不安全产镐,這是因?yàn)門LS握手感知到了客戶端的證書來源不明,假如我們點(diǎn)擊高級(jí)踢步,繼續(xù)訪問癣亚,忽略這個(gè)警告,那么我們會(huì)在抓包工具上看到這樣的畫面:
報(bào)文的內(nèi)容成功被Charles竊聽了获印,所以逃糟,再次驗(yàn)證了一點(diǎn):如果正常上網(wǎng)瀏覽網(wǎng)頁,操作電子銀行等敏感信息時(shí)蓬豁,不要隨便忽略瀏覽器的安全警告绰咽。
由于大多數(shù)人安全意識(shí)薄弱,很習(xí)慣地點(diǎn)繼續(xù)訪問不安全連接 地粪,所以就有了HSTS取募。
2.5 HSTS是什么
**** HSTS(HTTP Strict Transport Security)****,這是一個(gè)由IEEE發(fā)布的網(wǎng)絡(luò)安全策略機(jī)制蟆技,如果服務(wù)器增加了這種策略玩敏,那么就意味著要求客戶端必須使用https協(xié)議和服務(wù)器進(jìn)行對(duì)話。
主流的瀏覽器都實(shí)現(xiàn)了HSTS策略质礼。當(dāng)TLS握手出現(xiàn)問題時(shí)旺聚,瀏覽器不會(huì)再訪問服務(wù)器。
百度的防火墻代理就實(shí)現(xiàn)了這個(gè)策略眶蕉。訪問https://www.baidu.com 砰粹,在瀏覽器截取到的服務(wù)器響應(yīng)頭中有一個(gè)Strict-Transport-Security字段 max-age=172800 。max-age是指HSTS的失效時(shí)間造挽,單位是秒碱璃。
由于服務(wù)器響應(yīng)頭增加了這個(gè)字段,瀏覽器就會(huì)履行一些HSTS的職責(zé)饭入。假如我們采取抓包工具偽造一個(gè)未知證書嵌器,再去訪問域名,就會(huì)受到警告谐丢,嘗試讓瀏覽器忽略不安全的警告繼續(xù)訪問會(huì)被禁止爽航,如下圖:
然而HSTS也不是絕對(duì)安全的。一方面原因在于Strict-Transport-Security的max-age會(huì)過期乾忱,瀏覽器是否強(qiáng)制HSTS策略取決于當(dāng)前系統(tǒng)時(shí)間讥珍,它可能偽造;另一方面是因?yàn)槭状卧L問網(wǎng)址并不受HSTS保護(hù)饭耳〈觯可見技術(shù)對(duì)安全的防護(hù)永遠(yuǎn)是有限的,還需要用戶有足夠的安全意識(shí)進(jìn)行自我保護(hù)寞肖。
3 實(shí)現(xiàn)https抓包
了解了https的原理之后纲酗,知道TLS的握手關(guān)鍵在身份認(rèn)證這一步。HTTPS的數(shù)據(jù)傳輸可以類比成交談的雙方各自亮出身份證新蟆,然后用約定的暗號(hào)進(jìn)行交流觅赊,這樣即時(shí)旁邊有人竊聽,也無法破解經(jīng)過加密的信息琼稻。
測試時(shí)吮螺,通常會(huì)有抓取https包的需求。如果以為https已被加密,我們沒辦法抓到明文包鸠补,那這是不對(duì)的萝风。抓包的原理通常是在通信雙方插一個(gè)中間代理,對(duì)原有的客戶端和服務(wù)器的請求進(jìn)行來回轉(zhuǎn)發(fā)紫岩。如果要抓取https包规惰,顯然,構(gòu)造的代理必須有完成TLS握手的能力泉蝌,所以代理工具一般需要支持ssl歇万。有了TLS的握手能力,我們再設(shè)法使通信雙方相信代理的身份勋陪,就能實(shí)現(xiàn)https的抓包了叽讳∽偶ⅲ可以看到芦岂,https的數(shù)據(jù)安全關(guān)鍵點(diǎn)其實(shí)就是在數(shù)字證書上 拴测,因此也很容易理解為什么主流的瀏覽器都會(huì)警告用戶使用了來路不明的機(jī)構(gòu)頒發(fā)的證書。
實(shí)現(xiàn)https抓包呻粹,具體操作方案就是:用一個(gè)支持ssl的代理壕曼,偽造一個(gè)ca證書,當(dāng)通信雙方在TLS握手時(shí)發(fā)現(xiàn)有人竊聽時(shí)等浊,設(shè)法讓他們相信代理的身份(這個(gè)過程就見2.3); 代理身份被信任了腮郊,就會(huì)發(fā)生這個(gè)過程: 客戶端和代理進(jìn)行握手,請求數(shù)據(jù)發(fā)到代理上筹燕,由代理和服務(wù)器做TLS握手轧飞,并轉(zhuǎn)傳客戶端的請求數(shù)據(jù);服務(wù)器加密報(bào)文應(yīng)答撒踪,代理解密報(bào)文再用和客戶端協(xié)商的密碼方案加密報(bào)文过咬,傳給客戶端,客戶端解密報(bào)文制妄。
Charles抓包參看:http://www.reibang.com/p/7a88617ce80b
4 HTTPS的性能
4.1 HTTPS與HTTP的性能評(píng)測對(duì)比
我們使用Jmeter來測試http和https的比較掸绞。
在遠(yuǎn)程服務(wù)器上搭建一個(gè)http服務(wù)器,讓它返回一個(gè)簡單的靜態(tài)網(wǎng)頁:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
<title>首頁測試</title>
</head><body>
<p>這是一個(gè)測試網(wǎng)頁</p>
然后使用nginx進(jìn)行代理
第一次關(guān)閉nginx的ssl安全開關(guān)耕捞,讓服務(wù)器作為普通的http服務(wù)器衔掸,用jmeter發(fā)請求;第二次俺抽,開啟ssl策略敞映,強(qiáng)制進(jìn)行TLS握手,再用jmeter發(fā)請求磷斧。
兩次的數(shù)據(jù)比較如下:
請求方式 | 響應(yīng)時(shí)間(ms) |
---|---|
http | 164 |
https | 419 |
100個(gè)樣本的測試數(shù)據(jù):
http100個(gè)樣本的數(shù)據(jù):
https100個(gè)樣本的數(shù)據(jù):
注意:
. 使用jmeter發(fā)出100個(gè)樣本時(shí)振愿,需要把keep-alive選項(xiàng)勾掉捷犹,保證每次請求都進(jìn)行了TCP握手,而不是復(fù)用連接冕末;否則得到的性能數(shù)據(jù)會(huì)更好萍歉。
. 發(fā)出https請求時(shí),除了在服務(wù)端nginx上把ssl的開關(guān)打開栓霜,還要在jmeter的協(xié)議選項(xiàng)中填上https翠桦,如圖:
可以看到,使用了https胳蛮,如果每次連接都進(jìn)行完全握手,https的性能會(huì)比http多出250ms左右丛晌。也就是說仅炊,請求一個(gè)動(dòng)態(tài)網(wǎng)頁的響應(yīng)時(shí)間假如是200ms,那么https會(huì)使性能下降100%澎蛛。然而抚垄,如果使用keep-alive連接復(fù)用,性能的對(duì)比并沒有那么可怕:
使用keep-alive谋逻,100個(gè)https的請求的結(jié)果:
http:
除了第一個(gè)樣本的差距比較大呆馁,整個(gè)平均響應(yīng)時(shí)間看上去https反而要略優(yōu)于http。
下面嘗試使用tcpdump探查一下TLS握手各個(gè)階段的耗時(shí)分布
4.2 TLS握手的性能評(píng)測
4.2.1數(shù)據(jù)包截取
這里使用tcpdump來抓一段https請求的數(shù)據(jù)包(這里并沒有發(fā)生TLS完全握手毁兆,客戶端沒有給服務(wù)器傳證書):
輸入命令:
$ sudo tcpdump host $hostname
然后請求一下https的url浙滤,會(huì)截獲到如下的數(shù)據(jù):
Line 1 15:19:48.793920 IP client.https.host.63209 > server.httpshost: Flags [S], seq 2411985045, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 669725535 ecr 0,sackOK,eol], length 0
Line 2 15:19:48.875001 IP server.httpshost > client.https.host.63209: Flags [S.], seq 284701943, ack 2411985046, win 14480, options [mss 1460,sackOK,TS val 175414051 ecr 669725535,nop,wscale 8], length 0
Line 3 15:19:48.875074 IP client.https.host.63209 > server.httpshost: Flags [.], ack 1, win 4117, options [nop,nop,TS val 669725616 ecr 175414051], length 0
Line 4 15:19:48.876925 IP client.https.host.63209 > server.httpshost: Flags [P.], seq 1:201, ack 1, win 4117, options [nop,nop,TS val 669725617 ecr 175414051], length 200
Line 5 15:19:48.958843 IP server.httpshost > client.https.host.63209: Flags [.], ack 201, win 61, options [nop,nop,TS val 175414134 ecr 669725617], length 0
Line 6 15:19:48.961690 IP server.httpshost > client.https.host.63209: Flags [.], seq 1:1449, ack 201, win 61, options [nop,nop,TS val 175414135 ecr 669725617], length 1448
Line 7 15:19:48.961696 IP server.httpshost > client.https.host.63209: Flags [.], seq 1449:2897, ack 201, win 61, options [nop,nop,TS val 175414135 ecr 669725617], length 1448
Line 8 15:19:48.961736 IP client.https.host.63209 > server.httpshost: Flags [.], ack 2897, win 4027, options [nop,nop,TS val 669725700 ecr 175414135], length 0
Line 9 15:19:48.961914 IP server.httpshost > client.https.host.63209: Flags [P.], seq 2897:3255, ack 201, win 61, options [nop,nop,TS val 175414135 ecr 669725617], length 358
Line 10 15:19:48.961933 IP client.https.host.63209 > server.httpshost: Flags [.], ack 3255, win 4016, options [nop,nop,TS val 669725700 ecr 175414135], length 0
Line 11 15:19:48.964670 IP client.https.host.63209 > server.httpshost: Flags [P.], seq 201:276, ack 3255, win 4096, options [nop,nop,TS val 669725702 ecr 175414135], length 75
Line 12 15:19:49.045770 IP server.httpshost > client.https.host.63209: Flags [.], ack 276, win 61, options [nop,nop,TS val 175414221 ecr 669725702], length 0
Line 13 15:19:49.045812 IP client.https.host.63209 > server.httpshost: Flags [P.], seq 276:327, ack 3255, win 4096, options [nop,nop,TS val 669725783 ecr 175414221], length 51
Line 14 15:19:49.126510 IP server.httpshost > client.https.host.63209: Flags [.], ack 327, win 61, options [nop,nop,TS val 175414302 ecr 669725783], length 0
Line 15 15:19:49.126517 IP server.httpshost > client.https.host.63209: Flags [P.], seq 3255:3306, ack 327, win 61, options [nop,nop,TS val 175414302 ecr 669725783], length 51
Line 16 15:19:49.126575 IP client.https.host.63209 > server.httpshost: Flags [.], ack 3306, win 4094, options [nop,nop,TS val 669725862 ecr 175414302], length 0
Line 17 15:19:49.127304 IP client.https.host.63209 > server.httpshost: Flags [P.], seq 327:471, ack 3306, win 4096, options [nop,nop,TS val 669725862 ecr 175414302], length 144
Line 18 15:19:49.208120 IP server.httpshost > client.https.host.63209: Flags [.], ack 471, win 65, options [nop,nop,TS val 175414384 ecr 669725862], length 0
Line 19 15:19:49.209352 IP server.httpshost > client.https.host.63209: Flags [P.], seq 3306:3671, ack 471, win 65, options [nop,nop,TS val 175414385 ecr 669725862], length 365
Line 20 15:19:49.209394 IP client.https.host.63209 > server.httpshost: Flags [.], ack 3671, win 4084, options [nop,nop,TS val 669725943 ecr 175414385], length 0
Line 21 15:19:49.210228 IP client.https.host.63209 > server.httpshost: Flags [P.], seq 471:502, ack 3671, win 4096, options [nop,nop,TS val 669725943 ecr 175414385], length 31
Line 22 15:19:49.210263 IP client.https.host.63209 > server.httpshost: Flags [F.], seq 502, ack 3671, win 4096, options [nop,nop,TS val 669725943 ecr 175414385], length 0
Line 23 15:19:49.292232 IP server.httpshost > client.https.host.63209: Flags [.], ack 502, win 65, options [nop,nop,TS val 175414467 ecr 669725943], length 0
Line 24 15:19:49.292239 IP server.httpshost > client.https.host.63209: Flags [F.], seq 3671, ack 502, win 65, options [nop,nop,TS val 175414467 ecr 669725943], length 0
Line 25 15:19:49.292240 IP server.httpshost > client.https.host.63209: Flags [.], ack 503, win 65, options [nop,nop,TS val 175414467 ecr 669725943], length 0
Line 26 15:19:49.292286 IP client.https.host.63209 > server.httpshost: Flags [F.], seq 502, ack 3672, win 4096, options [nop,nop,TS val 669726025 ecr 175414467], length 0
4.2.2抓包數(shù)據(jù)解析
- Line1-Line3 是TCP的3路握手,這里耗時(shí)從15:19:48.793920到15:19:48.875074 這一次RTT花費(fèi)了81.154ms
- Line4-Line5 判斷是客戶端發(fā)ClientHello消息气堕,這里客戶端發(fā)出了200字節(jié)纺腊,TLS握手的開始
*Line7 Line8 Line9 從TCP選項(xiàng)可以看出來,是數(shù)據(jù)分了三組傳送茎芭,總字節(jié)是1448 * 2 + 358 = 3254個(gè)字節(jié)揖膜,由TLS協(xié)議可以判斷這是服務(wù)器在回應(yīng)ServerHello以及傳遞服務(wù)器證書;這個(gè)過程耗時(shí)是89.968 ms;與一次TCP握手耗時(shí)相近- Line10到Line16 是客戶端和服務(wù)器協(xié)商密鑰的過程梅桩。這期間壹粟,客戶端發(fā)送了兩次數(shù)據(jù),服務(wù)器發(fā)了一次宿百;服務(wù)器進(jìn)行了兩次非對(duì)稱解密運(yùn)算趁仙,一次數(shù)字簽名校驗(yàn),一次解密拿到隨機(jī)預(yù)主密鑰犀呼,總共耗時(shí)161.905ms幸撕,到Line16 TLS 握手完成
- Line17行~Line22開始進(jìn)行應(yīng)用數(shù)據(jù)傳輸,傳輸時(shí)使用預(yù)主密鑰計(jì)算出來的主密鑰對(duì)應(yīng)用層數(shù)據(jù)進(jìn)行加密外臂,總共耗時(shí)82.959ms
- 最后4行是TCP的關(guān)閉過程坐儿,可以暫不考慮。
4.2.3 TLS性能結(jié)果匯總
從4.2.2 的分析可以看到整個(gè)過程400多ms的時(shí)間分配如下:
過程 | 耗時(shí)/ms | 耗時(shí)占比% |
---|---|---|
tcp握手 | 81.154ms | 19.49 |
傳遞證書和ClientHello,ServerHello | 89.968ms | 21.61 |
協(xié)商主密鑰和簽名校驗(yàn)(2次公鑰加密/解密運(yùn)算) | 161.905ms | 38.89 |
應(yīng)用層數(shù)據(jù)傳輸 | 82.959ms | 19.93 |
其他 | 0.357ms | 0.08 |
總耗時(shí)(Line22時(shí)間減去Line1) | 416.343ms | 19.49 |
進(jìn)行過充分優(yōu)化的https連接主要的耗時(shí)基本上集中在應(yīng)用層數(shù)據(jù)傳輸上,這跟我們使用Jmeter評(píng)測keep-alive狀態(tài)得到的數(shù)據(jù)相吻合貌矿。
從表中可見炭菌,HTTPS完全握手下性能消耗大多集中在TLS握手期間,約占60%逛漫。TLS握手中服務(wù)器進(jìn)行RSA解密不僅會(huì)有時(shí)間消耗黑低,還會(huì)對(duì)服務(wù)器形成CPU壓力。
通過這個(gè)分析酌毡,可以看出HTTPS的性能優(yōu)化策略應(yīng)該會(huì)從嘗試考慮減少TLS握手頻率克握,復(fù)用TLS會(huì)話,在分布式服務(wù)中用緩存共享會(huì)話枷踏,或?qū)⒔饷苓\(yùn)算轉(zhuǎn)到云端菩暗,提升服務(wù)器的硬件級(jí)別等方面入手。
附1:密碼學(xué)相關(guān)概念:
主密鑰(master secret):一個(gè)48位的共享密鑰旭蠕,客戶端和服務(wù)器都會(huì)知道停团。
MAC算法: 消息認(rèn)證碼算法。
對(duì)稱密鑰加密:加密和解密編碼使用的密鑰相同掏熬。對(duì)稱加密的缺點(diǎn)之一是任何兩臺(tái)主機(jī)進(jìn)行通信都需要維護(hù)一個(gè)雙方都知道的密鑰佑稠,造成管理負(fù)擔(dān),一個(gè)有N個(gè)站點(diǎn)的網(wǎng)絡(luò)旗芬,可能需要維護(hù) N(N-1)個(gè)密鑰舌胶。
流加密:是一種對(duì)稱加密算法,加密和解密雙方使用相同偽隨機(jī)加密數(shù)據(jù)流(pseudo-random stream)作為密鑰岗屏,明文數(shù)據(jù)每次與密鑰數(shù)據(jù)流順次對(duì)應(yīng)加密辆琅,得到密文數(shù)據(jù)流。
分組加密:又稱分塊加密或塊密碼这刷,是一種對(duì)稱密鑰算法婉烟。它將明文分成多個(gè)等長的模塊(block),使用確定的算法和對(duì)稱密鑰對(duì)每組分別加密解密暇屋。如AES似袁,DES
公鑰加密:非對(duì)稱加密。加密和解密使用不同的密鑰咐刨,加密密鑰是公開的昙衅,解密密鑰一般被服務(wù)器保存,不對(duì)外公布定鸟。
數(shù)字簽名:附在報(bào)文中的特殊加密校驗(yàn)碼而涉,用來證明報(bào)文作者的身份。
數(shù)字證書:類似與身份ID联予,常用的數(shù)字證書格式是X.509 v3啼县,證書中包含基本的字段信息:序列號(hào)材原,簽名算法ID,證書頒發(fā)機(jī)構(gòu)季眷,有效期余蟹,對(duì)象名稱,對(duì)象公開密鑰信息子刮,發(fā)布者的唯一ID威酒,對(duì)象的唯一ID,擴(kuò)展挺峡。
PKI: Public Key Infrastructure 公鑰基礎(chǔ)設(shè)施葵孤,是一組由硬件、軟件沙郭、參與者佛呻、管理政策與流程組成的基礎(chǔ)架構(gòu),其目的在于創(chuàng)造病线、管理、分配鲤嫡、使用送挑、存儲(chǔ)以及撤銷數(shù)字證書。
附2:參考資料
說明: 本文關(guān)于TLS協(xié)議的描述本于RFC5246暖眼,Nginx搭建https本于nginx的官網(wǎng)文檔
- RFC5246參考網(wǎng)址: https://tools.ietf.org/html/rfc5246
- Nginx安裝參考網(wǎng)址:http://nginx.org/en/docs/install.html
- Nginx搭建https參考網(wǎng)址: http://nginx.org/en/docs/http/configuring_https_servers.html
- 信任證書方案本文只是在MAC系統(tǒng)上進(jìn)行了操作實(shí)踐惕耕,其他操作系統(tǒng)可參考 : http://blog.getpostman.com/2014/01/28/using-self-signed-certificates-with-postman/
附3:使用charles進(jìn)行https抓包
也是我寫的一篇文章:http://www.reibang.com/p/7a88617ce80b