10、udprelay,实现udp的转达,用于local端处理local和客户端的socks5协议通信,用于local端和远程端shadowsocks协议的通信;用于远程端与local端shadowsocks协议的通信,用于远程端和dest端的通信
代码质量相当的高,感觉都能达到重用的级别。而且由于作者设计的思想是,一个配置文件,同一段程序,在本地和远程通用,所以其中的代码,常常能够达到一个函数,在本地和服务器有不同的功能这样的效果。
===============================================================
eventloop使用select、epoll、kqueue等IO复用实现异步处理。优先级为epoll>kqueue>select。Eventloop将三种复用机制的add,remove,poll,add_handler,remve_handler接口统一起来,程序员只需要使用这些函数即可,不需要处理底层细节。
后三个文件分别实现用来处理udp的请求,tcp的请求,dns的查询请求,并且将三种请求的处理包装成handler。对于tcp,udp的handler,它们bind到特定的端口,并且将socket交给eventloop,并且将自己的处理函数加到eventloop的handlers;对于dns的handler,它接受来自udp handler和tcp handler的dns查询请求,并且向远程dns服务器发出udp请求;
当eventloop监测到socket的数据,程序就将所有监测到的socket和事件交给所有handler去处理,每个handler通过socket和事件判断自己是否要处理该事件,并进行相对的处理:
+----+------+------+----------+----------+----------+ |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | +----+------+------+----------+----------+----------+ | 2 | 1 | 1 | Variable | 2 | Variable | +----+------+------+----------+----------+----------+
trim->
+------+----------+----------+----------+ | ATYP | DST.ADDR | DST.PORT | DATA | +------+----------+----------+----------+ | 1 | Variable | 2 | Variable | +------+----------+----------+----------+
->encrypt
+-------+--------------+ | IV | PAYLOAD | +-------+--------------+ | Fixed | Variable | +-------+--------------+
+-------+--------------+ | IV | PAYLOAD | +-------+--------------+ | Fixed | Variable | +-------+--------------+
->decrypt
+------+----------+----------+----------+ | ATYP | DST.ADDR | DST.PORT | DATA | +------+----------+----------+----------+ | 1 | Variable | 2 | Variable | +------+----------+----------+----------+
->add
+----+------+------+----------+----------+----------+ |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | +----+------+------+----------+----------+----------+ | 2 | 1 | 1 | Variable | 2 | Variable | +----+------+------+----------+----------+----------+
+-------+--------------+ | IV | PAYLOAD | +-------+--------------+ | Fixed | Variable | +-------+--------------+
->decrypt
+------+----------+----------+----------+ | ATYP | DST.ADDR | DST.PORT | DATA | +------+----------+----------+----------+ | 1 | Variable | 2 | Variable | +------+----------+----------+----------+
->trim
+----------+ | DATA | +----------+ | Variable | +----------+
->getaddrinfo->tcp/udp ->send to dest server via tcp/udp
+----------+ | DATA | +----------+ | Variable | +----------+
->add
+------+----------+----------+----------+ | ATYP | DST.ADDR | DST.PORT | DATA | +------+----------+----------+----------+ | 1 | Variable | 2 | Variable | +------+----------+----------+----------+
->encrypt
+-------+--------------+ | IV | PAYLOAD | +-------+--------------+ | Fixed | Variable | +-------+--------------+
->send to local
在handler函数里面的基本逻辑就是:
if sock == self._server_socket: self._handle_server() elif sock and (fd in self._sockets): self._handle_client(sock)
协议解析和构建用的struct.pack()和struct.unpack()
===============================================================
1.1、读取/etc/hosts和/etc/resolv.conf文件,如果没有设置,就设置dns服务器为8.8.8.8和8.8.4.4 1.2、收到tcp handler和udp handler的dns请求之后,建立socket并且向远程服务器发送请求,并把(hostname:callback)加入_hostname_to_cb 1.3、收到响应之后触发callback _hostname_to_cbhostname
# 请求 # 1 1 1 1 1 1 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # | ID | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # |QR| Opcode |AA|TC|RD|RA| Z | RCODE | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # | QDCOUNT | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # | ANCOUNT | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # | NSCOUNT | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ # | ARCOUNT | # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
响应:
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
===============================================================
self._store = self._time_to_keys = collections.defaultdict(list) self._keys_to_last_time = self._last_visits = collections.deque()
===============================================================
一些问题: