1. 程式人生 > >FreeRadius : 模組開發(一)

FreeRadius : 模組開發(一)

這篇文章主要總結一些模組開發的基礎知識。

引文是為FreeRadius3.X增加一個模組的幫助文件,在這裡做一些翻譯。

doc/developer

給開發者的文件,對與模組開發的說明在這裡:

伺服器的職責

這個文件首先說明了Freeradius伺服器主要工作。Freeradius伺服器就是一個認證伺服器(AAA伺服器,認證、授權、計帳),它只做如下工作:

  • 獲取一個RADIUS request
    • 處理該request
    • 在database中查詢資訊
  • 將資訊儲存在database中
  • 返回一個response

所以Freerasdius不需定時器等其他複雜的設計,因為那樣會讓伺服器不穩定、不安全、不易維護。(KISS原則即視感)

一些思考:看到這裡感覺FR就是在TCP/IP的基礎上,進行分包的處理:接收一個請求request包;分析這個包;處理邏輯;返回響應response。
伺服器的業務邏輯重點就是分包的處理。底層的IO由網路庫來支援好,那麼程式設計師的工作效率會有所提高吧。muduo網路庫、handy網路庫是C++網路庫,libevent是C網路庫,應該感謝這些作者。

模組簡介

一個模組由若干元件構成:

  • authorization(授權):檢查使用者是否存在,確定一個認證過程,設定一些response中的attribute
  • authentication(認證):驗證密碼是否正確
  • accounting(計帳): 將request記錄在log中

A module declares which components it supports by putting function pointers in its “module_dl_t rlm_*” structure.

元件其實就是函式,也就是說一個模組需要實現一些特定的函式,供FR呼叫。這些函式的指標存放在一個叫modult_t的結構中。

模組的配置

要想使用某個模組,需要在radiusd.conf中的modules{}塊中新增該模組的例項:

module_name [instance_name] {
  param1 = value1
  param2 = value2
  param3 = value3
  ...
}

module_name可以在安裝目錄下的lib資料夾中查詢,我的安裝目錄是/usr/local,因此/usr/local/lib下包含所有安裝的模組,名字為rlm_xxx.so

instance_name用於區分同一個module的不同例項,如果只有一個例項可以忽略不寫。

param是模組定義的引數,通常是指定database的位置、開啟某些功能。它們由伺服器直接傳遞給模組。

當伺服器接收到一個Access-Request時,authorize{} 塊被呼叫(它會選定某種Auth-Type),然後authenticate{}中的對應的Auth-Type{}塊被呼叫。最後post-auth{}塊被呼叫。

模組的生命週期

當伺服器啟動時或接收到SIGHUP而重新初始化時,伺服器會讀取modules{}塊,在該塊中的module會被載入,並且它的init()方法會被呼叫。(沒明白init)

接著module的instantiate()被呼叫,server會給該函式傳遞兩個引數:

  • CONF_SECTION *cs:通過cs可以訪問到在前面設定的模組引數等。
  • void *instance : 該模組例項的指標。
int instantiate(CONF_SECTION *cs, void *instance)

模組的authorize(), authenticate(), preaccounting(), and accounting()也以同樣的方式被呼叫,它們的原型如下所示:

int authorize(void *instance, REQUEST *request)
int authenticate(void *instance, REQUEST *request)
int preaccounting(void *instance, REQUEST *request)
int accounting(void *instance, REQUEST *request)

instance與上面相同,是模組的handle,request則代表請求。它們會使用instance中儲存的database來處理該request。

當伺服器關閉時,模組的detach被呼叫,它會釋放在instantiate中獲取的資源。當一個模組的所有例項被detached了,模組的destroy被呼叫,它釋放在init中獲取的資源。

src/modules/stable

將模組名字新增到這個檔案中,模組會被編譯。

伺服器處理流程

FreeRADIUS uses a thread pool to serve requests. Each request is processed
synchronously, and processing passes through a series of stages, and a list
of modules in each stage.

The request is processed as follows

  • The radius packet is received by a listener - see listen.c
  • The radius packet is parsed and validated into a request - see ?
  • The request is processed - see process.c
  • The server passes through each authentication stage
    • authorize
    • if Proxy-To-Realm is set:
    • pre-proxy
    • send proxy request
    • post-proxy
    • else
    • authenticate
    • post-auth
  • Authentication stages are lists of modules - see modcall.c