Ejemplo n.º 1
0
 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()
Ejemplo n.º 2
0
 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()
Ejemplo n.º 3
0
 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()
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
    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()
Ejemplo n.º 9
0
 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')
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
    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()
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
 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()
Ejemplo n.º 15
0
    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()
Ejemplo n.º 16
0
 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
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
 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
Ejemplo n.º 19
0
    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()
Ejemplo n.º 20
0
    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()
Ejemplo n.º 21
0
    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()
Ejemplo n.º 22
0
 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)
Ejemplo n.º 23
0
 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()
Ejemplo n.º 24
0
 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()
Ejemplo n.º 25
0
 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()
Ejemplo n.º 26
0
 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()
Ejemplo n.º 27
0
    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()
Ejemplo n.º 28
0
 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()
Ejemplo n.º 29
0
    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)
Ejemplo n.º 30
0
    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
Ejemplo n.º 31
0
    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()
Ejemplo n.º 32
0
    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()
Ejemplo n.º 33
0
    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)
Ejemplo n.º 34
0
 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()
Ejemplo n.º 35
0
    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)
Ejemplo n.º 36
0
    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)
Ejemplo n.º 37
0
    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
Ejemplo n.º 38
0
    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)
Ejemplo n.º 39
0
    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)
Ejemplo n.º 40
0
 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()
Ejemplo n.º 41
0
    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)
Ejemplo n.º 42
0
 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)
Ejemplo n.º 43
0
 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)
Ejemplo n.º 44
0
 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
Ejemplo n.º 45
0
    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')
Ejemplo n.º 46
0
Archivo: s5s.py Proyecto: cheng-xz/s5s
    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()
Ejemplo n.º 47
0
 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)
Ejemplo n.º 48
0
 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)
Ejemplo n.º 49
0
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)
Ejemplo n.º 50
0
 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
Ejemplo n.º 51
0
    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()
Ejemplo n.º 52
0
 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)
Ejemplo n.º 53
0
Archivo: s5s.py Proyecto: cheng-xz/s5s
    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
Ejemplo n.º 54
0
    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()
Ejemplo n.º 55
0
 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)
Ejemplo n.º 56
0
    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()
Ejemplo n.º 57
0
 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')
Ejemplo n.º 58
0
Archivo: tcprelay.py Proyecto: able8/ss
    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)
Ejemplo n.º 59
0
 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)