所谓的Edge连接主要是形容在链路两端所使用的连接,包括AP连接与EXIT连接两种。Edge连接的存在,主要是为了个应用程序连接提供服务,所以才将两种Edge连接命名为Application Proxy应用代理连接和EXIT出口连接。这两种连接主要出现于链路两端,即链路第一跳与链路最后一跳,分别用于接受应用请求和处理应用请求的发出。因为Edge连接在Tor系统中也具有重要的作用,所以本篇就简单分析关于Edge连接的源码文件connection_edge.c。
因为Edge连接位于链路两端,需要处理的事务比中间结点单纯的传递和记录要繁琐出许多,有很多部分笔者也没有很详细的看过或找出其应用需要,此处必定有很多讲的含糊其辞和不准确的地方,请大家包涵。
0. 全局变量
/** A client-side struct to remember requests to rewrite addresses
* to new addresses. These structs are stored in the hash table
* "addressmap" below.
* 由此处可见,addressmap全局变量的使用,只存在于客户端,其他身份的TOR成员并不使用此全局变量;
*
* There are 5 ways to set an address mapping:
* - A MapAddress command from the controller [permanent]
* - An AddressMap directive in the torrc [permanent]
* - When a TrackHostExits torrc directive is triggered [temporary]
* - When a DNS resolve succeeds [temporary]
* - When a DNS resolve fails [temporary]
* 由此处可见,除去在配置文件中进行地址映射之外,主要还是靠DNS解析来修改address mapping;
*
* When an addressmap request is made but one is already registered,
* the new one is replaced only if the currently registered one has
* no "new_address" (that is, it's in the process of DNS resolve),
* or if the new one is permanent (expires==0 or 1).
*
* (We overload the 'expires' field, using "0" for mappings set via
* the configuration file, "1" for mappings set from the control
* interface, and other values for DNS and TrackHostExit mappings that can
* expire.)
*
* A mapping may be 'wildcarded'. If "src_wildcard" is true, then
* any address that ends with a . followed by the key for this entry will
* get remapped by it. If "dst_wildcard" is also true, then only the
* matching suffix of such addresses will get replaced by new_address.
*/
typedef struct {
char *new_address;
time_t expires;
addressmap_entry_source_t source:3;
unsigned src_wildcard:1;
unsigned dst_wildcard:1;
short num_resolve_failures;
} addressmap_entry_t;
/** Entry for mapping addresses to which virtual address we mapped them to. */
typedef struct {
char *ipv4_address;
char *hostname_address;
} virtaddress_entry_t;
/** A hash table to store client-side address rewrite instructions. */
static strmap_t *addressmap=NULL;
/**
* Table mapping addresses to which virtual address, if any, we
* assigned them to.
*
* We maintain the following invariant: if [A,B] is in
* virtaddress_reversemap, then B must be a virtual address, and [A,B]
* must be in addressmap. We do not require that the converse hold:
* if it fails, then we could end up mapping two virtual addresses to
* the same address, which is no disaster.
**/
static strmap_t *virtaddress_reversemap=NULL;
此处两全局变量的作用尚不明确,有待分析。
/* By default, we hand out 127.192.0.1 through 127.254.254.254.
* These addresses should map to localhost, so even if the
* application accidentally tried to connect to them directly (not
* via Tor), it wouldn't get too far astray.
*
* These options are configured by parse_virtual_addr_network().
*/
/** Which network should we use for virtual IPv4 addresses? Only the first
* bits of this value are fixed. */
static uint32_t virtual_addr_network = 0x7fc00000u;
/** How many bits of virtual_addr_network are fixed? */
static maskbits_t virtual_addr_netmask_bits = 10;
/** What's the next virtual address we will hand out? */
static uint32_t next_virtual_addr = 0x7fc00000u;
此处三全局变量的作用尚不明确,有待分析。
1. AP与EXIT通用函数
connection_edge_reached_eof –> connection_edge_end
断开连接,如果身份正确(AP)则发送end cell通知对应出口结点关闭数据流;
connection_edge_process_inbuf
分情况管理连接事务及连接缓冲区内部的数据;
connection_edge_destroy –> connection_mark_unattached_ap(若身份为AP)
connection_edge_end_errno –> connection_edge_end
连接因链路断开而结束或因某个errno而结束,则关闭连接,发送流终止通知;
connection_edge_flushed_some
connection_edge_finished_flushing
connection_edge_finished_connecting(主要用于身份为EXIT的情况)
连接完成缓冲区输出或完成下层连接之时调用相关函数,以完成扫尾工作;
connection_edge_is_rendezvous_stream
connection_edge_compatible_with_circuit
connection_edge_update_circuit_isolation
circuit_clear_isolation
连接的某些属性判断,关键点在于rendezvous子系统和isolation flag作用;
2. AP处理函数
connection_mark_unattached_ap
connection_ap_about_to_close
AP连接关闭前的处理以及关闭处理;
connection_ap_handshake_send_begin
connection_ap_handshake_send_resolve
AP连接向远端发送Relay Begin以及Relay Resolve命令,用于完成开启流与地址解析的功能;
connection_ap_make_link
一般用于内部DIR连接与AP连接相关联之时,该函数创建一个可用的AP连接,并将其与DIR连接互联;可用意味着AP连接找到附着的链路Circuit;
connection_ap_handshake_socks_reply
connection_ap_handshake_socks_resolved
向AP连接送回相关消息:连接结束消息,地址解析成功消息;
connection_ap_can_use_exit
判断出口结点是否允许相应AP连接出口;
connection_ap_expire_beginning
connection_ap_attach_pending
connection_ap_detach_retriable
重连一个请求超时的AP连接;重新为找不到链路的AP连接分配链路;
connection_ap_fail_onehop
通知所有等待某个无法连接的结点的AP连接;
connection_ap_process_transparent –> connection_ap_rewrite_and_attach_if_allowed –> connection_ap_handshake_rewrite_and_attach
透明AP使用的函数,未细究;
3. EXIT处理函数
connection_exit_about_to_close
connection_exit_begin_conn –> connection_exit_connect
connection_exit_begin_resolve
以上四个函数包括了EXIT连接的几乎所有操作,主要就是连接的建立与对外的连接,以及地址解析和关闭;
4. AddressMap相关处理函数(暂略)
address_is_invalid_destination
parse_virtual_addr_network
parse_extended_hostname
addressmap_init
addressmap_clear_excluded_trackexithosts
addressmap_clear_invalid_automaps
addressmap_clean
addressmap_clear_configured
addressmap_clear_transient
addressmap_free_all
addressmap_rewrite
addressmap_have_mapping
addressmap_register
addressmap_register_virtual_address
addressmap_get_mappings
client_dns_incr_failures
client_dns_clear_failures
client_dns_set_addressmap
5. 额外函数(暂略)
circuit_discard_optional_exit_enclaves
get_pf_socket