­

802.1X 帳號密碼+設備資訊雙重認證

名詞解釋

802.1X:

IEEE802 LAN/WAN 委員會為解決無線區域網網路安全問題,提出了 802.1X 協議。後來,802.1X協議作為區域網埠的一個普通接入控制機制在乙太網中被廣泛應用,主要解決乙太網內認證和安全方面的問題。802.1X 協議是一種基於埠的網路接入控制協議(port based network access control protocol)。「基於埠的網路接入控制」是指在區域網接入設備的埠這一級對所接入的用戶設備進行認證和控制。連接在埠上的用戶設備如果能通過認證,就可以訪問區域網中的資源;如果不能通過認證,則無法訪問區域網中的資源。

EAP協議:

EAP(Extensible Autllentication Protocol) 協議是 802.1X協議定義的一種報文封裝格式,主要用於在客戶端和設備端之間傳送EAP協議報文,以允許EAP協議報文在LAN上傳送。目前可以採用的EAP類型包括:EAP-MD5、LEAP、PEAP、EAP—TLS 等方式。本文主要使用的協議為EAP-MD5協議,進行802.1X網路認證。

FreeRADIUS:

RADIUS認證伺服器(Remote Authentication Dial In User Service,遠程用戶撥號認證系統)是目前應用最廣泛的AAA協議(AAA=authentication、Authorization、Accounting,即認證、授權、計費),FreeRADIUS包含一個radius伺服器和radius-client,可以對支援radius協議的網路設備進行鑒權記賬。

RSA非對稱加密:

