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_cache,rend_cache_v2_dir;
addressmap_init(),初始化地址映射addressmap,virtaddress_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.