如何用雙向HTTPS進行“偷懶”

寫在前面

近期某項目有一個業(yè)務拓展的需求斤程,需要將項目中單機房部署的模塊擴展成異地多機房部署粪糙。原先項目的模塊都部署在自建的機房A肠缔,有防火墻等相關安全策略的保護,相對比較安全宣吱,但現(xiàn)在網(wǎng)絡跨越了兩個公網(wǎng)通信的機房窃这,該如何保證傳輸安全和訪問控制呢?

HTTPS可以對服務器進行身份認證征候,同時也可以保證數(shù)據(jù)流量傳輸?shù)陌踩脊ィ苊庵虚g人攻擊,但這并不能滿足我們訪問權限控制的要求(我們的服務并不希望任何人都能訪問)疤坝。

解決以上問題有兩種思路兆解,一種是在應用層對模塊進行改造,使其支持訪問權限控制跑揉;另外一種則是雙向HTTPS锅睛,基于雙向HTTPS的特性來實現(xiàn)。出于是否能快速實現(xiàn)與成本考慮历谍,我們最終選擇了雙向HTTPS來實現(xiàn)這一需求现拒。

下面我們對如何實現(xiàn)這個需求與雙向HTTPS的原理做一個簡要介紹,希望給遇到類似問題的開發(fā)者提供一個思路供參考望侈。

HTTPS & 雙向HTTPS

HTTPS

HTTPS 全稱為 HyperText Transfer Protocol Secure印蔬,在HTTP的基礎上,集成了TLS/SSL傳輸層協(xié)議脱衙,以提供對網(wǎng)站服務器的身份認證扛点,保護交換數(shù)據(jù)的隱私與完整性。

雙向HTTPS

雙向HTTPS在單向HTTPS認證的基礎上岂丘,增加了服務端對客戶端身份認證的步驟,在進行通信前互相驗證對方身份眠饮,增加了網(wǎng)絡的安全性奥帘。

方案思考

網(wǎng)絡環(huán)境介紹

服務端與客戶端原先在同一機房內(nèi),只使用了HTTP協(xié)議來做數(shù)據(jù)傳輸仪召。

我們的目標方案則是保證跨域公網(wǎng)的兩個模塊能夠互相通信寨蹋,并在此基礎上確保輸過程的安全性與權限控制。

2.? 在1 的基礎上為客戶端增加Nginx做正向代理扔茅,將單向HTTPS升級為雙向HTTPS雙向HTTPS在單向HTTPS的基礎上已旧,多了服務端校驗客戶端證書的步驟。若服務端校驗客戶端證書失敗召娜,則在HTTPS握手階段服務端就將其拒絕运褪。這樣,就一定程度上實現(xiàn)了服務端的訪問權限控制。

涉及新增修改的內(nèi)容

1.? 新增代理層代理層包括客戶端和服務端的兩個代理服務器秸讹,此處選用Nginx

2.? 新增一個CA中心新增的CA中心主要用于為客戶端頒發(fā)證書( 服務端的HTTPS證書將選用商用CA證書)

配置雙向HTTPS的整體投入的整體投入和為模塊開發(fā)權限功能比起來檀咙,此方案的實現(xiàn)相對來說更簡單也更快捷。

環(huán)境搭建驗證

此處將使用openssl 與docker璃诀,在本地搭建一套方案中的模擬環(huán)境來驗證方案的可行性弧可。

證書生成

證書結構

證書結構方案所需的證書結構如下:

生成證書

生成私鑰

openssl genrsa -out ca.key 4096

# 生成自簽名根證書

openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

生成服務端用證書

# 生成私鑰?

openssl genrsa -out server.key 4096

# 生成CSR證書請求

openssl req -new -key server.key -out server.csr

# 使用CA1根證書簽發(fā)證書

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650

生成客戶端證書的過程同生成服務端的過程相同,更換相應名稱即可

配置服務端Nginx

? 配置并啟動修改服務端 Nginx配置文件并啟動劣欢,具體關鍵配置如下:

服務端Nginx啟動

docker run \

? ? --name nginx_server \

? ? # 指定映射的端口

-p 30443:30443 \

? ? -d \

? ? #將相應的證書和配置文件掛載入容器

-v /Users/zhangchenyu/Documents/temp/nginx_test2/server/conf/nginx.conf:/etc/nginx/nginx.conf:ro \

? ? -v /Users/zhangchenyu/Documents/temp/nginx_test2/server/conf/index.html:/etc/nginx/html/index.html:ro \

? ? -v /Users/zhangchenyu/Documents/temp/nginx_test2/ca1:/etc/nginx/ca1:ro \

? ? -v /Users/zhangchenyu/Documents/temp/nginx_test2/ca2:/etc/nginx/ca2:ro \

? ? nginx

使用curl命令檢查Nginx是否已經(jīng)啟用雙向認證

證書注冊時使用了域名棕诵,將注冊時的相關域名添加到 /etc/hosts,否則使用本地ip無法訪問凿将。

直接訪問

