【協議】AAA Radius協議的常用報文分析

Mr.YF發表於2021-08-27

寫在前面的話

RADIUS:Remote Authentication Dial In User Service,遠端使用者撥號認證系統由RFC2865,RFC2866定義,是應用最廣泛的AAA協議。

如下簡單的分析一下 RADIUS 協議是怎麼工作的。

 

名詞解釋

BRAS:寬頻接入伺服器,Broadband Remote Access Server,簡稱 BRAS

NAS: 網路接入伺服器,Network Access Server,簡稱 NAS

AAA: 認證 Authentication,授權 Authorization,計費 Accounting

RADIUS: 遠端認證撥號使用者服務,remote authentication dial-in user service,簡稱RADIUS。

DM: Radius主動發起斷開連結請求 Disconnect-Request,簡稱DM

COA: Radius主動發起修改授權屬性,Change of Authorization,簡稱 COA

報文說明

 Radius協議的報文協議

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   |                         Authenticator                         |
   |                                                               |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Attributes ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-

在報文中的表示如下所示:

Radius 報文可以分為 Header 和 Attribute 兩部分

Radius 的頭部程式碼定義

// radius header
typedef struct RadHeader {i
    unsigned char  code;
    unsigned char  identifier;
    unsigned short length;
    unsigned char  authcator[16];
} RadHeader; 

Code 佔一個位元組

常用的取值如下:

1 Access-Request
2 Access-Accept
3 Access-Reject
4 Accounting-Request
5 Accounting-Response

6 Accounting Status (now Interim Accounting [5])
7 Password Request
8 Password Ack
9 Password Reject
10 Accounting Message
11 Access-Challenge
12 Status-Server (experimental)
13 Status-Client (experimental)

21 Resource Free Request
22 Resource Free Response
23 Resource Query Request
24 Resource Query Response
25 Alternate Resource Reclaim Request
26 NAS Reboot Request
27 NAS Reboot Response

29 Next Passcode
30 New Pin
31 Terminate Session
32 Password Expired
33 Event Request
34 Event Response
40 Disconnect Request
41 Disconnect Ack
42 Disconnect Nak
43 Change Filters Request
44 Change Filters Ack
45 Change Filters Nak
50 IP Address Allocate
51 IP Address Release

255 Reserved

 

Identifier是報文的流水號

NAS 和 AAA 伺服器通過這個流水號來標識認證請求和認證響應,計費請求和計費響應的配對關係。

如下所示:

認證請求和認證響應的配對關係(認證成功)

認證請求和認證響應的配對關係(認證失敗)

 

 計費請求和計費響應的配對關係。

  

Length 欄位是整個報文的長度

長度包括 Code, Identifier, Length, Authenticator 和 Attribute fields.

 

Authenticator認證

這個欄位主要是為了驗證報文的合法性。

計算方式如下 MD5(Code+ID+Length+RequestAuth+Attributes+Secret)

 

Attribute屬性

 這個欄位是 Radius 協議的重點,包括標準屬性和廠家的26號私有屬性兩類。

Attribute 通過 T-L-V 編碼格式進行編碼,Type-Length-Value

Radius 的 Attribute 程式碼定義

// radius int attribute.
typedef struct RadInt {
    unsigned char type;
    unsigned char length;
    char          value[4];
} RadInt;

#define RAD_ATTRSTR_LEN     253     /* Attribute (string) */
// radius string attribute.
typedef struct RadStr {
    unsigned char type;
    unsigned char length;
    char          value[RAD_ATTRSTR_LEN];
} RadStr; 

// radius structure attribute.
typedef struct AttrStru {
    unsigned char type;
    unsigned char length;
    char          iValue[1];
} AttrStru;

Radius 的 Attribute 的 Type 有如下幾種,不同的型別使用不同的編解碼器進行編解碼處理。

// Define Attribute and Value Type.
#define RAD_ATTR_TYPE_STRING     (0x01)
#define RAD_ATTR_TYPE_ADDRESS    (0x02)
#define RAD_ATTR_TYPE_INTEGER    (0x03)
#define RAD_ATTR_TYPE_TIME       (0x04)
#define RAD_ATTR_TYPE_ADDRESS6   (0x05)
#define RAD_ATTR_TYPE_FIX8       (0x06)
#define RAD_ATTR_TYPE_BINARY     (0x07)
#define RAD_ATTR_TYPE_IPV6PREFIX (0x08)
#define RAD_ATTR_TYPE_SECRET     (0x09)
#define RAD_ATTR_TYPE_UNKNOWNTP  (0x00)

 

