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))
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
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)
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)
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, 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))
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
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)
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)
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)