curl \

? ? # 指定服務端證書的CA證書

--cacert ../ca1/ca.crt \

? ? https://test.server:30443

服務端返回的結果提示:要求的證書未發(fā)送校套。

指定客戶端發(fā)送證書

curl \

# 指定服務端證書的CA證書

--cacert ../ca1/ca.crt \

# 指定客戶端證書

--cert client.crt \

# 指定客戶端私鑰

--key ./client.key \

# 指定tls 協(xié)議版本

--tlsv1.2 \

? ? https://test.server:30443

調(diào)用結果:

當我們看到服務端返回了相應的頁面,說明服務端已經(jīng)開始使用雙向HTTPS丸相,對接收到的請求不再全部接受搔确,而是在HTTPS握手階段要求客戶端發(fā)送客戶端證書進行校驗,校驗通過的請求才進行處理灭忠。

配置客戶端Nginx的正向代理

配置并啟動

客戶端Nginx配置見下

注意:docker容器內(nèi)的Nginx 在配置轉發(fā)地址膳算,指定的IP端口需要為容器內(nèi)部IP端口。

客戶端Nginx 啟動

docker run \

? ? --name nginx_client\

? ? -d \

? ? # 指定端口映射

-p 9999:9999 \

? ? # 將相應的證書和配置文件掛載入容器

-v /Users/zhangchenyu/Documents/temp/nginx_temp2/client/conf/nginx.conf:/etc/nginx/nginx.conf:ro \

? ? -v /Users/zhangchenyu/Documents/temp/nginx_temp2/ca1:/etc/nginx/ca1:ro \

? ? -v /Users/zhangchenyu/Documents/temp/nginx_temp2/ca2:/etc/nginx/ca2:ro \

? ? nginx

使用 curl 命令檢查鏈路連通性

至此弛作,整套鏈路已經(jīng)搭建完成涕蜂,如果使用curl 命令能最后訪問到相應的服務端頁面,那說明我們目標達成

curl http://127.0.0.1:9999

調(diào)用結果:

顯然映琳,客戶端使用HTTP就訪問到了終端服務机隙。通過以上步驟我們可以看到Nginx 的兩次代理,已經(jīng)完全實現(xiàn)了本次需求萨西。同時有鹿,我們發(fā)現(xiàn)通過Nginx配置的修改即可實現(xiàn)接口權限的控制,且保證網(wǎng)絡傳輸?shù)陌踩?/p>

抓包分析

最后谎脯,完成了配置也別忘了總結分析哦葱跋。我們對雙向HTTPS的握手和交互的過程進行抓包,抓包的同時簡要分析單雙向HTTPS的差異源梭,并對雙向HTTPS實現(xiàn)權限的控制過程予以了解娱俺。

單向HTTPS流量分析

隨意訪問一個HTTPS網(wǎng)站,并抓包废麻。具體內(nèi)容見下圖 :

1. 客戶端向服務端發(fā)送 Client Hello荠卷,其中包含一個隨機數(shù)A、支持的TLS版本烛愧、支持的加密套件等

2. 服務器響應給客戶端一個隨機數(shù)B油宜、選用的TLS協(xié)議版本掂碱、選用的加密套件、服務器證書验庙、DH公鑰等

此處Server Hello的包和證書顶吮、服務端DH公鑰等響應的數(shù)據(jù)包分成了兩個,而雙向HTTPS的數(shù)據(jù)包是單個的粪薛,這與單向雙向無關悴了,具體看服務器對HTTPS協(xié)議的實現(xiàn)方式。

3. 客戶端返回DH公鑰

4. 使用DH算法計算生成Pre-master secret违寿,并通過Master Secret生成器及隨機數(shù)A湃交、隨機數(shù)B、Pre-master Secret 生成最終加密通信所用的Master Secret

5. 客戶端和服務端互相告知對方自己狀態(tài)切換完成藤巢,并發(fā)送一條加密信息搞莺,以互相驗證雙方都擁有了正確的Master Secret

6. 握手完成,開始使用 Master Secret加密通信梳理下整體流程:

雙向HTTPS流量分析

此處抓包的內(nèi)容源自兩臺Nginx之間的流量

客戶端向服務端發(fā)送 Client Hello掂咒,其中包含隨機數(shù)A才沧、支持的TLS版本、支持的加密套件等

加密套件說明 例如:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

ECDHE 秘鑰交換算法

RSA 身份驗證算法

AES128_GCM 批量加密算法

SHA256 消息認證碼算法

2.? 服務器響應給客戶端隨機數(shù)B绍刮、選用的TLS協(xié)議版本温圆、選用的加密套件、服務器證書孩革、DH算法公鑰岁歉、以及要求客戶端返回證書的請求等

–? ? 隨機數(shù)B、選用的TLS協(xié)議版本膝蜈、選用的加密套件

–? 服務端證書

–? 服務端DH公鑰

ServerKeyExchange是只有DH秘鑰交換算法才有的一步锅移,可以理解為這一步是為了計算得到Pre-master Secret;通過非對稱加密方式來握手獲取Pre-master Secret的加密套件不需要這一步饱搏。

