1.背景
網際網路從來就不是一個安全的地方。很多時候我們過分依賴防火牆來解決安全的問題,不幸的是,防火牆是假設“壞人”是來自外部的,而真正具有破壞性的攻擊事件都是往往都是來自於內部的。
近幾年,在thehackernews
等網站上總會時不時的看到可以看到一些因為資料安全問題被大面積攻擊、勒索的事件。在Hadoop1.0.0之前,Hadoop並不提供對安全的支援,預設叢集內所有角色都是可靠的。使用者訪問時不需要進行任何驗證,++導致++惡意使用者很容易就可以偽裝進入叢集進行破壞。
要保證Hadoop叢集的安全,至少要做到2個A:Authentication
(認證),Authorization
(授權)。常見的方案有:
- Authentication: MIT Kerberos, Azure AD, Kerby
- Authorization: Apache Sentry(Cloudera), Apache Ranger(Hortonworks)
Hadoop叢集對Kerberos的支援
2012年1.0.0版本正式釋出後,Hadoop才增加了對Kerberos的支援, 使得叢集中的節點是可信任的。
Kerberos可以將認證的金鑰在叢集部署時事先放到可靠的節點上。叢集執行時,叢集內的節點使用金鑰得到認證,認證通過後的節點才能提供服務。企圖冒充的節點由於沒有事先得到的金鑰資訊,無法與叢集內部的節點通訊。這樣就防止了惡意地使用或篡改Hadoop叢集的問題,確保了Hadoop叢集的可靠性、安全性。
2.Kerberos介紹
Kerberos是種網路身份驗證協議,最初設計是用來保護雅典娜工程的網路伺服器。Kerberos這個名字源於希臘神話,是一隻三頭犬的名字,它旨在通過使用金鑰加密技術為Client/Server序提供強身份驗證。可以用於防止竊聽、防止重放攻擊、保護資料完整性等場合,是一種應用對稱金鑰體制進行金鑰管理的系統。Kerberos的擴充套件產品也使用公開金鑰加密方法進行認證。
Kerberos目前最新版本是5,1~3版本只在MIT內部發行,因為使用DES加密,早期被美國出口管制局列為軍需品禁止出口,直到瑞典皇家工學院實現了Kerberos版本4,KTH-KRB。後續也是這個團隊實現了版本5: Heimdal,目前常見的Kerberos5實現之一。
本文中討論的Kerberos5實現版本為MIT Kerberos,MIT保持的大約半年左右一次的更新速度,目前最新版本是2018-11-01釋出的1.16.2版本。
2.1 名詞解釋
- AS(Authentication Server):認證伺服器
- KDC(Key Distribution Center):金鑰分發中心
- TGT(Ticket Granting Ticket):票據授權票據,票據的票據
- TGS(Ticket Granting Server):票據授權伺服器
- SS(Service Server):特定服務提供端
- Principal:被認證的個體
- Ticket:票據,客戶端用來證明身份真實性。包含:使用者名稱,IP,時間戳,有效期,會話祕鑰。
使用Kerberos時,一個客戶端需要經過三個步驟來獲取服務:
認證
: 客戶端向認證伺服器傳送一條報文,獲取一個包含時間戳的TGT。授權
: 客戶端使用TGT向TGS請求指定Service的Ticket。服務請求
: 客戶端向指定的Service出示服務Ticket鑑權通訊。
Kerberos協議在網路通訊協定中屬於顯示層。其通訊流程簡單地說,使用者先用共享金鑰從某認證伺服器得到一個身份證明。隨後,使用者使用這個身份證明與SS通訊,而不使用共享金鑰。
2.2 具體通訊流程
①此流程使用了對稱加密; ②此流程發生在某一個Kerberos領域中; ③小寫字母c,d,e,g是客戶端發出的訊息,大寫字母A,B,E,F,H是各個伺服器發回的訊息。
首先,使用者使用客戶端上的程式進行登入:
- 輸入使用者ID和密碼到客戶端(或使用keytab登入)。
- 客戶端程式執行一個單向函式(大多數為Hash)把密碼轉換成金鑰,這個就是客戶端的“使用者金鑰”(user's secret key)。
2.2.1 客戶端認證(Kinit)
客戶端(Client)從認證伺服器(AS)獲取票據的票據(TGT)。
-
Client向AS傳送1條明文訊息,申請基於該使用者所應享有的服務,例如“使用者Sunny想請求服務”(Sunny是使用者ID)。(注意:使用者不向AS傳送“使用者金鑰”(user's secret key),也不傳送密碼)該AS能夠從本地資料庫中查詢到該申請使用者的密碼,並通過相同途徑轉換成相同的“使用者金鑰”(user's secret key)。
-
AS檢查該使用者ID是否在於本地資料庫中,如果使用者存在則返回2條訊息:
- 【訊息A】:Client/TGS會話金鑰(Client/TGS Session Key)(該Session Key用在將來Client與TGS的通訊(會話)上),通過 使用者金鑰(user's secret key) 進行加密。
- 【訊息B】:票據授權票據(TGT)(TGT包括:訊息A中的“Client/TGS會話金鑰”(Client/TGS Session Key),使用者ID,使用者網址,TGT有效期),通過TGS金鑰(TGS's secret key) 進行加密。
-
一旦Client收到訊息A和訊息B,Client首先嚐試用自己的“使用者金鑰”(user's secret key)解密訊息A,如果使用者輸入的密碼與AS資料庫中的密碼不符,則不能成功解密訊息A。輸入正確的密碼並通過隨之生成的"user's secret key"才能解密訊息A,從而得到“Client/TGS會話金鑰”(Client/TGS Session Key)。(注意:Client不能解密訊息B,因為B是用TGS金鑰(TGS's secret key)加密的)。擁有了“Client/TGS會話金鑰”(Client/TGS Session Key),Client就足以通過TGS進行認證了。
2.2.2 服務授權
Client從TGS獲取票據(client-to-server ticket)。
-
當client需要申請特定服務時,其向TGS傳送以下2條訊息:
- 【訊息c】:即訊息B的內容(TGS's secret key加密後的TGT),和想獲取的服務的服務ID(注意:不是使用者ID)。
- 【訊息d】:認證符(Authenticator)(Authenticator包括:使用者ID,時間戳),通過**Client/TGS會話金鑰(Client/TGS Session Key)**進行加密。
-
收到訊息c和訊息d後,TGS首先檢查KDC資料庫中是否存在所需的服務,查詢到之後,TGS用自己的“TGS金鑰”(TGS's secret key)解密訊息c中的訊息B(也就是TGT),從而得到之前生成的“Client/TGS會話金鑰”(Client/TGS Session Key)。TGS再用這個Session Key解密訊息d得到包含使用者ID和時間戳的Authenticator,並對TGT和Authenticator進行驗證,驗證通過之後返回2條訊息:
- 【訊息E】:client-server票據(client-to-server ticket)(該ticket包括:Client/SS會話金鑰 (Client/Server Session Key),使用者ID,使用者網址,有效期),通過提供該服務的伺服器金鑰(service's secret key) 進行加密。
- 【訊息F】:Client/SS會話金鑰( Client/Server Session Key) (該Session Key用在將來Client與Server Service的通訊(會話)上),通過Client/TGS會話金鑰(Client/TGS Session Key) 進行加密。
-
Client收到這些訊息後,用“Client/TGS會話金鑰”(Client/TGS Session Key)解密訊息F,得到“Client/SS會話金鑰”(Client/Server Session Key)。(注意:Client不能解密訊息E,因為E是用“伺服器金鑰”(service's secret key)加密的)。
2.2.3 服務請求
Client從SS獲取服務。
-
當獲得“Client/SS會話金鑰”(Client/Server Session Key)之後,Client就能夠使用伺服器提供的服務了。Client向指定伺服器SS發出2條訊息:
- 【訊息e】:即上一步中的訊息E“client-server票據”(client-to-server ticket),通過伺服器金鑰(service's secret key) 進行加密
- 【訊息g】:新的Authenticator(包括:使用者ID,時間戳),通過Client/SS會話金鑰(Client/Server Session Key) 進行加密
-
SS用自己的金鑰(service's secret key)解密訊息e從而得到TGS提供的Client/SS會話金鑰(Client/Server Session Key)。再用這個會話金鑰解密訊息g得到Authenticator,(同TGS一樣)對Ticket和Authenticator進行驗證,驗證通過則返回1條訊息(確認函:確證身份真實,樂於提供服務)。
- 【訊息H】:新時間戳(新時間戳是:Client傳送的時間戳加1,v5已經取消這一做法),通過Client/SS會話金鑰(Client/Server Session Key) 進行加密。
-
Client通過Client/SS會話金鑰(Client/Server Session Key)解密訊息H,得到新時間戳並驗證其是否正確。驗證通過的話則客戶端可以信賴伺服器,並向伺服器(SS)傳送服務請求。
-
伺服器(SS)向客戶端提供相應的服務。
3.Kerberos HA架構
Kerberos支援兩種伺服器在域內冗餘方式:Master/Slave
(MIT和Heimdal)和Multimaster
結構(Windows Active Directory)。在生產環境中部署Kerberos時,最好使用一主(Master)多從(Slave)的架構,以確保Kerberos服務的高可用性。
Kerberos中每個KDC都包含資料庫的副本。主KDC包含域(Realm)資料庫的可寫副本,它以固定的時間間隔複製到從KDC中。所有資料庫更改(例如密碼更改)都在主KDC上進行,當主KDC不可用時,從KDC提供Kerberos票據給服務授權,但不提供資料庫管理。KDC需要一個Admin來進行日常的管理操作。
Kerberos的同步機制只複製主資料庫的內容,但不傳遞配置檔案,以下檔案必須手動複製到每個Slave中:
- krb5.conf
- kdc.conf
- kadm5.acl
- master key stash file
複製程式碼
3.1 HA方案
目前單機房HA方案使用的較多的是Keepalived + Rsync 。Keepalived可以將多個無狀態的單點通過虛擬IP(以下稱為VIP)漂移的方式搭建成一個高可用服務。
首先,在Master KDC中建立資料庫的dump檔案(將當前的Kerberos和KADM5資料庫轉儲為ASCII檔案):
kdb5_util dump [-b7|-ov|-r13] [-verbose] [-mkey_convert] [-new_mkey_file mkey_file] [-rev] [-recurse] [filename [principals...]]
複製程式碼
然後使用Rsync將目錄同步到Slave機器的對應目錄中, 再匯入KDC中:
kdb5_util load [-b7|-ov|-r13] [-hash] [-verbose] [-update] filename [dbname]
複製程式碼
Hadoop所有請求通過請求內網域名,解析到Keepalived繫結的VIP的方式來使用KDC:
4. 優化和展望
4.1 優化
(1)使用者(Principal)管理
如果團隊中已經有一套許可權系統,要將現有的身份系統整合到Kerberos中會很困難。 隨著業務的飛速增長,伺服器規模越來越大,Kerberos Principal手動操作會越來越頻繁,手動的增刪改查維護會非常痛苦。需要在Kerberos管理系統中規範Principal申請、維護、刪除、keytab生成流程。Principal申請和許可權管理自動化。
(2)資料同步優化
Kerberos資料同步可以將生成的資料記錄同步寫入到MySQL中,使用MySQL雙主同步方式。在跨機房環境中,KDC資料使用Rsync工具進行增量同步。以A核心機房作為主機房,Rsync Server使用了Keepalived VIP的方式,當Kerberos主機當機後,VIP漂移到另外一臺主機器上,Rsync Client會以VIP所在的KDC主機器為Rsync Server進行資料同步,以保證KDC資料同步的高可用性。
(3)運維
使用程式管理工具對Kerberos相關程式進行存活監控,當發現有程式異常退出時,郵件/微信/釘釘報警,主動再次拉起程式。
4.2 展望
部署過Kerberos的同學都知道,在Hadoop叢集部署Kerberos實際是一項非常繁瑣的工作。Kerberos本質上是一種協議或安全通道,對於大多數使用者或普通使用者來說,是有一定學習曲線的,是否有更好的實現能夠對普通使用者隱藏這些繁瑣的細節。
阿里和Intel合作專案Hadoop Authentication Service (HAS) 據稱目前已經應用到ApsaraDB for HBase2.0中:
HAS方案使用Kerby替代MIT Kerberos服務,利用HAS外掛式驗證方式建立一套人們習慣的賬戶密碼體系。
目前HAS在Apache Kerby專案has-project
分支開發中,未來會作為Kerbby的新feature出現在下一次release中。
Apache Kerby作為Apache Directory的一個子專案,目前關注度並不高,讓我們期待它在後續的發展吧。