コード例 #1
0
ファイル: udprelay.py プロジェクト: hxzmm/shadowsocksr
    def _handle_server_dns_resolved(self, error, remote_addr, server_addr, params):
        if error:
            return
        data, r_addr, uid, header_length = params
        user_id = self._listen_port
        try:
            server_port = remote_addr[1]
            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]
            server_addr = sa[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) > header_length + 13 and data[header_length + 4 : header_length + 12] == b"\x00\x01\x00\x00\x00\x00\x00\x00":
                    is_dns = True
                else:
                    pass
                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 not None:
                    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)
            common.connect_log('UDP data from %s:%d', common.to_str(r_addr[0]), r_addr[1])

            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
        except Exception as e:
            shell.print_exception(e)
            logging.error("exception from user %d" % (user_id,))

        try:
            client.sendto(data, (server_addr, server_port))
            self.add_transfer_u(client_uid, len(data))
            common.connect_log('UDP data remote to %s:%d', common.to_str(server_addr), server_port)
            if client_pair is None: # new request
                addr, port = client.getsockname()[:2]
                common.connect_log('UDP data to %s(%s):%d from %s:%d by user %d' %
                        (common.to_str(remote_addr[0]), common.to_str(server_addr), server_port, addr, port, user_id))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            logging.warning('IOError sendto %s:%d by user %d' % (server_addr, server_port, user_id))
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
コード例 #2
0
ファイル: udprelay.py プロジェクト: hxzmm/shadowsocksr
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        common.connect_log('UDP data remote from %s:%d', common.to_str(r_addr[0]), r_addr[1])
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        client_uid = None
        if client_addr:
            addr = client_addr[0]
            common.connect_log('UDP data to %s:%d', common.to_str(addr[0]), addr[1])
            key = client_key(client_addr[0], client_addr[1])
            client_pair = self._cache.get(key, None)
            client_dns_pair = self._cache_dns_client.get(key, None)
            if client_pair:
                client, client_uid = client_pair
            elif client_dns_pair:
                client, client_uid = client_dns_pair

        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.server_udp_pre_encrypt(data, client_uid)
            response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1,
                                           data, ref_iv)
            if not response:
                return
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
                                       data, ref_iv)
            if not data:
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data = self._protocol.client_udp_post_decrypt(data)
            header_result = parse_header(data)
            if header_result is None:
                return
            #connecttype, dest_addr, dest_port, header_length = header_result
            #logging.debug('UDP handle_client %s:%d to %s:%d' % (common.to_str(r_addr[0]), r_addr[1], dest_addr, dest_port))

            response = b'\x00\x00\x00' + data

        if client_addr:
            if client_uid:
                self.add_transfer_d(client_uid, len(response))
            else:
                self.server_transfer_dl += len(response)
            self.write_to_server_socket(response, client_addr[0])
            if client_dns_pair:
                logging.debug("remove dns client %s:%d" % (client_addr[0][0], client_addr[0][1]))
                del self._cache_dns_client[key]
                self._close_client(client_dns_pair[0])
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
コード例 #3
0
    def _handle_server_dns_resolved(self, error, remote_addr, server_addr,
                                    params):
        if error:
            return
        data, r_addr, uid, header_length, is_relay = params
        if uid is None:
            user_id = self._listen_port
        else:
            user_id = uid
        try:
            server_port = remote_addr[1]
            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]
            server_addr = sa[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_relay)
                is_dns = False
                if len(data) > header_length + 13 and data[
                        header_length + 4:header_length +
                        12] == b"\x00\x01\x00\x00\x00\x00\x00\x00":
                    is_dns = True
                else:
                    pass
                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'], 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
        except Exception as e:
            shell.print_exception(e)
            if self._config['verbose']:
                traceback.print_exc()
            logging.error("exception from user %d" % (user_id, ))

        try:
            client.sendto(data, (server_addr, server_port))
            self.add_transfer_u(client_uid, len(data))
            if client_pair is None:  # new request
                addr, port = client.getsockname()[:2]
                common.connect_log(
                    'UDP data to %s(%s):%d from %s:%d by user %d' %
                    (common.to_str(remote_addr[0]), common.to_str(server_addr),
                     server_port, addr, port, user_id))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            logging.warning('IOError sendto %s:%d by user %d' %
                            (server_addr, server_port, user_id))
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
コード例 #4
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        client_uid = None
        if client_addr:
            key = client_key(client_addr[0], client_addr[1])
            client_pair = self._cache.get(key, None)
            client_dns_pair = self._cache_dns_client.get(key, None)
            if client_pair:
                client, client_uid = client_pair
            elif client_dns_pair:
                client, client_uid = client_dns_pair

        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.server_udp_pre_encrypt(data, client_uid)
            response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1,
                                           data, ref_iv)
            if not response:
                return
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
                                       data, ref_iv)
            if not data:
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data = self._protocol.client_udp_post_decrypt(data)
            header_result = parse_header(data)
            if header_result is None:
                return
            #connecttype, dest_addr, dest_port, header_length = header_result
            #logging.debug('UDP handle_client %s:%d to %s:%d' % (common.to_str(r_addr[0]), r_addr[1], dest_addr, dest_port))

            response = b'\x00\x00\x00' + data

        if client_addr:
            if client_uid:
                self.add_transfer_d(client_uid, len(response))
            else:
                self.server_transfer_dl += len(response)
            self.write_to_server_socket(response, client_addr[0])
            if client_dns_pair:
                logging.debug("remove dns client %s:%d" % (client_addr[0][0], client_addr[0][1]))
                del self._cache_dns_client[key]
                self._close_client(client_dns_pair[0])
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
コード例 #5
0
    def _handle_server_dns_resolved(self, error, remote_addr, server_addr, params):
        if error:
            return
        data, r_addr, uid, header_length = params
        user_id = self._listen_port
        try:
            server_port = remote_addr[1]
            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]
            server_addr = sa[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) > header_length + 13 and data[header_length + 4 : header_length + 12] == b"\x00\x01\x00\x00\x00\x00\x00\x00":
                    is_dns = True
                else:
                    pass
                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 not None:
                    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
        except Exception as e:
            shell.print_exception(e)
            logging.error("exception from user %d" % (user_id,))

        try:
            client.sendto(data, (server_addr, server_port))
            self.add_transfer_u(client_uid, len(data))
            if client_pair is None: # new request
                addr, port = client.getsockname()[:2]
                common.connect_log('UDP data to %s(%s):%d from %s:%d by user %d' %
                        (common.to_str(remote_addr[0]), common.to_str(server_addr), server_port, addr, port, user_id))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            logging.warning('IOError sendto %s:%d by user %d' % (server_addr, server_port, user_id))
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
コード例 #6
0
ファイル: udprelay.py プロジェクト: jsondog/shadowsocks
    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)
コード例 #7
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)