對稱加密演算法在加密和解密時使用的是同一個秘鑰,與對稱加密演算法不同,非對稱加密演算法需要兩個密鑰:[公開密鑰](publickey)和[私有密鑰](privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種演算法叫作非對稱加密演算法。

問題&&現狀

目前802.1X網路認證中EAP-MD5協議主要流程就是客戶端發送用戶帳號和經過MD5加密後的密碼到RADIUS認證伺服器,RADIUS服務通過調用 OpenLDAP/Mysql 等組件,查詢對應的用戶是否存在,並校驗密碼是否一致,來判斷用戶是否合法,然後回應認證成功/失敗報文到接入設備,接入設備根據RADIUS伺服器響應的報文,向客戶端響應成功/失敗狀態,並設置埠授權狀態,從而控制用戶是否能通過埠訪問網路。

僅針對帳號密碼進行認證,這樣的驗證方式單一而且缺乏力度,忽略了終端安全。按照目前的認證方式,一旦用戶密碼不慎泄漏,非法用戶可以通過不可信的終端接入網內,從而存在很多安全隱患。在伺服器、網路、終端這樣三位一體的電腦通訊系統上,終端是最為龐大的主體,而且攻擊也多半是從終端發起的。終端將成為我們安全體系中越發不可忽視的一環。只要保證目前系統中的所有主體都是安全可信賴的,而新的主體在加入網路時也通過了安全性驗證,那麼無論網路規模如何發展,整個體系的安全性都能得到很好的保障。

技術方案

為了滿足網路准入安全性要去,本方案主要是在原有的EAP-MD5協議帳號密碼單一認證基礎上,再通過驗證終端設備的硬體資訊(MAC地址,CPU序列號,硬碟序列號等),在進行802.1X網路認證的時,實現 帳號密碼+設備資訊 雙重認證,從而提高對接入用戶與終端設備的可信性和可控性管理。

整體設計

802.1X帳號密碼+設備資訊認證總體可以劃分為下面幾個模組

  1. 設備認證服務模組:進行設備資訊的錄入,並進行設備證書校驗等功能
  2. 客戶端模組:客戶端模組主要是發起經過改造後的802.1X認證協議
  3. freeradius認證服務模組:freeradius服務模組主要負責調用OpenLDAP/Mysql進行帳號密碼認證,並轉發EAP-MD5協議相關資訊到設備認證服務端模組,從而完成設備資訊的校驗

改造前 EAP-MD5認證 流程如下

如圖所示:
avatar

  1. 當用戶有訪問網路需求時打開 802.1X 客戶端程式,輸入已經申請、登記過的用戶名和碼,發起連接請求(EAPOL-Start 報文)。此時,客戶端程式將發出請求認證的報文給設備端,開始啟動一次認證過程。
  2. 設備端收到請求認證的數據幀後,將發出一個請求幀(EAP-Request/Identity 報文)要求用戶的客戶端程式發送輸入的用戶名。
  3. 客戶端程式響應設備端發出的請求,將用戶名資訊通過數據幀(EAP-Response/Identity 報文)發送給設備端。設備端將客戶端發送的數據幀經過封包處理後(RADIUS Access-Request 報文)送給認證伺服器進行處理。
  4. RADIUS 伺服器收到設備端轉發的用戶名資訊後,將該資訊與資料庫中的用戶名表對比,找到該用戶名對應的密碼資訊,用隨機生成的一個加密字對它進行加密處理,同時也將此加密字通過 RADIUS Access-Challenge 報文發送給設備端,由設備端轉發給客戶端程式。
  5. 客戶端程式收到由設備端傳來的加密字(EAP-Request/MD5 Challenge 報文)後,用該加密字對密碼部分進行加密處理(此種加密演算法通常是不可逆的),生成 EAP-Response/MD5 Challenge 報文,並通過設備端傳給認證伺服器。
  6. RADIUS 伺服器將收到的已加密的密碼資訊(RADIUS Access-Request 報文)和本地經過加密運算後的密碼資訊進行對比,如果相同,則認為該用戶為合法用戶,回饋認證通過的消息(RADIUS Access-Accept 報文和 EAP-Success 報文)。

改造後 帳號密碼+設備資訊認證 流程如下

如圖所示:
avatar

  1. 在客戶端發起802.1X網路認證之前,設備認證服務端需要主動採集終端設備相關資訊(MAC地址,CPU序列號,硬碟序列號等),通過SHA256摘要演算法,生成設備資訊摘要,將設備相關資訊保存到設備認證服務端資料庫中
  2. 通過改造原有802.1X 客戶端程式,在改造前流程第5步,發送 MD5 Challenge 的同時,讀取出端設備相關資訊並生成設備資訊摘要,並通過RSA非對稱加密演算法,加密摘要資訊,通過EAP-MD5協議擴展欄位 EAP-MD5 Extra Data 傳遞到freeradius認證伺服器
  3. freeradius認證伺服器通過配置開啟自身rlm_rest模組,將加密後的設備摘要資訊轉發到設備認證服務模組
  4. 設備認證服務模組讀取加密後的摘要資訊,通過私鑰進行解密,然後在認證服務端資料庫中進行查詢,如果可以匹配到同樣的摘要資訊,則表示該終端設備資訊合法,返回成功狀態碼給freeradius認證伺服器,freeradius認證伺服器會結合帳號密碼認證結果統一判斷,如果 帳號密碼+設備資訊 都認證通過,則允許用戶訪問網路,否則不允許用戶訪問網路

關鍵程式碼

客戶端相關程式碼

func (h *Handle) SendResponseMD5Chall(id uint8, salt, user, pass []byte) error {
	// MD5 Challenge MD5加密後的密碼資訊
	plain := []byte{id}
	plain = append(plain, pass...)
	plain = append(plain, salt[:0x10]...)
	cipher := md5.Sum(plain)
	data := append([]byte{uint8(len(cipher))}, cipher[:]...)

	//初始化密鑰對
	rsaCryptoKey := GenRasKeyFromPem("./config/client_private.pem", "./config/server_public.pem")

	//獲取設備資訊摘要(64位字元串)
	deviceInfo := GetSHA256DeviceInfo()

	//加密設備資訊摘要
	enc, err := rsaCryptoKey.RsaEncrypt([]byte(deviceInfo))
	if err != nil {
		return err
	}

	//base64編碼
	base64ExtarData := base64.StdEncoding.EncodeToString(enc)

	//將加密後的設備資訊摘要加入到EAP請求包內
	data = append(data, []byte(base64ExtarData)...)

	eth := layers.Ethernet{
		SrcMAC:       h.srcMacAddr,
		DstMAC:       h.dstMacAddr,
		EthernetType: layers.EthernetTypeEAPOL,
	}

	eapol := layers.EAPOL{
		Version: 0x01,
		Type:    layers.EAPOLTypeEAP,
		Length:  uint16(5 + len(data)),
	}

	eap := layers.EAP{
		Code:     layers.EAPCodeResponse,
		Id:       id,
		Type:     layers.EAPTypeOTP,
		TypeData: data,
		Length:   eapol.Length,
	}

	if err := h.send(&eth, &eapol, &eap, &fillLayer); err != nil {
		return err
	}
	return nil
}

設備認證服務模組

//授權操作
// http.StatusNoContent 對應freeradius ok 狀態
// http.StatusUnauthorized 對應freeradius reject 狀態
func Authorize(c *gin.Context) {
	var (
		err  error               = nil
		data []byte              = nil
		auth model.AuthorizeInfo = model.AuthorizeInfo{}
	)

    //讀取freeradius rest模組轉發的消息
	data, err = ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	log.Info("Authorize data:%v", string(data))

	err = json.Unmarshal(data, &auth)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	if len(auth.EAPMessage) <= 46 {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, "Authorize wrong length"))
		return
	}

	//EAPMessage消息結構:前14位為請求頭資訊,15-46中間32位是MD5加密後的密碼資訊,46-末尾是Extra Data 擴展欄位的資訊
	extarData := auth.EAPMessage[46:]
	log.Info("Authorize extarData:%v", extarData)

	//解析設備摘要資訊
	decHexExtarData, err := hex.DecodeString(extarData)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	decBase64ExtarData, err := base64.StdEncoding.DecodeString(decHexExtarData)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	//解密設備摘要資訊
	deviceInfo, err := config.RsaCryptoKey.RsaDecrypt(decBase64ExtarData)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	//校驗設備摘要資訊是否在資料庫內
	_, err = dao.IsExist(deviceInfo)
	if err != nil {
		c.JSON(http.StatusUnauthorized, model.ErrResultModel(model.ParamErr, err.Error()))
		return
	}

	//校驗設備摘要資訊通過則響應 http.StatusNoContent 204 狀態
	c.JSON(http.StatusNoContent, model.OkResultModel("success"))
	return
}

