Ejemplo n.º 1
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
Ejemplo n.º 2
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
Ejemplo n.º 3
0
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         if False and ord(data[0]) != 0x88: # force new header
             raise Exception('can not parse header')
         data = pre_parse_header(data)
         if data is None:
             raise Exception('can not parse header')
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         connecttype, remote_addr, remote_port, header_length = header_result
         logging.info('%s connecting %s:%d from %s:%d' %
                     ((connecttype == 0) and 'TCP' or 'UDP',
                         common.to_str(remote_addr), remote_port,
                         self._client_address[0], self._client_address[1]))
         self._remote_address = (common.to_str(remote_addr), remote_port)
         self._remote_udp = (connecttype != 0)
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Ejemplo n.º 4
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return

        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        header_result = parse_header(data)
        if header_result is None:
            return
        connecttype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
            key = client_key(r_addr[0], r_addr[1], dest_addr, dest_port)
        else:
            server_addr, server_port = dest_addr, dest_port
            addrs = socket.getaddrinfo(dest_addr, dest_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                key = client_key(r_addr[0], r_addr[1], af, 0)
            else:
                key = None

        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            #logging.info('UDP handle_server %s:%d from %s:%d' % (common.to_str(server_addr), server_port, self._listen_addr, self._listen_port))
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                if self._forbidden_iplist:
                    if common.to_str(sa[0]) in self._forbidden_iplist:
                        logging.debug('IP %s is in forbidden list, drop' %
                                      common.to_str(sa[0]))
                        # drop
                        return
                client = socket.socket(af, socktype, proto)
                client.setblocking(False)
                self._cache[key] = client
                self._client_fd_to_server_addr[client.fileno()] = r_addr
            else:
                # drop
                return
            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN)

        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Ejemplo n.º 5
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            try:
                data, key, ref_iv = encrypt.decrypt_all(self._password,
                                                    self._method,
                                                    data)
            except Exception:
                logging.debug('UDP handle_server: decrypt data failed')
                return

            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            ref_iv = [0]
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

            if self._config['is_multi_user'] != 0 and data:
                if uid:
                    if uid not in self.mu_server_transfer_ul:
                        self.mu_server_transfer_ul[uid] = 0
                    if uid not in self.mu_server_transfer_dl:
                        self.mu_server_transfer_dl[uid] = 0
                    if uid not in self.mu_connected_iplist:
                        self.mu_connected_iplist[uid] = []
                    if uid not in self.mu_detect_log_list:
                        self.mu_detect_log_list[uid] = []

                    if common.getRealIp(r_addr[0]) not in self.mu_connected_iplist[uid]:
                        self.mu_connected_iplist[uid].append(common.getRealIp(r_addr[0]))

                else:
                    raise Exception(
                        'This port is multi user in single port only,so The connection has been rejected, when connect from %s:%d via port %d' %
                        (r_addr[0], r_addr[1], self._listen_port))

        is_relay = False

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:

            if not self._is_relay(r_addr, ogn_data, uid):
                data = pre_parse_header(data)

                data = self._pre_parse_udp_header(data)
                if data is None:
                    return

                if isinstance(data, tuple):
                    return
                    # return self._handle_tcp_over_udp(data, r_addr)
            else:
                if self._config["is_multi_user"] == 0:
                    data, is_relay = self._handel_normal_relay(r_addr, ogn_data)
                else:
                    data, is_relay = self._handel_mu_relay(r_addr, ogn_data, uid)

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length, is_relay))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length, is_relay))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length, is_relay))
Ejemplo n.º 6
0
    def _handle_stage_addr(self, ogn_data, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug("UDP associate")
                    if self._local_sock.family == socket.AF_INET6:
                        header = b"\x05\x00\x00\x04"
                    else:
                        header = b"\x05\x00\x00\x01"
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family, addr)
                    port_to_send = struct.pack(">H", port)
                    self._write_to_sock(header + addr_to_send + port_to_send, self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error("unknown command %d", cmd)
                    self.destroy()
                    return

            before_parse_data = data
            if self._is_local:
                header_result = parse_header(data)
            else:
                if (
                    data is None
                    or FORCE_NEW_PROTOCOL
                    and common.ord(data[0]) != 0x88
                    and (~common.ord(data[0]) & 0xFF) != 0x88
                ):
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                data = pre_parse_header(data)
                if data is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                header_result = parse_header(data)
                if header_result is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                    header_result = parse_header(data)
            connecttype, remote_addr, remote_port, header_length = header_result
            logging.info(
                "%s connecting %s:%d from %s:%d"
                % (
                    (connecttype == 0) and "TCP" or "UDP",
                    common.to_str(remote_addr),
                    remote_port,
                    self._client_address[0],
                    self._client_address[1],
                )
            )
            self._remote_address = (common.to_str(remote_addr), remote_port)
            self._remote_udp = connecttype != 0
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b"\x05\x00\x00\x01" b"\x00\x00\x00\x00\x10\x10"), self._local_sock)
                if CLIENT_NEW_PROTOCOL:
                    rnd_len = random.randint(1, 32)
                    total_len = 7 + rnd_len + len(data)
                    data = b"\x88" + struct.pack(">H", total_len) + chr(rnd_len) + (b" " * (rnd_len - 1)) + data
                    crc = (0xFFFFFFFF - binascii.crc32(data)) & 0xFFFFFFFF
                    data += struct.pack("<I", crc)
                data = self._obfs.client_pre_encrypt(data)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0], self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr, self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config["verbose"]:
                traceback.print_exc()
            self.destroy()
