摘要
本文主要是在測試https服務(wù)時對搭建https服務(wù)器的一些實踐總結(jié)。TLS協(xié)議的介紹部分來源于對RFC5246的理解,不當(dāng)之處,還請指出。后面包含一段對https的性能分析的工程實踐。
1 TLS協(xié)議簡介
1.1 簡介
TSL是傳輸層安全協(xié)議(Transport Secure Protocol)的簡稱,它的前身是SSL(Secure Sockets Layer)。TLS的設(shè)計目標(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é)議是獨立于應(yīng)用層協(xié)議的,也就是說高層的應(yīng)用層協(xié)議,如HTTP,F(xiàn)TP等都可以創(chuàng)建在TLS之上,TLS的下層可以是任何可靠傳輸層協(xié)議,如TCP,SPX等。
1.2 TLS的版本演進(jìn)
發(fā)布時間 | 版本 | 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ù)校驗,重新 組裝后傳到上一層。
握手層協(xié)議(TLS Handshake Protocol):
握手層協(xié)議處于記錄層協(xié)議之上,握手層協(xié)議的作用是在真正的應(yīng)用數(shù)據(jù)傳輸之前,使客戶端和服務(wù)器互相進(jìn)行身份認(rèn)證,協(xié)商加密算法以及生成加密密鑰。握手層用于協(xié)商出記錄層的參數(shù)。這些參數(shù)將會被記錄層用于雙方的身份認(rèn)證,實例化協(xié)商的安全參數(shù),錯誤報告。
TLS在協(xié)議棧中的位置:
TLS的握手過程:
- 客戶端發(fā)送ClientHello消息,包含可選密碼組件,一個客戶端生成的隨機(jī)數(shù)等,服務(wù)端接收后回一個ServerHello消息給客戶端,確定密碼方案,并生成一個服務(wù)器隨機(jī)數(shù),發(fā)給客戶端。
這一步的數(shù)據(jù)傳輸在TCP上進(jìn)行,數(shù)據(jù)都是公開的,中間人攻擊者可以很輕松的得到這些數(shù)據(jù)。- 服務(wù)器發(fā)送證書,服務(wù)器的身份確認(rèn)成功后;服務(wù)器可能會請求一個客戶端證書,要求客戶端進(jìn)行身份認(rèn)證,客戶端給服務(wù)器發(fā)出證書,驗明身份。這一步不是必須的。
- 客戶端向服務(wù)器發(fā)出摘要認(rèn)證,確認(rèn)接收的消息的完整性,保證沒有被第三方篡改。
- 雙方交換必需的加密參數(shù)。其中包括一個預(yù)主密鑰,客戶端會用服務(wù)器證書中的公鑰將這個密鑰加密傳給服務(wù)器,服務(wù)器使用私鑰進(jìn)行解密。
- 客戶端生成一個預(yù)主密鑰,并使用服務(wù)器證書中的公鑰加密,服務(wù)器解密后生成一個主密鑰。雙方使用這個主密鑰(master secret)對應(yīng)用層數(shù)據(jù)進(jìn)行對稱加密(如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:
會話恢復(fù)過程:
客戶端服務(wù)器出于性能的考慮,可能會恢復(fù)前面的會話,或復(fù)制一個當(dāng)前存在的會話,而不是重新協(xié)商密碼參數(shù),建立新的會話(4.2部分使用tcpdump跟蹤發(fā)現(xiàn),這個過程確實是耗時占比很大)。
- 客戶端發(fā)出一個ClientHello消息,這個消息包含要恢復(fù)的會話的Session ID。
- 服務(wù)接到這個SessionID后,檢查它的緩存是否存在該會話ID。如果找到了,服務(wù)器將使用該會話狀態(tài)重建連接,并發(fā)一個ServerHello給客戶端,其中包含一個和ClientHello消息一模一樣的SessionID。
- 此時,協(xié)議規(guī)定,必須要雙方發(fā)出ChangeCipherSpec消息,并接著發(fā)出Finished消息確認(rèn)握手完成。然后客戶端服務(wù)器就可以傳輸應(yīng)用層數(shù)據(jù)了。
- 如果服務(wù)器沒有在緩存中找到Session ID,那么新的SessionID將會建立,然后又會執(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ù)--with-http_ssl_module,最新的nginx版本是默認(rèn)有這個編譯參數(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ù)器的客戶端都能拿到這個證書;
*** ssl_certificate_key*** : 是私鑰,只能被服務(wù)器知道。
ssl_protocols, ssl_ciphers選項是可選的。
2.2 詳細(xì)操作步驟
下面嘗試在本地搭建一個簡單的https服務(wù)器,在443端口監(jiān)聽。
步驟如下:
- 搭建一個nginx服務(wù)器;
- 使用openssl生成服務(wù)器私鑰,客戶端私鑰,服務(wù)器公鑰,客戶端公鑰;
- 生成CA根證書,為服務(wù)器證書和客戶端證書(可選)提供簽名服務(wù);
- 生成服務(wù)器證書和客戶端證書,并請求CA的簽名;
- 在操作系統(tǒng)上信任我們偽造的服務(wù)器證書,這里沒有為客戶端生成證書;
- 隨便寫一個web服務(wù),提供一個url返回一段靜態(tài)報文,讓nginx為它做一下代理,然后啟動這個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會測試一下配置文件 conf/https_server.conf
如果輸出下面的東西,表示配置沒什么格式問題了:
啟動nginx:
$ ./sbin/nginx -c conf/https_server.conf
這里我們搭建一個http服務(wù)器,在端口8887上監(jiān)聽,使用nginx代理,在瀏覽器中訪問:
https://localhost/hello
返回:
{
"user_id":1, "name":"Tom"
}
2.3 信任證書:
瀏覽器中輸入
https://localhost:443
因為我們的根證書是自己簽發(fā)的,簽發(fā)機(jī)構(gòu)是偽造的,不在瀏覽器的信任列表中。對于這種情況,不同的瀏覽器對此會有不同的表現(xiàn),但主流的瀏覽器都會發(fā)出警告。下面提供了一種辦法,使瀏覽器信任證書。注意,這里只是為了測試,正常上網(wǎng)不要忽略瀏覽器的警告,輕易地信任不明來源的證書。
下面是在Mac下的Google Chrome中信任證書的操作步驟:
. 當(dāng)瀏覽器提示連接不安全時,在瀏覽器的抓包工具中點到如下的界面:
. 點按鈕:View Certificate
. 拖動證書的icon,拉到本地桌面上并雙擊它:
雙擊它打開系統(tǒng)的鑰匙串,將桌面證書拖拽到系統(tǒng)鑰匙串中,
雙擊打開,選擇『始終信任』
注:截圖的證書為測試時隨意生成的根證書;所有證書信任的辦法類似。
重啟瀏覽器后,再訪問https://localhost/hello ,會看到這樣的結(jié)果:
2.4 測試加密效果
現(xiàn)在,我們嘗試用抓包工具模擬中間人截取報文,看看能不能截取到報文:
在mac上我們使用charles進(jìn)行抓包,結(jié)果如下,報文已經(jīng)被加密,看到的內(nèi)容都是亂碼:
嘗試用Charles進(jìn)行一次中間人攻擊:偽造證書,在Charles上可以安全一個代理證書,具體操作參考這里:http://www.lxweimin.com/p/7a88617ce80b
,然后再訪問https://localhost/hello
這時瀏覽器會又提示我們連接不安全,這是因為TLS握手感知到了客戶端的證書來源不明,假如我們點擊高級,繼續(xù)訪問,忽略這個警告,那么我們會在抓包工具上看到這樣的畫面:
報文的內(nèi)容成功被Charles竊聽了,所以,再次驗證了一點:如果正常上網(wǎng)瀏覽網(wǎng)頁,操作電子銀行等敏感信息時,不要隨便忽略瀏覽器的安全警告。
由于大多數(shù)人安全意識薄弱,很習(xí)慣地點繼續(xù)訪問不安全連接 ,所以就有了HSTS。
2.5 HSTS是什么
**** HSTS(HTTP Strict Transport Security)****,這是一個由IEEE發(fā)布的網(wǎng)絡(luò)安全策略機(jī)制,如果服務(wù)器增加了這種策略,那么就意味著要求客戶端必須使用https協(xié)議和服務(wù)器進(jìn)行對話。
主流的瀏覽器都實現(xiàn)了HSTS策略。當(dāng)TLS握手出現(xiàn)問題時,瀏覽器不會再訪問服務(wù)器。
百度的防火墻代理就實現(xiàn)了這個策略。訪問https://www.baidu.com ,在瀏覽器截取到的服務(wù)器響應(yīng)頭中有一個Strict-Transport-Security字段 max-age=172800 。max-age是指HSTS的失效時間,單位是秒。
由于服務(wù)器響應(yīng)頭增加了這個字段,瀏覽器就會履行一些HSTS的職責(zé)。假如我們采取抓包工具偽造一個未知證書,再去訪問域名,就會受到警告,嘗試讓瀏覽器忽略不安全的警告繼續(xù)訪問會被禁止,如下圖:
然而HSTS也不是絕對安全的。一方面原因在于Strict-Transport-Security的max-age會過期,瀏覽器是否強(qiáng)制HSTS策略取決于當(dāng)前系統(tǒng)時間,它可能偽造;另一方面是因為首次訪問網(wǎng)址并不受HSTS保護(hù)。可見技術(shù)對安全的防護(hù)永遠(yuǎn)是有限的,還需要用戶有足夠的安全意識進(jìn)行自我保護(hù)。
3 實現(xiàn)https抓包
了解了https的原理之后,知道TLS的握手關(guān)鍵在身份認(rèn)證這一步。HTTPS的數(shù)據(jù)傳輸可以類比成交談的雙方各自亮出身份證,然后用約定的暗號進(jìn)行交流,這樣即時旁邊有人竊聽,也無法破解經(jīng)過加密的信息。
測試時,通常會有抓取https包的需求。如果以為https已被加密,我們沒辦法抓到明文包,那這是不對的。抓包的原理通常是在通信雙方插一個中間代理,對原有的客戶端和服務(wù)器的請求進(jìn)行來回轉(zhuǎn)發(fā)。如果要抓取https包,顯然,構(gòu)造的代理必須有完成TLS握手的能力,所以代理工具一般需要支持ssl。有了TLS的握手能力,我們再設(shè)法使通信雙方相信代理的身份,就能實現(xiàn)https的抓包了。可以看到,https的數(shù)據(jù)安全關(guān)鍵點其實就是在數(shù)字證書上 ,因此也很容易理解為什么主流的瀏覽器都會警告用戶使用了來路不明的機(jī)構(gòu)頒發(fā)的證書。
實現(xiàn)https抓包,具體操作方案就是:用一個支持ssl的代理,偽造一個ca證書,當(dāng)通信雙方在TLS握手時發(fā)現(xiàn)有人竊聽時,設(shè)法讓他們相信代理的身份(這個過程就見2.3); 代理身份被信任了,就會發(fā)生這個過程: 客戶端和代理進(jìn)行握手,請求數(shù)據(jù)發(fā)到代理上,由代理和服務(wù)器做TLS握手,并轉(zhuǎn)傳客戶端的請求數(shù)據(jù);服務(wù)器加密報文應(yīng)答,代理解密報文再用和客戶端協(xié)商的密碼方案加密報文,傳給客戶端,客戶端解密報文。
Charles抓包參看:http://www.lxweimin.com/p/7a88617ce80b
4 HTTPS的性能
4.1 HTTPS與HTTP的性能評測對比
我們使用Jmeter來測試http和https的比較。
在遠(yuǎn)程服務(wù)器上搭建一個http服務(wù)器,讓它返回一個簡單的靜態(tài)網(wǎng)頁:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
<title>首頁測試</title>
</head><body>
<p>這是一個測試網(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)時間(ms) |
---|---|
http | 164 |
https | 419 |
100個樣本的測試數(shù)據(jù):
http100個樣本的數(shù)據(jù):
https100個樣本的數(shù)據(jù):
注意:
. 使用jmeter發(fā)出100個樣本時,需要把keep-alive選項勾掉,保證每次請求都進(jìn)行了TCP握手,而不是復(fù)用連接;否則得到的性能數(shù)據(jù)會更好。
. 發(fā)出https請求時,除了在服務(wù)端nginx上把ssl的開關(guān)打開,還要在jmeter的協(xié)議選項中填上https,如圖:
圖15
可以看到,使用了https,如果每次連接都進(jìn)行完全握手,https的性能會比http多出250ms左右。也就是說,請求一個動態(tài)網(wǎng)頁的響應(yīng)時間假如是200ms,那么https會使性能下降100%。然而,如果使用keep-alive連接復(fù)用,性能的對比并沒有那么可怕:
使用keep-alive,100個https的請求的結(jié)果:
http:
除了第一個樣本的差距比較大,整個平均響應(yīng)時間看上去https反而要略優(yōu)于http。
下面嘗試使用tcpdump探查一下TLS握手各個階段的耗時分布
4.2 TLS握手的性能評測
4.2.1數(shù)據(jù)包截取
這里使用tcpdump來抓一段https請求的數(shù)據(jù)包(這里并沒有發(fā)生TLS完全握手,客戶端沒有給服務(wù)器傳證書):
輸入命令:
$ sudo tcpdump host $hostname
然后請求一下https的url,會截獲到如下的數(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路握手,這里耗時從15:19:48.793920到15:19:48.875074 這一次RTT花費了81.154ms
- Line4-Line5 判斷是客戶端發(fā)ClientHello消息,這里客戶端發(fā)出了200字節(jié),TLS握手的開始
*Line7 Line8 Line9 從TCP選項可以看出來,是數(shù)據(jù)分了三組傳送,總字節(jié)是1448 * 2 + 358 = 3254個字節(jié),由TLS協(xié)議可以判斷這是服務(wù)器在回應(yīng)ServerHello以及傳遞服務(wù)器證書;這個過程耗時是89.968 ms;與一次TCP握手耗時相近- Line10到Line16 是客戶端和服務(wù)器協(xié)商密鑰的過程。這期間,客戶端發(fā)送了兩次數(shù)據(jù),服務(wù)器發(fā)了一次;服務(wù)器進(jìn)行了兩次非對稱解密運(yùn)算,一次數(shù)字簽名校驗,一次解密拿到隨機(jī)預(yù)主密鑰,總共耗時161.905ms,到Line16 TLS 握手完成
- Line17行~Line22開始進(jìn)行應(yīng)用數(shù)據(jù)傳輸,傳輸時使用預(yù)主密鑰計算出來的主密鑰對應(yīng)用層數(shù)據(jù)進(jìn)行加密,總共耗時82.959ms
- 最后4行是TCP的關(guān)閉過程,可以暫不考慮。
4.2.3 TLS性能結(jié)果匯總
從4.2.2 的分析可以看到整個過程400多ms的時間分配如下:
過程 | 耗時/ms | 耗時占比% |
---|---|---|
tcp握手 | 81.154ms | 19.49 |
傳遞證書和ClientHello,ServerHello | 89.968ms | 21.61 |
協(xié)商主密鑰和簽名校驗(2次公鑰加密/解密運(yùn)算) | 161.905ms | 38.89 |
應(yīng)用層數(shù)據(jù)傳輸 | 82.959ms | 19.93 |
其他 | 0.357ms | 0.08 |
總耗時(Line22時間減去Line1) | 416.343ms | 19.49 |
進(jìn)行過充分優(yōu)化的https連接主要的耗時基本上集中在應(yīng)用層數(shù)據(jù)傳輸上,這跟我們使用Jmeter評測keep-alive狀態(tài)得到的數(shù)據(jù)相吻合。
從表中可見,HTTPS完全握手下性能消耗大多集中在TLS握手期間,約占60%。TLS握手中服務(wù)器進(jìn)行RSA解密不僅會有時間消耗,還會對服務(wù)器形成CPU壓力。
通過這個分析,可以看出HTTPS的性能優(yōu)化策略應(yīng)該會從嘗試考慮減少TLS握手頻率,復(fù)用TLS會話,在分布式服務(wù)中用緩存共享會話,或?qū)⒔饷苓\(yùn)算轉(zhuǎn)到云端,提升服務(wù)器的硬件級別等方面入手。
附1:密碼學(xué)相關(guān)概念:
主密鑰(master secret):一個48位的共享密鑰,客戶端和服務(wù)器都會知道。
MAC算法: 消息認(rèn)證碼算法。
對稱密鑰加密:加密和解密編碼使用的密鑰相同。對稱加密的缺點之一是任何兩臺主機(jī)進(jìn)行通信都需要維護(hù)一個雙方都知道的密鑰,造成管理負(fù)擔(dān),一個有N個站點的網(wǎng)絡(luò),可能需要維護(hù) N(N-1)個密鑰。
流加密:是一種對稱加密算法,加密和解密雙方使用相同偽隨機(jī)加密數(shù)據(jù)流(pseudo-random stream)作為密鑰,明文數(shù)據(jù)每次與密鑰數(shù)據(jù)流順次對應(yīng)加密,得到密文數(shù)據(jù)流。
分組加密:又稱分塊加密或塊密碼,是一種對稱密鑰算法。它將明文分成多個等長的模塊(block),使用確定的算法和對稱密鑰對每組分別加密解密。如AES,DES
公鑰加密:非對稱加密。加密和解密使用不同的密鑰,加密密鑰是公開的,解密密鑰一般被服務(wù)器保存,不對外公布。
數(shù)字簽名:附在報文中的特殊加密校驗碼,用來證明報文作者的身份。
數(shù)字證書:類似與身份ID,常用的數(shù)字證書格式是X.509 v3,證書中包含基本的字段信息:序列號,簽名算法ID,證書頒發(fā)機(jī)構(gòu),有效期,對象名稱,對象公開密鑰信息,發(fā)布者的唯一ID,對象的唯一ID,擴(kuò)展。
PKI: Public Key Infrastructure 公鑰基礎(chǔ)設(shè)施,是一組由硬件、軟件、參與者、管理政策與流程組成的基礎(chǔ)架構(gòu),其目的在于創(chuàng)造、管理、分配、使用、存儲以及撤銷數(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)行了操作實踐,其他操作系統(tǒng)可參考 : http://blog.getpostman.com/2014/01/28/using-self-signed-certificates-with-postman/
附3:使用charles進(jìn)行https抓包
也是我寫的一篇文章:http://www.lxweimin.com/p/7a88617ce80b