原文:https://blog.csdn.net/wenwen360360/article/details/78913347
最近老在項目的shell腳本中看到kinit這個東西,完整的命令是
kinit -k -t ./conf/kerberos.keytab sherlocky/admin
查閱一番資料后了解到,之所以有這個命令,是由於該shell腳本接下來會訪問Hadoop集群,從上面拉取文件做一些處理任務,並將結果存到Hadoop集群上,那么該命令的作用就是進行身份驗證(Authentication),確保Hadoop集群資源的安全。這里就牽扯到kerberos協議,本文接下來將對此一一闡述。
一、kinit命令
Kinit命令用於獲取和緩存principal(當前主體)初始的票據授予票據(TGT),此票據用於Kerberos系統進行身份安全驗證,實際上它是MIT在版權許可的條件下為kerberos協議所研發的免費實現工具MIT Kerberos(當前最新版本為krb5-1.15.1)的一部分,相關的配套命令還有klist、kdestory、kpasswd、krb5-config等等,基本用法如下:
kinit [-V][-l lifetime] [-s start_time][-r renewable_life][-p | -P][-f | -F][-a][-A][-C][-E][-v][-R][-k [-t keytab_file]][-c cache_name][-n][-S service_name][-I input_ccache][-T armor_ccache][-X attribute[=value]][principal]
各選項具體含義都不做介紹了,可參考官網,較常用的方式就如前言所示,根據指定的事先生成的kerberos.keytab文件為指定個體進行驗證。驗證通過后,就可以像平常一樣進行Hadoop系列操作。那么它是如何進行驗證的呢?其中的過程和原理又是怎樣的?下面要介紹的kerberos協議細節將會回答你的疑惑。
二、Kerberos協議
Kerberos(具體可參考RFC1510)是一種網絡身份驗證的協議(注意它只包括驗證環節,不負責授權,關於這兩者后面會有介紹區分),用戶只需輸入一次身份驗證信息,就可憑借此驗證獲得的票據授予票據(ticket-granting ticket)訪問多個接入Kerberos的服務,即SSO(Single Sign On,單點登錄)。
1.基本概念
- Principal:安全個體,具有唯一命名的客戶端或服務器。命名規則:主名稱+實例+領域,如本文開頭中的
sherlocky/admin@EXAMPLE.COM
- Ticket:票據,一條包含客戶端標識信息、會話密鑰和時間戳的記錄,客戶端用它來向目標服務器認證自己
- Session key:會話密鑰,指兩個安全個體之間使用的臨時加密秘鑰,其時效性取決於單點登錄的會話時間長短
- AS:認證服務器(Authentication Server),KDC的一部分。通常會維護一個包含安全個體及其秘鑰的數據庫,用於身份認證
- SS:特定服務的提供端(Service Server)
- TGS:許可證服務器(Ticket Granting Server),KDC的一部分,根據客戶端傳來的TGT發放訪問對應服務的票據
- TGT:票據授予票據(Ticket Granting Ticket),包含客戶端ID、客戶端網絡地址、票據有效期以及client/TGS會話密鑰
- KDC:Key分發中心(key distribution center),是一個提供票據(tickets)和臨時會話密鑰(session keys)的網絡服務。KDC服務作為客戶端和服務器端信賴的第三方,為其提供初始票據(initial ticket)服務和票據授予票據(ticket-granting ticket)服務,前半部分有時被稱為AS,后半部分有時則被稱為TGS。
關於概念的一點補充,博文Kerberos 服務的工作原理中對於TGT和Ticket給出了巧妙的比喻:TGT類似於護照,Ticket則是簽證,而訪問特定的服務則好比出游某個國家。與護照一樣,TGT可標識你的身份並允許你獲得多個Ticket(簽證),每個Ticket對應一個特定的服務,TGT和Ticket同樣具有有效期,過期后就需要重新認證。
2.認證過程
Kerberos的認證過程可細分為三個階段:初始驗證、獲取服務票據和服務驗證。第一階段主要是客戶端向KDC中的AS發送用戶信息,以請求TGT,然后到第二階段,客戶端拿着之前獲得的TGT向KDC中的TGS請求訪問某個服務的票據,最后階段拿到票據(Ticket)后再到該服務的提供端驗證身份,然后使用建立的加密通道與服務通信。
2.1 初始驗證
此過程是客戶端向AS請求獲取TGT:
- 客戶端向AS發送自身用戶信息(如用戶ID),該動作通常發生在用戶初次登陸或使用kinit命令時
- AS檢查本地數據庫是否存在該用戶,若存在則返回如下兩條信息:
- 消息A:使用用戶密鑰加密的Client/TGS會話密鑰,我們稱之為SK1。其中用戶密鑰是通過對該用戶在數據庫中對應的密碼hash生成的
- 消息B:使用TGS的密鑰加密的TGT(包含客戶端ID、客戶端網絡地址、票據有效期和SK1)
- 當客戶端收到消息A和B時,它會嘗試用本地的用戶密鑰(由用戶輸入的密碼或kerberos.keytab文件中的密碼hash生成)對A進行解密,只有當本地用戶密鑰與AS中對應該用戶的密鑰匹配時才能解密成功。對A解密成功后,客戶端就能拿到SK1,才能與TGS進行后續的會話,這里就相當於AS對客戶端的一次驗證,只有真正擁有正確用戶密鑰的客戶端才能有機會與AS進行后續會話。而對於消息B,由於它是由TGS的密鑰加密的,故無法對其解密,也看不到其中的內容。
2.2 獲取服務票據
此過程則是客戶端向TGS請求獲取訪問對應服務的票據:
當客戶端要訪問某個服務時,會向TGS發送如下兩條消息:
- 消息C:消息B的內容(即加密后的TGT)和服務ID
- 消息D:通過SK1加密的驗證器(Authenticator,包括用戶ID和時間戳)
TGS收到消息C和D后,首先檢查KDC數據庫中是否存在所需服務,若存在則用自己的TGS密鑰嘗試對C中的消息B進行解密,這里也是客戶端對TGS的反向認證,只有真正擁有正確密鑰的TGS才能對B解密,解密成功后就能拿到其中的SK1,然后再用SK1解密消息D拿到包含用戶ID和時間戳的Authenticator,通過比較分別來自C和D的用戶ID,如果二者匹配,則向客戶端返回如下兩條消息:
- 消息E:通過SK1加密的Client/SS會話密鑰,該會話密鑰是KDC新生成的隨機密鑰,用於將來客戶端(Client)與服務端(SS)的通信加密,我們稱之為SK2
- 消息F:使用服務的密鑰加密的client-server票據(Ticket,包含用戶ID、用戶網絡地址、票據有效期和SK2),之所以要用服務的密鑰加密,是因為這個Ticket是給服務端看的,但又需要經過客戶端傳給服務端,且不能讓客戶端看到。那么就會有人問,為什么KDC不直接把消息E發送給服務端呢,這樣豈不省事?問題就在於網絡時延,若分開發送,消息E和F就不能確保同時到達服務端,考慮一個極端情況,KDC與服務之前的網絡臨時不通了,那么這段時間服務端就無法收到消息E,導致驗證失敗,而實際上該客戶端是有訪問權限的。通過公鑰加密這種方式巧妙地回避了該問題
客戶端收到消息后,嘗試用SK1解密消息E,得到Client/SS會話密鑰SK2
2.3 服務驗證
此過程是客戶端與服務端相互驗證,並通信
客戶端向服務端發送如下兩條消息:
消息G:即上一步中的消息F——client-server票據
消息H:通過SK2加密的新的驗證器(Authenticator,包含用戶ID和時間戳)
服務端收到消息后,嘗試用自己的密鑰解密消息G,這里實際上也是客戶端對服務端的一次驗證,只有真正擁有正確密鑰的服務端才能正確解密,從而有機會拿到Ticket中的SK2,然后再用該SK2解密消息H,同TGS一樣,對分別來自Ticket和Authenticator中的用戶ID進行驗證,如果匹配成功則返回一條確認消息:
- 消息I:通過SK2加密的新時間戳
客戶端嘗試用SK2解密消息I,得到新時間戳並驗證其正確性,驗證通過后,客戶端與服務端就達到了相互信任,后續的通信都采用SK2加密,就好比建立了一條加密通道,二者即可享受服務與被服務的樂趣了
3.前提(環境假設)
- 共享密鑰:在協議工作前,客戶端與KDC,KDC與服務端都確保有了各自的共享密鑰。
- 防Dos攻擊:Kerberos協議本身並沒有解決Dos攻擊(Denial of service,拒絕服務)防范問題,通常是由系統管理員和用戶自己去定期探測並解決這樣的攻擊。
- 保障安全個體自身安全:參與到Kerberos協議中的安全個體必須確保其秘鑰的安全性,一旦秘鑰泄露或被攻擊者暴力破解,那么攻擊者就能隨意地偽裝安全個體,做一些不和諧的事情。
- 不循環利用Principal的唯一標識:訪問控制的常用方式是通過訪問控制列表(access control lists,ACLs)來對特定的安全個體進行授權。如果列表中有條記錄對應的安全個體A早已被刪除,而A的唯一標識卻被后來新加的某個個體B再次利用,那么B就會繼承之前A對應的權限,這是不安全的。避免這種風險的做法就是不復用Principal的唯一標識。
- 時鍾同步:參與到協議中的主機必須有個時鍾相互之間進行“松散同步”,松散度是可配置的。為什么需要同步各主機的時間呢?實際上從Kerberos的認證過程可以看到,任何人都可以向KDC請求任何服務的TGT,那攻擊者就有可能中途截獲正常用戶的請求包,然后離線解密,就能合法地拿到TGT。為了防止這種重放攻擊,票據(Ticket)會包含時間戳信息,即具有一定的有效期,因此如果主機的時鍾與Kerberos服務器的時鍾不同步,則認證會失敗。在實踐中,通常用網絡時間協議(Network Time Protocol, NTP)軟件來同步時鍾。
4.局限性
- 單點風險:過度依賴於KDC服務,Kerberos協議運轉時需要KDC的持續響應,一旦KDC服務掛了,或者KDC數據庫被攻破,那么Kerberos協議將無法運轉
- 安全個體自身的安全:Kerberos協議之所以能運行在非安全網絡之上,關鍵假設就是主機自身是安全的,一旦主機上的私鑰泄露,攻擊者將能輕易的偽裝該個體實施攻擊
三、Kerberos應用
1.Hadoop安全機制
Apache Hadoop 最初設計時並沒有考慮安全問題,它不對用戶或服務進行驗證,任何人都可以向集群提交代碼並得到執行,使用Hadoop的組織只能把集群隔離到專有網絡,確保只有經過授權的用戶才能訪問,但這也並不能解決Hadoop集群內部的安全問題。為了增強Hadoop的安全機制,從1.0.0版本以后,引入Kerberos認證機制,即用戶跟服務通信以及各個服務之間通信均用Kerberos認證,在用戶認證后任務執行、訪問服務、讀寫數據等均采用特定服務發起訪問token,讓需求方憑借token訪問相應服務和數據。下面以Yarn中提交MR任務為例:
A、用戶先向KDC請求TGT,做初始驗證
B、用戶通過TGT向KDC請求訪問服務的Ticket
C、客戶端通過ticket向服務認證自己,完成身份認證
D、完成身份認證后,客戶端向服務請求若干token供后續任務執行時認證使用
F、客戶端連同獲取的token一並提交任務,后續任務執行使用token與服務進行認證
四、其他安全機制
1.OAuth認證
OAuth(Open Authorization,開放授權)用於第三方授權服務,現常用的第三方賬號登陸都是采用該機制。比如我用github賬號登陸LeetCode官網,LeetCode並不需要知道我的github賬號、密碼,它只需要將登陸請求轉給授權方(github),由它進行認證授權,然后把授權信息傳回LeetCode實現登陸。
2.LDAP
LDAP(Lightweight Directory Access Protocol,輕量級目錄訪問協議)是一種用於訪問目錄服務的業界標准方法,LDAP目錄以樹狀結構來存儲數據,針對讀取操作做了特定優化,比從專門為OLTP優化的關系數據庫中讀取數據快一個量級。LDAP中的安全模型主要通過身份認證、安全通道和訪問控制來實現,它可以把整個目錄、目錄的子樹、特定條目、條目屬性集火符合某過濾條件的條目作為控制對象進行授權,也可以把特定用戶、特定組或所有目錄用戶作為授權主體進行授權,也可以對特定位置(如IP或DNS名稱)進行授權。
3.SSL
SSL(Secure Sockets Layer,安全套接層)是目前廣泛應用的加密通信協議,其基本思路是采用公鑰加密法,即客戶端先向服務器端索要公鑰,然后用公鑰加密信息,服務端收到密文后用自己的私鑰解密。它的安全機制包含如下三點:
- 連接的私密性:利用會話密鑰通過對稱加密算法(DES)對傳輸數據進行加密,並利用RSA對會話密鑰本身加密
- 身份驗證:基於數字證書利用數字簽名方法進行身份驗證,SSL服務器和客戶端通過PKI(Public Key Infrastructure)提供的機制從CA獲取證書
- 內容可靠:使用基於密鑰的MAC(Message Authentication Code,消息驗證碼)驗證消息的完整性,防竄改
本文同步更新到此處
作者:sherlockyb 鏈接:https://www.jianshu.com/p/2039fe8c62a1 來源:簡書 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。