認證計費的完整流程

認證失敗流程

 AAA 返回給 NAS認證拒絕時,流程結束 。

認證成功+計費流程

 AAA 返回給 NAS 認證成功時,NAS 會繼續發起計費開始報文,使用者下線時 NAS 發起計費結束報文,AAA 回覆計費相應報文。

認證請求報文(Authentication Request)

報文資料方向,NAS發起到AAA Radius Server

   +----------+      Auth-Request        +----------+
   |          |   -------------------->  |          |
   |   NAS    |                          |  RADIUS  |
   |          |     Auth-Response        |  Server  |
   |          |   <--------------------- |          |
   +----------+                          +----------+

Code取值:1

如下以華為的裝置為例說明認證請求報文:

 

 

認證通過響應報文(Authentication Accept)

報文資料方向,AAA Radius Server傳送認證通過給 NAS

   +----------+      Auth-Request        +----------+
   |          |   -------------------->  |          |
   |   NAS    |                          |  RADIUS  |
   |          |     Auth-Response        |  Server  |
   |          |   <--------------------- |          |
   +----------+                          +----------+

 

Code取值:2

如下是一個認證成功的響應報文例子:

 

 

通過驗證使用者的賬號和密碼,驗證方式優 PAP 和 CHAP, 對通過驗證的使用者,下發授權峰值頻寬,控制使用者的上網頻寬。

以華為裝置為例,AAA 會通過上網策略下發如下幾個屬性控制上網頻寬。

如下舉例說明,將上行頻寬設定為1M,下行頻寬設定為2M。

HW-Input-Peak-Rate 1048576
HW-Input-Average-Rate 1048576
HW-Input-Basic-Rate 1048576
HW-Output-Peak-Rate 2097152
HW-Output-Average-Rate 2097152
HW-Output-Basic-Rate 2097152

認證拒絕響應報文(Authentication Reject)

報文資料方向,AAA Radius Server傳送認證拒絕給 NAS

   +----------+      Auth-Request        +----------+
   |          |   -------------------->  |          |
   |   NAS    |                          |  RADIUS  |
   |          |     Auth-Response        |  Server  |
   |          |   <--------------------- |          |
   +----------+                          +----------+

Code取值:3 

通過PAP 和 CHAP方式驗證使用者的使用者名稱和加密密碼失敗時,AAA會返給NAS 一個認證拒絕報文。

如下是一個認證拒絕的響應報文例子:

 

 

計費請求報文(Accounting Request)

報文資料方向,NAS 傳送計費報文給AAA Radius Server

   +----------+      Acct-Request        +----------+
   |          |   -------------------->  |          |
   |   NAS    |                          |  RADIUS  |
   |          |     Acct-Response        |  Server  |
   |          |   <--------------------- |          |
   +----------+                          +----------+

 

Code取值:4

通過第一步中,NAS 發起認證請求到 AAA,AAA 認證通過給 NAS 後。

NAS 進行第二步的報文互動,NAS 發起計費開始報文請求到 AAA,AAA 計費響應報文給 NAS 。

注:計費報文的 Acct-Session-Id必須和第一步認證通過的 Acct-Session-Id 一致,說明本次計費是以認證成功的 Acct-Session-Id為計費物件。

使用者某一時間段的總流量是通過這個時間段內一個一個的 Acct-Session-Id上流量合併得到。

 

計費報文分三類:

  • 計費開始報文 Start
  • 計費保活報文 Keepalive
  • 計費結束報文 Stop

 

計費的開始報文Start

計費請求引數 Acct-Status-Type = 1

如下是一個計費開始報文的報文例子:

 

 

計費的結束報文Stop

 計費報文的Acct-Status-Type = 2

問題:運營商是如何統計一個寬頻賬號使用了多少流量呢?

運營商通過計費結束報文的Acct-Input-Octets統計上行流量,Acct-Output-Octets 統計下線流量,將這兩個流量相加得到使用者實際上網使用的流量是多少。

注:若使用者流量超過一定的額度,可以通過下次賬號登入後,下發授權峰值頻寬,控制使用者的上網頻寬。見認證響應通過報文。

 

如下是一個計費結束報文的報文例子:

 

 

 

