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_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的详细说明。此处就黏贴如下,不再翻译: