Tor源碼分析三 -- 客戶端執行流程(初始化)

  Tor系統中,主機的身份包括有這幾種:Client,Bridge Server,Relay Server,Directory Server。

  當然,有的時候一臺主機是可以身兼數個身份,提供不同的服務或獲取服務。

  我們從最簡單的客戶端配置的Tor來進行分析,事先了解整個Tor系統的執行規程,之後再具體分析其他身份時候的不同操作,從而加快了解系統的速度。此處要說明的是,由於筆者對Windows的編程不甚瞭解,暫時就去除源碼中所有爲了讓Tor系統具有誇平臺性的Windows代碼部分。


1. Tor系統的入口函數

  大部分源程序的入口函數是main。Tor系統爲了實現更加簡便的單元測試,將main函數設爲調用tor_main函數,後者是整個Tor系統的執行主函數。上述關係可以在Tor_main.c文件中看到,該文件中只是用很少的幾行描述了main與tor_main之間的關係。


2. Tor系統初始化

  系統初始化包括四個函數:

  1)update_approx_time(time(NULL))

    記錄當前時間的估值,存於cached_approx_time,一般每秒鐘被系統其它部分調用一次。在系統開始運行時,最先執行。

  2)tor_threads_init()

    根據Tor系統是否被允許是多線程運行而執行不同的操作。

    若不允許多線程運行,則不做操作;

    若允許,記錄main_thread_id,並根據系統的平臺,設置thread_initialized標籤以及對多線程參數進行初始化。

  3)init_logging()

    初始化系統日誌信息列表。

    初始化對log進行操作的互斥量log_mutex,設置log_mutex_initialized標籤。在系統剛剛啓動時,會新建log日誌消息鏈表pending_cb_message

    注:smartlist是Tor系統實現的一個鏈表系統,可以執行基本鏈表操作等。

  4)tor_init()

    系統最主要的初始化函數。

    i)初始化系統最重要的幾個全局變量:

       time_of_process_start,進程開始真正運行的時間;

       connection_array,系統所有連接鏈表,連接包括DIR, AP, OR, EXIT等類型的連接;

       closeable_connection_lst,系統所有要關閉的連接鏈表;

       active_linked_connection_lst系統所有活動的linked連接鏈表,linked連接包括DIR, AP等類型的連接。

    ii)輸出調試信息和設置應用程序名appname

    iii)初始化三個子功能件:

       rep_hist_init(),reputation history初始化,包括摘要映射表history_map,帶寬數組bw_array,預測端口predicted_ports_list等初始化;

       rend_cache_init(),初始化服務描述符緩存rend_cacherend_cache_v2_dir

       addressmap_init(),初始化地址映射addressmapvirtaddress_reversemap

    iv)通過tor配置文件及命令行參數初始化tor系統,生成全局選項變量global_options;options_init_from_torrc()(非常重要,讀者要自行詳細分析)

       開啓系統監聽的端口;生成Lock與State文件;解析固化在系統代碼內的10個目錄服務器地址;解析GeoIp文件;執行其他相關操作。

    v)初始化OpenSSL:crypto_global_init()(略)


3. option_init_from_torrc()函數解析

  該函數指定了Tor運行的執行操作:CMD_RUN_TOR,CMD_LIST_FINGERPRINT,CMD_VERIFY_CONFIG,CMD_HASH_PASSWORD。

  其中,CMD_RUN_TOR是Tor系統真正的執行命令。當輸入的參數argv不存在上述後面三個命令之時,系統默認執行Tor主線命令,啓動Tor系統。

  而在系統啓動之前,還需要進行默認配置文件,輸入配置文件以及命令參數的綜合解析,所以該函數中出現以下執行代碼:

    1)cf_default = load_torrc_from_disk(argc, argv, 1);讀取默認配置文件中的配置參數,輸出爲整個字符串。

    2)cf = load_torrc_from_disk(argc, argv, 0);讀取命令行輸入的配置文件的配置參數,輸出爲整個字符串。

    3)options_init_from_string(cf_default, cf, command, command_arg, &errmsg);利用輸入的所有配置參數初步啓動系統。

      cf = config;cf_default = config default;

      command = 系統主命令;command_arg = 系統主命令參數,其實就是一般的命令行輸入參數;errmsg爲錯誤輸出消息。

  該函數的重點,在於調用了options_init_from_string()函數,從而往下調用到set_options()函數,而後又深層調用到了options_act_reversible()和options_act()。上述深層調用到的函數,會很細節地初始化Tor系統的大多部分,此處就不再贅述。另外關於配置,不得不提的是:默認配置,輸入配置文件以及命令行的配置,三個配置之間的選擇規則,是三者的優先級逐級遞增。也就是說,輸入配置文件的配置會先覆蓋默認配置文件的配置,命令行的配置會再次覆蓋輸入配置文件的配置。實際上這個部分還有更復雜的規則,具體細則,可以參看Tor Manual的詳細說明。此處就黏貼如下,不再翻譯:

  By default, an option on the command line overrides an option found in the configuration file, and an option in a configuration file overrides one in the defaults file.

  This rule is simple for options that take a single value, but it can become complicated for options that are allowed to occur more than once: if you specify four SOCKSPorts in your configuration file, and one more SOCKSPort on the command line, the option on the command line will replace all of the SOCKSPorts in the configuration file. If this isn’t what you want, prefix the option name with a plus sign, and it will be appended to the previous set of options instead.

  Alternatively, you might want to remove every instance of an option in the configuration file, and not replace it at all: you might want to say on the command line that you want no SOCKSPorts at all. To do that, prefix the option name with a forward slash.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章