–? 要求客戶端返回證書的請求

3.? 客戶端校驗證書的有效性

此處操作由Nginx 客戶端內(nèi)部完成非剃,未體現(xiàn)在抓包中。

4.? 客戶端返回客戶端自身證書, 以及對證書的簽名后, 通知服務端自己的加密策略已轉換推沸,以及第一條加密信息(用協(xié)商出的加密秘鑰加密)

–? 客戶端證書

此處區(qū)別于單向HTTPS努潘,客戶端發(fā)送的證書會被服務端Nginx配置的根證書進行校驗,只有驗證通過的客戶端才可進行下一步坤学。

– 客戶端DH算法公鑰

ClientKeyExchange,同ServerKeyExchange類似报慕,都是為了支援DH交換秘鑰

– 對證書的簽名

客戶端為了證明發(fā)出去的證書是自己的深浮,需要使用私鑰對證書進行簽名,以確認證書身份眠冈。

–? 通知服務端自己的加密策略已轉換(Client)

– Encrypted Handshake Message 客戶端第一條使用Master Secret加密的數(shù)據(jù)

Master Secret = MasterSecret生成器(隨機數(shù)A飞苇、 隨機數(shù)B菌瘫、 DH交換獲得的Pre-master Secret)

此消息發(fā)給服務端后,服務端會使用生成的Master Secret 進行解密布卡,確認客戶端已生成正確的Master Secret

5.? 服務端返回Session Ticket雨让、通知客戶端自己的加密策略已轉換以及第一條使用Master Secret加密的數(shù)據(jù)

– Session Ticket

服務端會緩存Master Secret 一段時間,只需要客戶端將Session Ticket 帶過來忿等,可以避免重復握手導致的資源開銷

– 通知服務端自己的加密策略已轉換(Server)

–? ? 服務端返回第一條使用Master Secret加密的數(shù)據(jù)栖忠,功能等同于服務端發(fā)送Encrypted Handshake Message,此項給客戶端是為了向客戶端證明自己也生成了正確的Master Secret贸街。

6. 開始使用Master Secret 加密數(shù)據(jù)并開始通信

梳理下整體流程:

流程對比

我們結合整體抓包和分析的流程可知庵寞,雙向HTTPS和單向HTTPS相比,多了對客戶端證書校驗薛匪、以及相應支援處理的步驟捐川。客戶端只有拿到了服務端CA頒發(fā)的證書逸尖,才能訪問到服務端古沥,這也是雙向HTTPS擁有一定權限控制功能的基礎。

總結

前文提及的改造需求娇跟,如果按照常規(guī)思路選擇改動業(yè)務代碼新增權限控制功能请垛,需要改動的整體流程較為復雜叨粘,開發(fā)成本也相對較重,為此我們借鑒雙向HTTPS的策略,通過修改配置方式快速地實現(xiàn)了該需求碘梢,避免了相關權限控制的重復勞動。

此外乳绕,HTTPS整體流程享潜,無論是單向還是雙向,都是互聯(lián)網(wǎng)技術領域的基礎保障基协,值得我們開發(fā)者繼續(xù)探究和學習其協(xié)議的相關細節(jié)歌亲。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市澜驮,隨后出現(xiàn)的幾起案子陷揪,更是在濱河造成了極大的恐慌,老刑警劉巖杂穷,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悍缠,死亡現(xiàn)場離奇詭異,居然都是意外死亡耐量,警方通過查閱死者的電腦和手機飞蚓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廊蜒,“玉大人趴拧,你說我怎么就攤上這事溅漾。” “怎么了著榴?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵添履,是天一觀的道長。 經(jīng)常有香客問我脑又,道長暮胧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任挂谍,我火速辦了婚禮叔壤,結果婚禮上,老公的妹妹穿的比我還像新娘口叙。我一直安慰自己炼绘,他們只是感情好,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布妄田。 她就那樣靜靜地躺著俺亮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疟呐。 梳的紋絲不亂的頭發(fā)上脚曾,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音启具,去河邊找鬼本讥。 笑死,一個胖子當著我的面吹牛鲁冯,可吹牛的內(nèi)容都是我干的拷沸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼薯演,長吁一口氣:“原來是場噩夢啊……” “哼撞芍!你這毒婦竟也來了?” 一聲冷哼從身側響起跨扮,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤序无,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后衡创,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帝嗡,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年璃氢,在試婚紗的時候發(fā)現(xiàn)自己被綠了哟玷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡拔莱,死狀恐怖碗降,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塘秦,我是刑警寧澤讼渊,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站尊剔,受9級特大地震影響爪幻,放射性物質發(fā)生泄漏。R本人自食惡果不足惜须误,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一挨稿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧京痢,春花似錦奶甘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至方淤,卻和暖如春钉赁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背携茂。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工你踩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讳苦。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓带膜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親医吊。 傳聞我的和親對象是個殘疾皇子钱慢,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359