Ejemplo n.º 7
0
    def _handle_stage_addr(self, ogn_data, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return

            before_parse_data = data
            if self._is_local:
                header_result = parse_header(data)
            else:
                if data is None or FORCE_NEW_PROTOCOL and common.ord(
                        data[0]) != 0x88 and (~common.ord(data[0])
                                              & 0xff) != 0x88:
                    data = self._handel_protocol_error(self._client_address,
                                                       ogn_data)
                data = pre_parse_header(data)
                if data is None:
                    data = self._handel_protocol_error(self._client_address,
                                                       ogn_data)
                header_result = parse_header(data)
                if header_result is None:
                    data = self._handel_protocol_error(self._client_address,
                                                       ogn_data)
                    header_result = parse_header(data)
            connecttype, remote_addr, remote_port, header_length = header_result
            logging.info('%s connecting %s:%d from %s:%d' %
                         ((connecttype == 0) and 'TCP'
                          or 'UDP', common.to_str(remote_addr), remote_port,
                          self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            self._remote_udp = (connecttype != 0)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                if CLIENT_NEW_PROTOCOL:
                    rnd_len = random.randint(1, 32)
                    total_len = 7 + rnd_len + len(data)
                    data = b'\x88' + struct.pack(
                        '>H',
                        total_len) + chr(rnd_len) + (b' ' *
                                                     (rnd_len - 1)) + data
                    crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff
                    data += struct.pack('<I', crc)
                data = self._obfs.client_pre_encrypt(data)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Ejemplo n.º 8
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key,
                                          self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

            if self._config['is_multi_user'] != 0 and data:
                if uid:
                    if uid not in self.mu_server_transfer_ul:
                        self.mu_server_transfer_ul[uid] = 0
                    if uid not in self.mu_server_transfer_dl:
                        self.mu_server_transfer_dl[uid] = 0
                    if uid not in self.mu_connected_iplist:
                        self.mu_connected_iplist[uid] = []
                    if uid not in self.mu_detect_log_list:
                        self.mu_detect_log_list[uid] = []

                    if common.get_ip_md5(
                            r_addr[0], self._config['ip_md5_salt']
                    ) not in self.mu_connected_iplist[uid]:
                        self.mu_connected_iplist[uid].append(
                            common.get_ip_md5(r_addr[0],
                                              self._config['ip_md5_salt']))

                else:
                    raise Exception(
                        'This port is multi user in single port only,so The connection has been rejected, when connect from %s:%d via port %d'
                        % (r_addr[0], r_addr[1], self._listen_port))

        is_relay = False

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:

            if not self._is_relay(r_addr, ogn_data, uid):
                data = pre_parse_header(data)

                data = self._pre_parse_udp_header(data)
                if data is None:
                    return

                if isinstance(data, tuple):
                    return
                    # return self._handle_tcp_over_udp(data, r_addr)
            else:
                if self._config["is_multi_user"] == 0:
                    data, is_relay = self._handel_normal_relay(
                        r_addr, ogn_data)
                else:
                    data, is_relay = self._handel_mu_relay(
                        r_addr, ogn_data, uid)

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            connecttype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (connecttype & 7) == 3:
            addrs = self._dns_cache.get(server_addr, None)
            if addrs is None:
                # TODO async getaddrinfo
                addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                           socket.SOCK_DGRAM, socket.SOL_UDP)
                if not addrs:
                    # drop
                    return
                else:
                    self._dns_cache[server_addr] = addrs
        else:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client_pair = self._cache.get(key, None)
        if not client_pair:
            client_pair = self._cache_dns_client.get(key, None)
        if not client_pair:
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            if self._forbidden_portset:
                if sa[1] in self._forbidden_portset:
                    logging.debug('Port %d is in forbidden list, reject' %
                                  sa[1])
                    # drop
                    return

            client = socket.socket(af, socktype, proto)
            client_uid = uid
            client.setblocking(False)
            self._socket_bind_addr(client, af, is_relay)
            is_dns = False
            if len(data) > 20 and data[
                    11:19] == b"\x00\x01\x00\x00\x00\x00\x00\x00":
                is_dns = True
            else:
                pass
                #logging.info("unknown data %s" % (binascii.hexlify(data),))
            if sa[1] == 53 and is_dns:  # DNS
                logging.debug("DNS query %s from %s:%d" %
                              (common.to_str(sa[0]), r_addr[0], r_addr[1]))
                self._cache_dns_client[key] = (client, uid)
            else:
                self._cache[key] = (client, uid)
            self._client_fd_to_server_addr[client.fileno()] = (r_addr, af)

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

            logging.debug('UDP port %5d sockets %d' %
                          (self._listen_port, len(self._sockets)))

            if not self.is_pushing_detect_text_list:
                for id in self.detect_text_list:
                    if common.match_regex(self.detect_text_list[id]['regex'],
                                          common.to_str(data)):
                        if self._config['is_multi_user'] != 0 and uid != 0:
                            if self.is_cleaning_mu_detect_log_list == False and id not in self.mu_detect_log_list[
                                    uid]:
                                self.mu_detect_log_list[uid].append(id)
                        else:
                            if self.is_cleaning_detect_log == False and id not in self.detect_log_list:
                                self.detect_log_list.append(id)
                        raise Exception(
                            'This connection match the regex: id:%d was reject,regex: %s ,connecting %s:%d from %s:%d via port %d'
                            % (self.detect_text_list[id]['id'],
                               self.detect_text_list[id]['regex'],
                               common.to_str(server_addr), server_port,
                               r_addr[0], r_addr[1], self._listen_port))
            if not self.is_pushing_detect_hex_list:
                for id in self.detect_hex_list:
                    if common.match_regex(self.detect_hex_list[id]['regex'],
                                          binascii.hexlify(data)):
                        if self._config['is_multi_user'] != 0 and uid != 0:
                            if self.is_cleaning_mu_detect_log_list == False and id not in self.mu_detect_log_list[
                                    uid]:
                                self.mu_detect_log_list[uid].append(id)
                        else:
                            if self.is_cleaning_detect_log == False and id not in self.detect_log_list:
                                self.detect_log_list.append(id)
                        raise Exception(
                            'This connection match the regex: id:%d was reject,regex: %s ,connecting %s:%d from %s:%d via port %d'
                            % (self.detect_hex_list[id]['id'],
                               self.detect_hex_list[id]['regex'],
                               common.to_str(server_addr), server_port,
                               r_addr[0], r_addr[1], self._listen_port))
            if not self._connect_hex_data:
                common.connect_log('UDP data to %s:%d from %s:%d via port %d' %
                                   (common.to_str(server_addr), server_port,
                                    r_addr[0], r_addr[1], self._listen_port))
            else:
                common.connect_log(
                    'UDP data to %s:%d from %s:%d via port %d,hex data : %s' %
                    (common.to_str(server_addr), server_port, r_addr[0],
                     r_addr[1], self._listen_port, binascii.hexlify(data)))
            if self._config['is_multi_user'] != 2:
                if common.to_str(r_addr[0]) in self.wrong_iplist and r_addr[
                        0] != 0 and self.is_cleaning_wrong_iplist == False:
                    del self.wrong_iplist[common.to_str(r_addr[0])]
                if common.get_ip_md5(
                        r_addr[0], self._config['ip_md5_salt']
                ) not in self.connected_iplist and r_addr[
                        0] != 0 and self.is_cleaning_connected_iplist == False:
                    self.connected_iplist.append(
                        common.get_ip_md5(r_addr[0],
                                          self._config['ip_md5_salt']))
        else:
            client, client_uid = client_pair

        self._cache.clear(self._udp_cache_size)
        self._cache_dns_client.clear(16)

        if self._is_local:
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.client_udp_pre_encrypt(data)
            #logging.debug("%s" % (binascii.hexlify(data),))
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key,
                                          self._method, 1, data, ref_iv)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            #logging.info('UDP handle_server sendto %s:%d %d bytes' % (common.to_str(server_addr), server_port, len(data)))
            client.sendto(data, (server_addr, server_port))
            self.add_transfer_u(client_uid, len(data))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Ejemplo n.º 9
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key,
                                          self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:
            data = pre_parse_header(data)

            data = self._pre_parse_udp_header(data)
            if data is None:
                return

            if type(data) is tuple:
                return
                #return self._handle_tcp_over_udp(data, r_addr)

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            connecttype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (connecttype & 7) == 3:
            addrs = self._dns_cache.get(server_addr, None)
            if addrs is None:
                # TODO async getaddrinfo
                addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                           socket.SOCK_DGRAM, socket.SOL_UDP)
                if not addrs:
                    # drop
                    return
                else:
                    self._dns_cache[server_addr] = addrs
        else:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client_pair = self._cache.get(key, None)
        if client_pair is None:
            client_pair = self._cache_dns_client.get(key, None)
        if client_pair is None:
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            if self._forbidden_portset:
                if sa[1] in self._forbidden_portset:
                    logging.debug('Port %d is in forbidden list, reject' %
                                  sa[1])
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client_uid = uid
            client.setblocking(False)
            self._socket_bind_addr(client, af)
            is_dns = False
            if len(data) > 20 and data[
                    11:19] == b"\x00\x01\x00\x00\x00\x00\x00\x00":
                is_dns = True
            else:
                pass
                #logging.info("unknown data %s" % (binascii.hexlify(data),))
            if sa[1] == 53 and is_dns:  #DNS
                logging.debug("DNS query %s from %s:%d" %
                              (common.to_str(sa[0]), r_addr[0], r_addr[1]))
                self._cache_dns_client[key] = (client, uid)
            else:
                self._cache[key] = (client, uid)
            self._client_fd_to_server_addr[client.fileno()] = (r_addr, af)

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

            logging.debug('UDP port %5d sockets %d' %
                          (self._listen_port, len(self._sockets)))

            if uid is None:
                user_id = self._listen_port
            else:
                user_id = struct.unpack('<I', client_uid)[0]
        else:
            client, client_uid = client_pair
        self._cache.clear(self._udp_cache_size)
        self._cache_dns_client.clear(16)

        if self._is_local:
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.client_udp_pre_encrypt(data)
            #logging.debug("%s" % (binascii.hexlify(data),))
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key,
                                          self._method, 1, data, ref_iv)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            #logging.info('UDP handle_server sendto %s:%d %d bytes' % (common.to_str(server_addr), server_port, len(data)))
            client.sendto(data, (server_addr, server_port))
            if client_pair is None:  # new request
                addr, port = client.getsockname()[:2]
                common.connect_log('UDP data to %s:%d from %s:%d by UID %d' %
                                   (common.to_str(server_addr), server_port,
                                    addr, port, user_id))
            self.add_transfer_u(client_uid, len(data))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Ejemplo n.º 10
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return

        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        header_result = parse_header(data)
        if header_result is None:
            return
        connecttype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        logging.debug(key)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN)

        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)