計費響應報文(Accounting Response)

報文資料方向,AAA Radius Server傳送計費相應給 NAS

   +----------+      Acct-Request        +----------+
   |          |   -------------------->  |          |
   |   NAS    |                          |  RADIUS  |
   |          |     Acct-Response        |  Server  |
   |          |   <--------------------- |          |
   +----------+                          +----------+

 

Code取值:5

 如下是一個計費響應報文的報文例子:

 

 

DM踢使用者下線報文

 

   +----------+   Disconnect-Request     +----------+
   |          |   <--------------------  |          |
   |    NAS   |                          |  RADIUS  |
   |          |   Disconnect-Response    |  Server  |
   |          |   ---------------------> |          |
   +----------+                          +----------+

 

Code取值:請求40,響應成功41,響應失敗42

  40 - Disconnect-Request [RFC2882]
  41 - Disconnect-ACK [RFC2882]
  42 - Disconnect-NAK [RFC2882]
 
如下是一個 DM 的報文例子:

 

 

 注:在 DM 報文中比較重要的屬性是 Acct-Session-Id,即:要將使用者的哪個會話踢下線。

如下是一個 DM 的組包程式碼例子:

int DisconnectHuaWei(int argc, char **argv) {
    char radiusPacketBuffer[0xffff+1] = {0};
    memset(radiusPacketBuffer, 0, sizeof(radiusPacketBuffer));
    radiusPacketBuffer[0] = 40;
    gID = ++gID % 0xff;
    radiusPacketBuffer[1] = gID;
    int len = 20;
    // User-Name 1
    int tmpLen = strlen(argv[1]);
    sprintf(radiusPacketBuffer+len, "%c%c%s", 1, tmpLen+2, argv[1]);
    len += tmpLen+2;

    // Framed-Ip-Address 8
    unsigned int sin_addr;
    if(inet_pton(AF_INET, argv[2], &sin_addr) <= 0)
    {
        return TCL_ERROR;
    }
    // 轉換成網路套接字
    //sin_addr = htonl(sin_addr);
    radiusPacketBuffer[len++] = 8;
    radiusPacketBuffer[len++] = 6;
    memcpy(radiusPacketBuffer+len, &sin_addr, 4);
    len += 4;
    
    // NAS-IP-Address 4
    if(inet_pton(AF_INET, argv[4], &sin_addr) <= 0)
    {
        return ERROR;
    }
    // 轉換成網路套接字
    //sin_addr = htonl(sin_addr);
    radiusPacketBuffer[len++] = 4;
    radiusPacketBuffer[len++] = 6;
    memcpy(radiusPacketBuffer+len, &sin_addr, 4);
    len += 4;

    // Acct-Session-Id 44
    tmpLen = strlen(argv[3]);
    sprintf(radiusPacketBuffer+len, "%c%c%s", 44, tmpLen+2, argv[3]);
    len += tmpLen+2;

    radiusPacketBuffer[2] = len / 0xff;
    radiusPacketBuffer[3] = len % 0xff;

    unsigned char authen[17] = {0};
    int keyLen = strlen(brasSecureKey);
    memcpy(radiusPacketBuffer+len, brasSecureKey, keyLen);
    MD5Calc((unsigned char*)radiusPacketBuffer, len+keyLen, authen);
    memcpy(radiusPacketBuffer+4, authen, 16);
    return OK;
}

 

COA下發策略報文(修改上下行頻寬,即:網路提速)

   +----------+      CoA-Request         +----------+
   |          |  <--------------------   |          |
   |   NAS    |                          |  RADIUS  |
   |          |     CoA-Response         |  Server  |
   |          |   ---------------------> |          |
   +----------+                          +----------+

 

Code取值:請求43,響應成功44,響應失敗45

43 - CoA-Request [RFC2882]
44 - CoA-ACK [RFC2882]
45 - CoA-NAK [RFC2882]

COA 的請求包43

如下是一個 COA 報文例子:

 

注:在 COA 報文中比較重要的屬性是 Acct-Session-Id,即:要改變使用者的哪個會話上的屬性。

COA 可以做 Portal 登入重定向,修改上網頻寬等功能。

 

COA的回包44

 

如下是一個 COA 的組包程式碼例子