freeradius認證服務模組

freeradius認證服務模組主要為相關配置,以實現認證消息轉發的功能

編譯安裝

rlm_rest 模組默認是不會安裝的,需要手動編譯安裝 freeradius 服務,編譯安裝freeradius-rest 模組時,需要進入 /src/modules/rlm_rest 模組執行 ./configure 檢查是否確少依賴包,安裝完對應的依賴包,否則會導致 freeradius 安裝成功,而 rlm_rest 模組編譯失敗的問題

配置rest模組

  1. 通過軟連接啟用rest模組
ln -s /usr/local/etc/raddb/mods-available/rest /usr/local/etc/raddb/mods-enabled/rest
  1. 修改rest相關配置
vim /usr/local/etc/raddb/mods-enabled/rest

//設備認證服務網關
connect_uri = "//127.0.0.1:2017"

//設置轉發參數和具體URL
authorize {
    uri = "${..connect_uri}/user/authorize"
    method = 'post'
    body = 'json'
    data = '{"user_name":"%{User-Name}","eap_message":"%{EAP-Message}","mac_id":"%{Calling-Station-Id}"}'
	tls = ${..tls}
	}
  1. 修改default文件,認證流程添加rest模組
vim /usr/local/etc/raddb/sites-enabled/default

authorize{
    rest
}

authenticate{
    Auth-Type rest{
        rest
    }
}

accouting{
    rest
}

  1. 重啟 freeradius認證服務 即可實現認證請求的轉發

實驗驗證

環境搭建:需要一台UOS客戶端兩台(一台設備資訊已錄入,一台設備資訊未錄入,安裝經過改造後的802.1X協議的客戶端),一台UOS服務端(編譯安裝freeradius),一台支援802.1X協議交換機(設置埠開啟802.1X協議認證)

場景一:測試 帳號密碼正確+設備資訊未登記 場景

如圖所示:
avatar

客戶端2發起802.1X認證請求,帳號為:yangyi,密碼為:testing,設備摘要資訊為:a4de2da2c87361550d24110dd18eb4c021e20db461102e677683aab5490e3484,在 EAP-MD5 請求 Response MD5-Challenge 節點,將經過加密後的摘要資訊發送到設備認證伺服器端,因為此設備摘要資訊未在設備認證伺服器端登記,所以交換機響應 Failure 狀態,用戶入網失敗

場景二:測試 帳號密碼正確+設備資訊已登記 場景

如圖所示:
avatar

客戶端1發起802.1X認證請求,帳號為:yangyi,密碼為:testing,設備摘要資訊為:21e20db461102e677683aab5490e3484a4de2da2c87361550d24110dd18eb4c0,在EAP-MD5 請求 Response MD5-Challenge 節點,將經過加密後的摘要資訊發送到設備認證伺服器端,因為此設備摘要資訊已在設備認證伺服器端登記,所以交換機響應 Success 狀態,用戶入網成功

小結

以上介紹了802.1X基於埠訪問控制協議的相關技術,提出並實現基於帳號密碼+設備資訊雙重認證的方案,以及對802.1X協議的擴展。整個系統是在Linux平台上基於802.1X認證的開源客戶端工具和伺服器端軟體FreeRADIUS進行新功能開發和改進,並最終實現了用戶帳號密碼認證和設備資訊雙重認證的功能。所實現的系統在用戶發起入網請求時,客戶端軟體會自動獲取終端設備資訊,並生成設備資訊摘要,和經過MD5加密後密碼,一起發送到FreeRADIUS認證伺服器,使得FreeRADIUS伺服器在完成對用戶身份驗證的同時也可以完成對終端設備資訊的可信認證。最後的測試結果顯示,該方案可以滿足可信網路連接的基本功能需求,將來可以實際應用於可信網路的接入控制。

但目前的該方案也存在以下一些不足之處:

  • EAP—MD5協議目前只能支援有線網路接入認證,對於無限網路接入認證,還需要進一步的研究
  • 設備擴展資訊雖然通過RSA非對稱加密後的密文進行傳輸,但公鑰保存在客戶端,可能存在泄漏的風險,可以考慮對公鑰進行密碼保護,或者需要管理員許可權才可以讀取到公鑰資訊,或者直接由服務端下發證書給客戶端的方案

參考資料