def _handle_remote(self, sock): try: data, addr = sock.recvfrom(BUF_SIZE) except (OSError, IOError) as e: logging.error(e) if eventloop.errno_from_exception(e) == errno.ECONNRESET: # just for Windows lol self._rebuild_sockets() return if data: try: header = asyncdns.parse_header(data) if header: req_id = header[0] res = asyncdns.parse_response(data) logging.info('response %s', res) addr = self._id_to_addr.get(req_id, None) if addr: for answer in res.answers: if answer and answer[0] in GFW_LIST: return self._local_sock.sendto(data, addr) del self._id_to_addr[req_id] except Exception as e: import traceback traceback.print_exc() logging.error(e) if eventloop.errno_from_exception(e) == errno.EACCES: # when we have changed our ip self._rebuild_sockets()
def _handle_stage_reply(self, data): if self._is_local: data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) if self._is_local and not self._fastopen_connected and \ self._config['fast_open']: try: self._fastopen_connected = True remote_sock = \ self._create_remote_socket(self._chosen_server[0], self._chosen_server[1]) self._loop.add(remote_sock, eventloop.POLL_ERR) data = b''.join(self._data_to_write_to_local) l = len(data) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) if s < l: data = data[s:] self._data_to_write_to_local = [data] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) else: self._data_to_write_to_local = [] self._update_stream(STREAM_UP, WAIT_STATUS_READING) self._stage = STAGE_STREAM except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) elif eventloop.errno_from_exception(e) == errno.ENOTCONN: logging.error('fast open not supported on this OS') self._config['fast_open'] = False self.destroy() else: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_stage_connecting(self, data): if self._is_local: data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) if self._is_local and not self._fastopen_connected and self._config["fast_open"]: # for sslocal and fastopen, we basically wait for data and use # sendto to connect try: # only connect once self._fastopen_connected = True remote_sock = self._create_remote_socket(self._chosen_server[0], self._chosen_server[1]) self._loop.add(remote_sock, eventloop.POLL_ERR) data = b"".join(self._data_to_write_to_remote) l = len(data) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) if s < l: data = data[s:] self._data_to_write_to_remote = [data] else: self._data_to_write_to_remote = [] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: # in this case data is not sent at all self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) elif eventloop.errno_from_exception(e) == errno.ENOTCONN: logging.error("fast open not supported on this OS") self._config["fast_open"] = False self.destroy() else: logging.error(e) if self._config["verbose"]: traceback.print_exc() self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage self._update_activity() if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b"\x05\00", self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _handle_conn(self, sock): try: local, addr = sock.accept() addrs = socket.getaddrinfo(self._remote_addr[0], self._remote_addr[1], 0, socket.SOCK_STREAM, socket.SOL_TCP) if len(addrs) == 0: raise Exception("can't get addrinfo for %s:%d" % self._remote_addr) af, socktype, proto, canonname, sa = addrs[0] remote = socket.socket(af, socktype, proto) local.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) remote.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) self._local_to_remote[local] = remote self._remote_to_local[remote] = local self._loop.add(local, 0) self._loop.add(remote, eventloop.POLL_OUT) try: remote.connect(self._remote_addr) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in (errno.EINPROGRESS, errno.EAGAIN): pass else: raise except (OSError, IOError) as e: logging.error(e)
def main(): logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') parser = argparse.ArgumentParser(description='Forward DNS requests.') parser.add_argument('-b', '--local_address', metavar='BIND_ADDR', type=str, help='address that listens, default: 127.0.0.1', default='127.0.0.1') parser.add_argument('-p', '--local_port', metavar='BIND_PORT', type=int, help='port that listens, default: 53', default=53) parser.add_argument('-s', '--dns', metavar='DNS', type=str, help='DNS server to use, default: ' '114.114.114.114,208.67.222.222,8.8.8.8', default='114.114.114.114,208.67.222.222,8.8.8.8') config = vars(parser.parse_args()) logging.info("starting dns at %s:%d", config['local_address'], config['local_port']) loop = eventloop.EventLoop() try: udprelay = UDPDNSRelay(config) udprelay.add_to_loop(loop) tcprelay = TCPDNSRelay(config) tcprelay.add_to_loop(loop) loop.run() except (OSError, IOError) as e: logging.error(e) if eventloop.errno_from_exception(e) == errno.EACCES: logging.info('please use sudo to run this program') sys.exit(1)
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: self._handle_stage_init(data) elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _on_remote_read(self): # handle all remote read events data = None try: data = self._remote_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if self._is_local: data = self._encryptor.decrypt(data) else: data = self._encryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def handle_event(self, sock, fd, event): # handle events and dispatch to handlers if sock: logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() else: if sock: handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn('poll removed fd')
def _on_local_read(self): self._update_activity() if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_HELLO return elif self._stage == STAGE_REPLY: self._handle_stage_reply(data) elif (is_local and self._stage == STAGE_HELLO) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_hello(data)
def _on_remote_read(self): logging.debug("Running in the TCPRelayHandler class. [_on_remote_read]") # handle all remote read events data = None try: data = self._remote_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if self._is_local: data = self._encryptor.decrypt(data) else: data = self._encryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) # if not self._is_local: # if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']): # port_limits = json.loads(open(self._config['port_limit']).read()) # if str(self._server._listen_port) in port_limits: # port_limits['%s' % self._server._listen_port]['used'] = port_limits['%s' % self._server._listen_port]['used'] + len(data) + BUF_SIZE # open('%s' % self._config['port_limit'],"w").write("%s" % json.dumps(port_limits,indent=4,ensure_ascii=False,sort_keys=True)) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _on_remote_read(self): logging.debug('on remote read') # handle all remote read events data = None try: data = self._remote_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if self._is_local: data = self._encryptor.decrypt(data) else: # logging.debug('received data:[%s]' % data) # data = 'HTTP/1.1 302 Found\nLocation: https://ashadowsocks.com/' data = self._encryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _handle_local(self, sock): try: data, addr = sock.recvfrom(BUF_SIZE) except (OSError, IOError) as e: logging.error(e) if eventloop.errno_from_exception(e) == errno.ECONNRESET: # just for Windows lol self._rebuild_sockets() return header = asyncdns.parse_header(data) if header: try: req_id = header[0] req = asyncdns.parse_response(data) logging.info('--- request %s', req.hostname) if req.hostname in self._hosts: response = self.build_response(data, self._hosts[req.hostname]) if response: logging.info('%s hit /etc/hosts', req.hostname) self._local_sock.sendto(response, addr) return self._id_to_addr[req_id] = addr for remote_addr in self._remote_addrs: self._remote_sock.sendto(data, remote_addr) except Exception as e: import traceback traceback.print_exc() logging.error(e)
def _handle_stage_connecting(self, data): # 如果是本地端,加密数据 if self._is_local: data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) # 若本地端设置了fast_open却没有fast_open连接 if self._is_local and not self._fastopen_connected and \ self._config['fast_open']: # for sslocal and fastopen, we basically wait for data and use # sendto to connect try: # only connect once self._fastopen_connected = True remote_sock = \ self._create_remote_socket(self._chosen_server[0], self._chosen_server[1]) self._loop.add(remote_sock, eventloop.POLL_ERR) # 发送二进制流 data = b''.join(self._data_to_write_to_local) l = len(data) # 发送给服务端 s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) # 若发送尚未完成,转入读写状态 if s < l: data = data[s:] self._data_to_write_to_local = [data] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) # 发送完毕,转入读状态 else: self._data_to_write_to_local = [] self._update_stream(STREAM_UP, WAIT_STATUS_READING) self._stage = STAGE_STREAM except (OSError, IOError) as e: # EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成,常见于非阻塞的socket连接中 # stream流状态更新为读写 if eventloop.errno_from_exception(e) == errno.EINPROGRESS: self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) # ENOTCONN指定的socket是一个未连接成功的socket elif eventloop.errno_from_exception(e) == errno.ENOTCONN: logging.error('fast open not supported on this OS') self._config['fast_open'] = False self.destroy() else: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_stage_connecting(self, data): # further process data # encrypt it and add to buffer if self._is_local: data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) # for fastopen, we basically # wait for data and use sendto to connect # only connect once if self._is_local and not self._fastopen_connected and \ self._config['fast_open']: try: self._fastopen_connected = True # 1. create _remote_sock # 2. add it to eventloop, set event as ERR # 3. send data to ssremote # 4. reset buffer with unsent data # 5. sslocal relays up stream remote_sock = \ self._create_remote_socket(self._chosen_server[0], self._chosen_server[1]) self._loop.add(remote_sock, eventloop.POLL_ERR, self._server) data = b''.join(self._data_to_write_to_remote) l = len(data) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) if s < l: data = data[s:] self._data_to_write_to_remote = [data] else: self._data_to_write_to_remote = [] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) elif eventloop.errno_from_exception(e) == errno.ENOTCONN: logging.error('fast open not supported on this OS') self._config['fast_open'] = False self.destroy() else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _write_to_sock(self, data, sock): logging.debug("Running in the TCPRelayHandler class. [_write_to_sock]") # write data to sock # if only some of the data are written, put remaining in the buffer # and update the stream to wait for writing if not data or not sock: return False uncomplete = False try: l = len(data) if sock == self._local_sock and self._is_local and self._stage == STAGE_INIT: logging.info("[Client] Received data from browser and just sending 'hello' back to [browser] ! data length is: [%s]" % l) elif sock == self._remote_sock and self._is_local and self._stage == STAGE_STREAM: logging.info("[Client] Received data from browser and just sending -encrypted- data to [VPS] ! data length is: [%s]" % l) elif sock == self._local_sock and self._is_local and self._stage == STAGE_STREAM: logging.info("[Client] Received data from VPS and just sending -decrypted- data to [browser] ! data length is: [%s]" % l) elif sock == self._remote_sock and not self._is_local and self._stage == STAGE_STREAM: logging.info("[Server] Received data from client and going to send -decrypted- data to [INTERNET] ! data length is: [%s]" % l) elif sock == self._local_sock and not self._is_local and self._stage == STAGE_STREAM: logging.info("[Server] Received data from INTERNET and going to send -encrypted- data to [client] ! data length is: [%s]" % l) if not self._is_local: if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']): port_limits = json.loads(open(self._config['port_limit']).read()) if str(self._server._listen_port) in port_limits: port_limits['%s' % self._server._listen_port]['used'] = port_limits['%s' % self._server._listen_port]['used'] + len(data) open('%s' % self._config['port_limit'],"w").write("%s" % json.dumps(port_limits,indent=4,ensure_ascii=False,sort_keys=True)) s = sock.send(data) if s < l: data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True else: shell.print_exception(e) self.destroy() return False if uncomplete: if sock == self._local_sock: self._data_to_write_to_local.append(data) self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) elif sock == self._remote_sock: self._data_to_write_to_remote.append(data) self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) else: logging.error('write_all_to_sock:unknown socket') common.error_to_file('write_all_to_sock:unknown socket',self._config) else: if sock == self._local_sock: self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) elif sock == self._remote_sock: self._update_stream(STREAM_UP, WAIT_STATUS_READING) else: logging.error('write_all_to_sock:unknown socket') common.error_to_file('write_all_to_sock:unknown socket',self._config) return True
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: if sock: # log级别是怎么显示出来的,平常都是INFO级别的消息? logging.log(utils.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) # 若来自服务端的数据 if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() # 创建一个新的连接,并且新建一个TCPRelayHandler处理 # Handler函数包含解密、dns解析等一系列的操作。 TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): continue # 继续进行for循环。 else: logging.error(e) if self._config['verbose']: traceback.print_exc() # 来自本地socket(1080端口)的数据 else: if sock: # 如果是已经accept的连接,就找相对应的handler处理它 handler = self._fd_to_handlers.get(fd, None) if handler: # 这里调用handler里面的handle_event来处理事件 handler.handle_event(sock, event) else: logging.warn('poll removed fd') now = time.time() # 超时,清理socket。 if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: # 移除当前的socket文件描述符 self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) # 移除服务函数。 if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _write_to_sock(self, data, sock): # write data to sock # if only some of the data are written, put remaining in the buffer # and update the stream to wait for writing # 写入数据到套接字,如果只有部分数据被写入,继续写入剩下的数据到缓冲区,并更新流方向为‘等待’ if not data or not sock: return False uncomplete = False try: l = len(data) s = sock.send(data) if s < l: # 返回list的切片,应该不是浅复制 data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True else: logging.error(e) # 哆嗦模式 if self._config['verbose']: traceback.print_exc() # 断开连接 self.destroy() # 尚未发送完毕 return False # 尚未完成发送数据 if uncomplete: if sock == self._local_sock: # 暂存数据,使用append追加 self._data_to_write_to_local.append(data) # 更新流的状态:等待写入,方向为‘服务端->本地’ self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) elif sock == self._remote_sock: # 跟上面一样的方法,追加数据,修改stream状态。 self._data_to_write_to_remote.append(data) # 方向‘本地->服务端’ self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) else: logging.error('write_all_to_sock:unknown socket') # 已经完成发送数据 else: if sock == self._local_sock: # 修改流的状态为等待读,方向为‘服务端->本地’ self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) elif sock == self._remote_sock: # 方向为‘本地->服务端’ self._update_stream(STREAM_UP, WAIT_STATUS_READING) else: logging.error('write_all_to_sock:unknown socket') # 函数执行完毕,不一定说明数据发送完毕,return true return True
def _handle_dns_resolved(self, result, error): if error: self._log_error(error) self.destroy() return # when domain name is resolved if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip # port is not included in the result if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] # for fastopen sslocal: # sslocal reads from client if self._is_local and self._config['fast_open']: self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet # for non-fastopen sslocal, # 1. connect to ssremote, add to loop, set event as ERR|OUT # 2. sslocal relays up stream # for ssremote, # 1. connect to dest, add to loop, set event as ERR|OUT # 2. ssremote reads from dest else: remote_sock = self._create_remote_socket(remote_addr, remote_port) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_dns_resolved(self, result, error): """ DNS请求解析完成后调用该函数 result: (addr, ip) error: error """ if error: self._log_error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip # 若为sslocal,则remote_socket连接的端口为初始化文件中的服务器端口 # 若为ssserver,则remote_socket连接的端口为解析出的remote_address的地址 if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket(remote_addr, remote_port) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_dns_resolved(self, result, error): if error: self._log_error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config["fast_open"]: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket(remote_addr, remote_port) if self._remote_udp: self._loop.add(remote_sock, eventloop.POLL_IN, self._server) if self._remote_sock_v6: self._loop.add(self._remote_sock_v6, eventloop.POLL_IN, self._server) else: try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) if self._remote_udp: while self._data_to_write_to_remote: data = self._data_to_write_to_remote[0] del self._data_to_write_to_remote[0] self._write_to_sock(data, self._remote_sock) return except Exception as e: shell.print_exception(e) if self._config["verbose"]: traceback.print_exc() self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return ogn_data = data self._update_activity(len(data)) if not is_local: if self._encrypt_correct: obfs_decode = self._obfs.server_decode(data) if obfs_decode[2]: self._write_to_sock(b'', self._local_sock) if obfs_decode[1]: data = self._encryptor.decrypt(obfs_decode[0]) else: data = obfs_decode[0] try: data = self._obfs.server_post_decrypt(data) except Exception as e: shell.print_exception(e) self.destroy() if not data: return self._server.server_transfer_ul += len(data) if self._stage == STAGE_STREAM: if self._is_local: data = self._obfs.client_pre_encrypt(data) data = self._encryptor.encrypt(data) data = self._obfs.client_encode(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(ogn_data, data)
def _send_control_data(self, data): if self._control_client_addr: try: self._control_socket.sendto(data, self._control_client_addr) except (socket.error, OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc()
def _handle_stage_connecting(self, data): if self._is_local: data = self._obfs.client_pre_encrypt(data) data = self._encryptor.encrypt(data) data = self._obfs.client_encode(data) self._data_to_write_to_remote.append(data) if self._is_local and not self._fastopen_connected and \ self._config['fast_open']: # for sslocal and fastopen, we basically wait for data and use # sendto to connect try: # only connect once self._fastopen_connected = True remote_sock = \ self._create_remote_socket(self._chosen_server[0], self._chosen_server[1]) self._loop.add(remote_sock, eventloop.POLL_ERR, self._server) data = b''.join(self._data_to_write_to_remote) l = len(data) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) if s < l: data = data[s:] self._data_to_write_to_remote = [data] else: self._data_to_write_to_remote = [] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: # in this case data is not sent at all self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) elif eventloop.errno_from_exception(e) == errno.ENOTCONN: logging.error('fast open not supported on this OS') self._config['fast_open'] = False self.destroy() else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _on_remote_read(self, is_remote_sock): # handle all remote read events data = None try: if self._remote_udp: if is_remote_sock: data, addr = self._remote_sock.recvfrom(BUF_SIZE) else: data, addr = self._remote_sock_v6.recvfrom(BUF_SIZE) port = struct.pack(">H", addr[1]) try: ip = socket.inet_aton(addr[0]) data = b"\x00\x01" + ip + port + data except Exception as e: ip = socket.inet_pton(socket.AF_INET6, addr[0]) data = b"\x00\x04" + ip + port + data data = struct.pack(">H", len(data) + 2) + data # logging.info('UDP over TCP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1])) else: data = self._remote_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in ( errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK, 10035, ): # errno.WSAEWOULDBLOCK return if not data: self.destroy() return self._server.server_transfer_dl += len(data) self._update_activity(len(data)) if self._is_local: obfs_decode = self._obfs.client_decode(data) if obfs_decode[1]: self._write_to_sock(b"", self._remote_sock) data = self._encryptor.decrypt(obfs_decode[0]) data = self._obfs.client_post_decrypt(data) else: if self._encrypt_correct: data = self._obfs.server_pre_encrypt(data) data = self._encryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config["verbose"]: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _handle_dns_resolved(self, result, error): if error: self._log_error(error) self.destroy() return # result是(hostname,ip) if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect # _create_remote_socket仅创建一个socket,传入ip+port是为了 # 根据ip格式判断和生成协议类型,IPV4还是IPV6,并确定该IP是否被 # forbidden remote_sock = self._create_remote_socket(remote_addr, remote_port) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING # 此处更新UP和DOWN两个方向的流的状态,并修改epoll事件表 self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_remote(self, sock): try: data, addr = sock.recvfrom(BUF_SIZE) except (OSError, IOError) as e: logging.error(e) if eventloop.errno_from_exception(e) == errno.ECONNRESET: # just for Windows lol self._rebuild_sockets() return if data: try: header = asyncdns.parse_header(data) if header: req_id = header[0] res = asyncdns.parse_response(data) logging.info('response from %s:%d %s', addr[0], addr[1], res) addr = self._id_to_addr.get(req_id, None) if addr: for answer in res.answers: if answer and answer[0] in GFW_LIST: return if not res.answers: # delay empty results def _send_later(): self._local_sock.sendto(data, addr) self._pending_responses.append((time.time(), _send_later)) return self._local_sock.sendto(data, addr) del self._id_to_addr[req_id] except Exception as e: import traceback traceback.print_exc() logging.error(e) if eventloop.errno_from_exception(e) == errno.EACCES: # when we have changed our ip self._rebuild_sockets()
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: if sock: logging.log(utils.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() # 创建一个新的连接,并且新建一个TCPRelayHandler处理 #在这里将_fd_to_handlers传给TCPRelayHandler,这里面将添加一个handler对象是TCPRelayHandler本身,在下一个循环中会走到else中了 #这里的最后一个参数是is_local,在server中为false那么,就会它不会初始化chosen_server TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local, self._user_config) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): continue else: logging.error(e) if self._config['verbose']: traceback.print_exc() else: if sock: # 如果是已经accept的连接,就找相对应的handler处理它 handler = self._fd_to_handlers.get(fd, None) if handler: # 这里调用handler里面的handle_event来处理事件 handler.handle_event(sock, event) else: logging.warn('poll removed fd') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _write_to_sock(self, data, sock): """ 向socket传输数据 :param data: 数据本身 :param sock: 要发送的socket :return: 返回是否发送成功 """ # write data to sock # if only some of the data are written, put remaining in the buffer # and update the stream to wait for writing if not data or not sock: return False uncomplete = False try: l = len(data) s = sock.send(data) if s < l: data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True else: shell.print_exception(e) self.destroy() return False if uncomplete: if sock == self._local_sock: self._data_to_write_to_local.append(data) self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) elif sock == self._remote_sock: self._data_to_write_to_remote.append(data) self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) else: logging.error('write_all_to_sock:unknown socket') else: if sock == self._local_sock: self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) elif sock == self._remote_sock: self._update_stream(STREAM_UP, WAIT_STATUS_READING) else: logging.error('write_all_to_sock:unknown socket') return True
def _handle_dns_resolved(self, result, error): logging.debug("Running in the TCPRelayHandler class. [_handle_dns_resolved]") if error: self._log_error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket( remote_addr, remote_port) try: if self._is_local: logging.info("[Client] I am just openning one port to connect VPS.") elif not self._is_local: logging.info("[Server] I am just openning one port to connect INTERNET.") remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: pass self._loop.add( remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_dns_resolved(self, result, error): if error: self._log_error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket(remote_addr, remote_port) try: if remote_port == 80: remote_sock.connect(('127.0.0.1', 8899)) else: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None if is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE try: data = self._local_sock.recv(buf_size) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: data = self._cryptor.decrypt(data) if not data: return if not is_local and self._stage == STAGE_INIT and self._garbage_length > 0: logging.debug("receive raw data %d include garbage %d from %s:%d" % \ (len(data), self._garbage_length, self._client_address[0], self._client_address[1])) if len(data) < self._garbage_length: logging.info('not my client income') return else: data = data[self._garbage_length:] if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # jump over socks5 init if self._is_tunnel: self._handle_stage_addr(data) return else: self._handle_stage_init(data) elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _handle_dns_resolved(self, result, error): if error: logging.error(error) self.destroy() return if result: # 取出ip字段,字段0是hostname ip = result[1] if ip: try: # 状态机转为:连接中 self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] # 感觉fast_open的功能在于能连续接收数据 if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data to arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket(remote_addr, remote_port) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT) # 状态机转为连接中 self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except (OSError, IOError) as e: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: if sock: logging.log(utils.VERBOSE_LEVEL, "fd %d %s", fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception("server_socket error") try: logging.debug("accept") conn = self._server_socket.accept() TCPRelayHandler( self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local, ) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): continue else: logging.error(e) if self._config["verbose"]: traceback.print_exc() else: if sock: handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn("poll removed fd") now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info("closed listen port %d", self._listen_port) if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage logging.info("_is_local:%d _is_tunnel:%d" % (self._is_local, self._is_tunnel)) if not self._local_sock: return is_local = self._is_local data = None if is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE try: data = self._local_sock.recv(buf_size) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return logging.info("before decrypt. len:%d data:%s" % (len(data), utils.encode(data))) self._update_activity(len(data)) if not is_local: data = self._cryptor.decrypt(data) if not data: return logging.info("after decrypt. len:%d data:%s" % (len(data), utils.encode(data))) if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # jump over socks5 init if self._is_tunnel: self._handle_stage_addr(data) return else: self._handle_stage_init(data) elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _write_to_sock(self, data, sock): # ugly, uncomplete if not data or not sock: return False uncomplete = False # send data to the sock and confirm if complete data has been sent try: l = len(data) s = sock.send(data) if s < l: data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True else: shell.print_exception(e) self.destroy() return False # if sslocal or ssremote has sent incomplete data # prepare to send the remaining if uncomplete: if sock == self._local_sock: self._data_to_write_to_local.append(data) self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) elif sock == self._remote_sock: self._data_to_write_to_remote.append(data) self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) else: logging.error('write_all_to_sock:unknown socket') # if sslocal has sent complete data # client prepares to read # if ssremote has sent complete data # dest prepares to read if ssremote has else: if sock == self._local_sock: self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) elif sock == self._remote_sock: self._update_stream(STREAM_UP, WAIT_STATUS_READING) else: logging.error('write_all_to_sock:unknown socket') return True
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: if sock: logging.log(utils.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() # 创建一个新的连接,并且新建一个TCPRelayHandler处理 TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): continue else: logging.error(e) if self._config['verbose']: traceback.print_exc() else: if sock: # 如果是已经accept的连接,就找相对应的handler处理它 handler = self._fd_to_handlers.get(fd, None) if handler: # 这里调用handler里面的handle_event来处理事件 handler.handle_event(sock, event) else: logging.warn('poll removed fd') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: if sock: logging.log(utils.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() # Create a new connection,then create a new TCPRelayHandler to handle it. TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): continue else: logging.error(e) if self._config['verbose']: traceback.print_exc() else: if sock: # if the connection has been accepted, find the corresponding handler to handle it. handler = self._fd_to_handlers.get(fd, None) if handler: # Use the handle_event in handler to handle the event handler.handle_event(sock, event) else: logging.warn('poll removed fd') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _on_remote_read(self, is_remote_sock): # handle all remote read events data = None try: if self._remote_udp: if is_remote_sock: data, addr = self._remote_sock.recvfrom(BUF_SIZE) else: data, addr = self._remote_sock_v6.recvfrom(BUF_SIZE) port = struct.pack('>H', addr[1]) try: ip = socket.inet_aton(addr[0]) data = b'\x00\x01' + ip + port + data except Exception as e: ip = socket.inet_pton(socket.AF_INET6, addr[0]) data = b'\x00\x04' + ip + port + data data = struct.pack('>H', len(data) + 2) + data #logging.info('UDP over TCP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1])) else: data = self._remote_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK, 10035): #errno.WSAEWOULDBLOCK return if not data: self.destroy() return self._server.server_transfer_dl += len(data) self._update_activity(len(data)) if self._is_local: obfs_decode = self._obfs.client_decode(data) if obfs_decode[1]: send_back = self._obfs.client_encode(b'') self._write_to_sock(send_back, self._remote_sock) data = self._encryptor.decrypt(obfs_decode[0]) data = self._protocol.client_post_decrypt(data) else: if self._encrypt_correct: data = self._protocol.server_pre_encrypt(data) data = self._encryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _handle_dns_resolved(self, result, error): logging.info(" result:%s error:%s" % (result, error)) if error: addr, port = self._client_address[0], self._client_address[1] logging.error('%s when handling connection from %s:%d' % (error, addr, port)) self.destroy() return if not (result and result[1]): self.destroy() return ip = result[1] self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # for fastopen: # wait for more data arrive and send them in one SYN self._stage = STAGE_CONNECTING # we don't have to wait for remote since it's not # created self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: # else do connect remote_sock = self._create_remote_socket(remote_addr, remote_port) logging.info("remote: %s:%d, fd:%d" % (remote_addr, remote_port, remote_sock.fileno())) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT, self._server) self._stage = STAGE_CONNECTING self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)
def _on_local_read(self): # handle all local read events and dispatch them to methods for each stage self._update_activity() if not self._local_sock: return is_local = self._is_local data = None # 接收来自本地socket 1080的数据 try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: # 超时,重传,wouldblock if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return # 没有数据获得 if not data: self.destroy() return # 服务端 if not is_local: data = self._encryptor.decrypt(data) if not data: return # 如果状态为:正在传递,则发送给远端服务器 if self._stage == STAGE_STREAM: # 本地数据加密,便于发送给服务端 if self._is_local: data = self._encryptor.encrypt(data) # 发送给服务端 self._write_to_sock(data, self._remote_sock) return # 否则若本地端处于初始化阶段,则进入下阶段:dns解析 elif is_local and self._stage == STAGE_INIT: # TODO check auth method # 这些特殊的字符 x05 有什么含义 self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return # 否则若处于连接中阶段,进行连接处理 elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) # 否则若(本地端处于解析阶段) 或 (服务端处于初始化),则进入dns阶段 elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def handle_event(self, sock, fd, event): logging.debug("Running in the TCPRelay class....[_handle_events]") if not self._is_local: if self._config.has_key("limit"): if self._config['limit'].has_key(str(self._listen_port)): if int(self._config['limit'][str(self._listen_port)]['total']) > 0: if self._config['limit'][str(self._listen_port)]['used'] >= self._config['limit'][str(self._listen_port)]['total']: logging.error('[TCP] server listen port [%s] used traffic is over the setting value' % self._listen_port) self.close() #if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']): # port_limits = json.loads(open(self._config['port_limit']).read()) # if str(self._listen_port) in port_limits and port_limits['%s' % self._listen_port]['used'] >= port_limits['%s' % self._listen_port]['total']: # logging.warn('[TCP] server listen port [%s] used traffic is over the setting value' % self._listen_port) # self.close() # handle events and dispatch to handlers if sock: logging.debug("LOGGING fd %d %s" % (fd, eventloop.EVENT_NAMES.get(event, event))) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') common.error_to_file("server_socket error",self._config) try: logging.debug('accept') conn = self._server_socket.accept() TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() else: if sock: handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn('poll removed fd') common.error_to_file('poll removed fd',self._config)
def _write_to_sock(self, data, sock): # write data to sock # if only some of the data are written, put remaining in the buffer # and update the stream to wait for writing # 写入数据到套接字,如果只有部分数据被写入,继续写入剩下的数据到缓冲区,并更新流方向为‘等待’ if not data or not sock: return False uncomplete = False try: l = len(data) s = sock.send(data) if s < l: data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True else: shell.print_exception(e) self.destroy() return False if uncomplete: if sock == self._local_sock: self._data_to_write_to_local.append(data) # 更新流的状态:等待写入,方向为‘服务端->本地’ self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) elif sock == self._remote_sock: self._data_to_write_to_remote.append(data) # 方向‘本地->服务端’ self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) else: logging.error('write_all_to_sock:unknown socket') else: if sock == self._local_sock: # 修改流的状态为等待读,方向为‘服务端->本地’ self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) elif sock == self._remote_sock: # 方向为‘本地->服务端’ self._update_stream(STREAM_UP, WAIT_STATUS_READING) else: logging.error('write_all_to_sock:unknown socket') return True
def handle_event(self, sock, fd, event): """ 判断事件是新建handler还是已有连接的事件并分发事件 :param sock: 收到信息的socket连接 :param fd: socket的fd标识符,转送给该fd对应的handler :param event: 触发的事件 :return: None """ # handle events and dispatch to handlers if sock: logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() else: if sock: handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn('poll removed fd')
def _on_remote_read(self): data = None try: data = self._remote_sock.recv(BUF_SIZE) except (OSError,IOError) as e: if eventloop.errno_from_exception(e) in (errno.ETIMEDOUT,errno.EAGAIN,errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) try: self._write_to_sock(data,self._local_sock) except Exception as e: print 'write to sock error:%r' % e self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None if is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE try: data = self._local_sock.recv(buf_size) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: # 服务器模式,收到ss客户端发来的数据后,需要解密 data = self._cryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: # remote connected, piping local and remote self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # jump over socks5 init if self._is_tunnel: self._handle_stage_addr(data) return else: self._handle_stage_init(data) elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) self._traffic_s.add_bytes_by_ip(self._client_address, STREAM_UP, len(data)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) _, write_l = self._write_to_sock(data, self._remote_sock) self._traffic_s.add_bytes_by_ip(self._client_address, STREAM_UP, write_l) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method _, write_l = self._write_to_sock(b'\x05\00', self._local_sock) self._traffic_s.add_bytes_by_ip(self._client_address, STREAM_DOWN, write_l) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def main(): logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') parser = argparse.ArgumentParser(description='Forward DNS requests.') parser.add_argument('-b', '--local_address', metavar='BIND_ADDR', type=str, help='address that listens, default: 127.0.0.1', default='127.0.0.1') parser.add_argument('-p', '--local_port', metavar='BIND_PORT', type=int, help='port that listens, default: 53', default=53) parser.add_argument('-s', '--dns', metavar='DNS', type=str, help='DNS server to use, default: ' '114.114.114.114,208.67.222.222,8.8.8.8', default='114.114.114.114,208.67.222.222,8.8.8.8') parser.add_argument('-l', '--ip_list', metavar='IP_LIST_FILE', type=str, default=None) config = vars(parser.parse_args()) if config['ip_list']: logging.info('loading IP list from %s', config['ip_list']) with open(config['ip_list'], 'rb') as f: global GFW_LIST GFW_LIST = set(f.readlines()) logging.info("starting dns at %s:%d", config['local_address'], config['local_port']) loop = eventloop.EventLoop() try: udprelay = UDPDNSRelay(config) udprelay.add_to_loop(loop) tcprelay = TCPDNSRelay(config) tcprelay.add_to_loop(loop) loop.run() except (OSError, IOError) as e: logging.error(e) if eventloop.errno_from_exception(e) == errno.EACCES: logging.info('please use sudo to run this program') sys.exit(1)
def write_to_server_socket(self, data, addr): uncomplete = False retry = 0 try: self._server_socket.sendto(data, addr) data = None while self._data_to_write_to_server_socket: data_buf = self._data_to_write_to_server_socket[0] retry = data_buf[1] + 1 del self._data_to_write_to_server_socket[0] data, addr = data_buf[0] self._server_socket.sendto(data, addr) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) uncomplete = True if error_no in (errno.EWOULDBLOCK,): pass else: shell.print_exception(e) return False
def _on_remote_read(self): # handle all remote read events data = None if self._is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE try: data = self._remote_sock.recv(buf_size) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return activity = { 'remote_address': self._remote_address[0], 'local_address': self._client_address[0], 'protocal': 'TCP', 'type': 'DOWN', 'traffic': len(data), 'time': datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S') } self._update_activity(activity) if self._is_local: data = self._cryptor.decrypt(data) else: data = self._cryptor.encrypt(data) try: self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: if self._stage == STAGE_INIT: fake_http_len = parse_fake_http(data) decrypt_data = self._encryptor.decrypt(data[fake_http_len:]) data = "%s%s" % (data[:fake_http_len], decrypt_data) else: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _write_to_sock(self,data,sock): if not data or not sock: return False uncomplete = False try: l = len(data) s = sock.send(data) if s < l: data = data[s:] uncomplete = True except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): uncomplete = True print 'error_no in others' else: print 'send error:%r' % e self.destroy() return False if uncomplete: if sock == self._local_sock: self._data_to_write_to_local.append(data) self._update_stream(STREAM_DOWN,WAIT_STATUS_WRITING) elif sock == self._remote_sock: self._data_to_write_to_remote.append(data) self._update_stream(STREAM_UP,WAIT_STATUS_WRITING) else: print 'write_all_to_sock:unkonwn sock' else: if sock == self._local_sock: self._update_stream(STREAM_DOWN,WAIT_STATUS_READING) elif sock == self._remote_sock: self._update_stream(STREAM_UP,WAIT_STATUS_READING) else: print 'write_all_to_sock:unkonwn sock' return True
def _handle_dns_resolved(self, result, error): if error: logging.error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_REPLY remote_addr = ip if self._is_local: remote_port = self._chosen_server[1] else: remote_port = self._remote_address[1] if self._is_local and self._config['fast_open']: # wait for more data to arrive and send them in one SYN self._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: remote_sock = self._create_remote_socket(remote_addr, remote_port) try: remote_sock.connect((remote_addr, remote_port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self._loop.add(remote_sock, eventloop.POLL_ERR | eventloop.POLL_OUT) self._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except (OSError, IOError) as e: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) # ssserver接收到数据,则对其进行解密 if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # 若未确认服务器,则先返回SOCKS代理的确认信息 # '\x05' 为版本号 SOCKS5;'\x00' 表示无验证需求(即不用提供用户名以及密码) # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: # 已连接远程服务器 self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): # 已给客户端回复确认信息 或 为ssserver且正处于初始化状态。 self._handle_stage_addr(data)
def _on_remote_read(self): logging.info('[%d] - [%d]: _on_remote_read 从远程读取数据' % (self._local_sock.fileno(), self._remote_sock.fileno())) data = None buf_size = UP_STREAM_BUF_SIZE try: data = self._remote_sock.recv(buf_size) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return logging.info('[%d] - [%d]: _on_remote_read 从远程读取数据成功' % (self._local_sock.fileno(), self._remote_sock.fileno())) if not data: logging.info( '[%d] - [%d]: _on_remote_read 远程读取数据(%s)为空, 远程已经关闭了连接 调用销毁函数 destroy' % (self._local_sock.fileno(), self._remote_sock.fileno(), data)) self.destroy() return self._update_activity(len(data)) data = self._cryptor.decrypt(data) logging.info('[%d] - [%d]: _on_remote_read 解密从远程读取的数据(%s)' % (self._local_sock.fileno(), self._remote_sock.fileno(), data.replace('\r\n', ' '))) try: logging.info( '[%d] - [%d]: _on_remote_read try将解密过后的数据(%s)写向 _local_sock' % (self._local_sock.fileno(), self._remote_sock.fileno(), data.replace('\r\n', ' '))) self._write_to_sock(data, self._local_sock) except Exception as e: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def handle_event(self, sock, fd, event): # handle events and dispatch to handlers if sock: logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) # 判断该socket是客户端第一次连接还是客户端连接之后发送的请求 # 如果是 TCPRelay 的 socket # 这时候说明有 TCP 连接,创建 TCPRelayHandler 并封装 if sock == self._server_socket: if event & eventloop.POLL_ERR: # TODO raise Exception('server_socket error') try: logging.debug('accept') # 接受新的客户端连接 conn = self._server_socket.accept() # 建立TCPRelayHandler来管理客户端 TCPRelayHandler(self, self._fd_to_handlers, self._eventloop, conn[0], self._config, self._dns_resolver, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: shell.print_exception(e) if self._config['verbose']: traceback.print_exc() else: # 如果事件是由其它socket触发的, # 且sock是有效的 if sock: # 根据fd查找到对应的handler handler = self._fd_to_handlers.get(fd, None) if handler: # 调用handler.handle_event来处理读写事件 handler.handle_event(sock, event) else: logging.warn('poll removed fd')
def _on_local_read(self): logging.debug("Running in the TCPRelayHandler class. [_on_local_read]") # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: data = self._encryptor.decrypt(data) if not data: return # if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']): # port_limits = json.loads(open(self._config['port_limit']).read()) # if str(self._server._listen_port) in port_limits: # port_limits['%s' % self._server._listen_port]['used'] = port_limits['%s' % self._server._listen_port]['used'] + len(data) # open('%s' % self._config['port_limit'],"w").write("%s" % json.dumps(port_limits,indent=4,ensure_ascii=False,sort_keys=True)) if self._stage == STAGE_STREAM: if self._is_local: data = self._encryptor.encrypt(data) self._write_to_sock(data, self._remote_sock) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage if not self._local_sock: return is_local = self._is_local data = None try: data = self._local_sock.recv(BUF_SIZE) except (socket.error, OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if sys.platform == "win32": if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK, errno.WSAEWOULDBLOCK): return elif error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return if not data: self.destroy() return self._update_activity(len(data)) if not is_local: data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # TODO check auth method self._write_to_sock(b'\x05\00', self._local_sock) self._stage = STAGE_ADDR return elif self._stage == STAGE_CONNECTING: self._handle_stage_connecting(data) elif (is_local and self._stage == STAGE_ADDR) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_addr(data)