int OpenHUAWEI(int argc, char **argv) {    
    char radiusPacketBuffer[0xffff+1] = {0};
    memset(radiusPacketBuffer, 0, sizeof(radiusPacketBuffer));
    radiusPacketBuffer[0] = 43;
    gID = ++gID % 0xff;
    radiusPacketBuffer[1] = gID;
    int len = 20;
    // User-Name 1
    int tmpLen = strlen(argv[1]);
    sprintf(radiusPacketBuffer+len, "%c%c%s", 1, tmpLen+2, argv[1]);
    len += tmpLen+2;

    // Framed-Ip-Address 8
    unsigned int sin_addr;
    if(inet_pton(AF_INET, argv[2], &sin_addr) <= 0)
    {
        return ERROR;
    }
    // 轉換成網路套接字
    //sin_addr = htonl(sin_addr);
    radiusPacketBuffer[len++] = 8;
    radiusPacketBuffer[len++] = 6;
    memcpy(radiusPacketBuffer+len, &sin_addr, 4);
    len += 4;

    // Acct-Session-Id 44
    tmpLen = strlen(argv[3]);
    sprintf(radiusPacketBuffer+len, "%c%c%s", 44, tmpLen+2, argv[3]);
    len += tmpLen+2;

    // Huawei-HW-Portal-Mode 85
    radiusPacketBuffer[len++] = 0x1a;
    radiusPacketBuffer[len++] = 6+4+2;
    radiusPacketBuffer[len++] = HUAWEIVendor[0];
    radiusPacketBuffer[len++] = HUAWEIVendor[1];
    radiusPacketBuffer[len++] = HUAWEIVendor[2];
    radiusPacketBuffer[len++] = HUAWEIVendor[3];

    radiusPacketBuffer[len++] = 0x55;
    radiusPacketBuffer[len++] = 0x06;
    radiusPacketBuffer[len++] = 0x00;
    radiusPacketBuffer[len++] = 0x00;
    radiusPacketBuffer[len++] = 0x00;
    radiusPacketBuffer[len++] = 0x01;

    // Huawei-PortalURL 27
    tmpLen = strlen(argv[4]);
    radiusPacketBuffer[len++] = 0x1a;
    radiusPacketBuffer[len++] = tmpLen+2+4+2;
    radiusPacketBuffer[len++] = HUAWEIVendor[0];
    radiusPacketBuffer[len++] = HUAWEIVendor[1];
    radiusPacketBuffer[len++] = HUAWEIVendor[2];
    radiusPacketBuffer[len++] = HUAWEIVendor[3];

    sprintf(radiusPacketBuffer+len, "%c%c%s", 27, tmpLen+2, argv[4]);
    len += tmpLen+2;

    radiusPacketBuffer[2] = len / 0xff;
    radiusPacketBuffer[3] = len % 0xff;

    unsigned char authen[17] = {0};
    int keyLen = strlen(brasSecureKey);
    memcpy(radiusPacketBuffer+len, brasSecureKey, keyLen);
    MD5Calc((unsigned char*)radiusPacketBuffer, len+keyLen, authen);
    memcpy(radiusPacketBuffer+4, authen, 16);
    return OK;
}

 

26號私有屬性說明

不同的廠家使用的26號私有屬性各有不同,如下列舉國內運營商常用的廠家的26號屬性。

# 亞信 AsiaInfo extern Vendor Attrib
# Vendor 26, 999
#
# 愛立信 Ericsson extern Vendor Attrib
# Vendor 26, 2352
#
# 華為 HuaWei extern Vendor Attrib
# Vendor 26, 2011
#
# 中興 ZTE extern Vendor Attrib
# Vendor 26, 3902
#
# 貝爾 BELL-ALC extern Vendor Attrib
# Vendor 26, 6527
#
# 海蜘蛛 HISPIDER extern Vendor Attrib
# Vendor 26, 16010

# ...

 

參考材料:

認證報文RFC參考 RFC2865: https://www.rfc-editor.org/rfc/rfc2865

計費報文RFC參考 RFC2866:https://www.rfc-editor.org/rfc/rfc2866

動態授權(DM和COA)RFC參考 RFC3576:https://www.rfc-editor.org/rfc/rfc3576

認證請求的CHAP參考:https://www.cnblogs.com/voipman/p/5047912.html

認證請求報文的PAP參考:https://www.cnblogs.com/voipman/p/5345320.html

PPPoE的參考:https://www.cnblogs.com/voipman/p/pppoe.html 

相關文章