def _read_packet(self): """ Reads a packet from a socket """ socket_in = self._connection # Read the size of the packet psize = bytearray(3) socket_in.recv_into(psize, 3) size = getSize(psize) + 1 # Read the rest of the packet packet_payload = bytearray(size) socket_in.recv_into(packet_payload, size) # Combine the chunks psize.extend(packet_payload) packetType = getType(psize) if packetType == Flags.ERR: buf = ERR.loadFromPacket(psize) logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage) self.close() exit(1) return psize
def init_upstream(self): conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = self.server.settings["server_host"] port = self.server.settings.getint("server_port") user = self.server.settings["server_user"] password = self.server.settings["server_password"] schema = "" conn.connect((host, port)) self.upstream = conn challenge = Challenge.loadFromPacket(self.upstream.recv(10240)) logger.debug("== Greeting ==") dump(challenge.toPacket()) challenge1 = challenge.challenge1 challenge2 = challenge.challenge2 scramble_password = scramble_native_password(password, challenge1 + challenge2) response = Response() response.sequenceId = 1 response.capabilityFlags = 33531397 response.characterSet = 33 response.maxPacketSize = 16777216 response.clientAttributes["_client_name"] = 'pymysql' response.clientAttributes["_pid"] = str(os.getpid()) response.clientAttributes["_client_version"] = '5.7' response.clientAttributes["program_name"] = 'mysql' response.pluginName = 'mysql_native_password' response.username = user response.schema = schema response.authResponse = scramble_password response.removeCapabilityFlag(Flags.CLIENT_COMPRESS) response.removeCapabilityFlag(Flags.CLIENT_SSL) response.removeCapabilityFlag(Flags.CLIENT_LOCAL_FILES) logger.debug("== Auth ==") dump(response.toPacket()) self.upstream.send(response.toPacket()) _packet = self.upstream.recv(10240) logger.debug("== Result ==") dump(_packet) packetType = getType(_packet) if packetType == Flags.ERR: buf = ERR.loadFromPacket(_packet) logger.error("Upstream error:", buf.errorCode, buf.sqlState, buf.errorMessage) self.upstream.close() self.finish() exit(1)
def handle(self): # 认证 challenge1 = '12345678' challenge2 = '123456789012' challenge = self.create_challenge(challenge1, challenge2) self.send_packet(challenge.toPacket()) packet = self.read_packet() response = Response() response = response.loadFromPacket(packet) username = response.username self.logger.info("login user:"******"proxy_password"] self.user_id = username # 验证密码 native_password = scramble_native_password(password, challenge1 + challenge2) if self.server.settings[ "proxy_user"] != username or response.authResponse.encode( "iso-8859-1") != native_password: err = ERR(9001, '28000', '[%s] Access denied.' % username) buff = err.toPacket() self.send_packet(buff) self.finish() return buff = file2packet("auth_result.cap") self.send_packet(buff) # 初始化后端服务器 self.init_upstream() # 查询 while True: packet = self.read_packet() if len(packet) < 4: continue packet_type = getType(packet) if packet_type == Flags.COM_QUIT: self.upstream.close() self.finish() elif packet_type == Flags.COM_QUERY: self.handle_query(packet) else: self.dispatch_packet(packet)
def read_packet(skt): while True: packet = read_server_packet(skt) sequenceId = getSequenceId(packet) print("read packet [%s]:" % (sequenceId, )) dump_my_packet(packet) packetType = getType(packet) if packetType == Flags.ERR: buf = ERR.loadFromPacket(packet) print("error:", buf.errorCode, buf.sqlState, buf.errorMessage) skt.close() exit(1) break if packetType == Flags.EOF or packetType == Flags.OK: break
def get_conn(self): conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = self._connection_settings["host"] port = self._connection_settings.getint("port") user = self._connection_settings["user"] password = self._connection_settings["password"] schema = "" conn.connect((host, port)) self._connection = conn challenge = Challenge.loadFromPacket(self._read_packet()) challenge1 = challenge.challenge1 challenge2 = challenge.challenge2 scramble_password = scramble_native_password(password, challenge1 + challenge2) response = Response() response.sequenceId = 1 response.capabilityFlags = 33531397 response.characterSet = 33 response.maxPacketSize = 16777216 response.clientAttributes["_client_name"] = 'pymysql' response.clientAttributes["_pid"] = str(os.getpid()) response.clientAttributes["_client_version"] = '5.7' response.clientAttributes["program_name"] = 'mysql' response.pluginName = 'mysql_native_password' response.username = user response.schema = schema response.authResponse = scramble_password response.removeCapabilityFlag(Flags.CLIENT_COMPRESS) response.removeCapabilityFlag(Flags.CLIENT_SSL) response.removeCapabilityFlag(Flags.CLIENT_LOCAL_FILES) self._send_packet(response.toPacket()) _packet = self._read_packet() packetType = getType(_packet) if packetType == Flags.ERR: buf = ERR.loadFromPacket(_packet) logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage) self.close() exit(1)
def read_binlog(skt): while True: packet = read_server_packet(skt) sequenceId = getSequenceId(packet) packetType = getType(packet) # OK value # timestamp # event_type # server_id # log_pos # flags unpack = struct.unpack('<cIcIIIH', packet[6:26]) # Header timestamp = unpack[1] event_type = byte2int(unpack[2]) server_id = unpack[3] event_size = unpack[4] # position of the next event log_pos = unpack[5] flags = unpack[6] print('timestamp', 'event_type', 'server_id', 'event_size', 'log_pos') print(timestamp, event_type, server_id, event_size, log_pos) dump_my_packet(packet) if event_type == 16: ack = SemiAck("mysql-bin.000001", log_pos) ack.sequenceId = 0 packet = ack.toPacket() send_socket(skt, packet) if packetType == Flags.ERR: buf = ERR.loadFromPacket(packet) print("error:", buf.errorCode, buf.sqlState, buf.errorMessage) skt.close() exit(1) break if packetType == Flags.EOF or packetType == Flags.OK: break
def fetchone(self): while True: self._register_slave() packet = self._read_packet() sequenceId = getSequenceId(packet) packetType = getType(packet) unpack = struct.unpack('<IcIIIH', packet[self.__binlog_header_fix_length:self.__binlog_header_fix_length + 19]) # Header timestamp = unpack[0] event_type = byte2int(unpack[1]) server_id = unpack[2] event_size = unpack[3] log_pos = unpack[4] flags = unpack[5] # 跳过HEARTBEAT_EVENT if event_type == HEARTBEAT_EVENT: continue # 跳过重启后的第一个 FORMAT_DESCRIPTION_EVENT if event_type == FORMAT_DESCRIPTION_EVENT and log_pos == 0: continue # Send SemiAck after xid event if self._connection_settings["semi_sync"]: if event_type in (XID_EVENT, QUERY_EVENT): ack = SemiAck(self.__log_file, log_pos) ack.sequenceId = 0 acp_packet = ack.toPacket() self._send_packet(acp_packet) if packetType == Flags.ERR: buf = ERR.loadFromPacket(packet) logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage) self.close() exit(1) return (timestamp, event_type, event_size, log_pos), packet[self.__binlog_header_fix_length:]
def handle(self): # 认证 challenge1 = '12345678' challenge2 = '123456789012' challenge = self.create_challenge(challenge1, challenge2) self.send_packet(challenge.toPacket()) packet = self.read_packet() response = Response() response = response.loadFromPacket(packet) username = response.username self.logger.info("login user:"******"password"] self.user_id = username # 验证密码 native_password = scramble_native_password(password, challenge1 + challenge2) if self.server.settings[ "user"] != username or response.authResponse.encode( "iso-8859-1") != native_password: err = ERR(9001, '28000', '[%s] Access denied.' % username) buff = err.toPacket() self.send_packet(buff) self.finish() return buff = file2packet("auth_result.cap") self.send_packet(buff) # self.send_packet(bytes.fromhex("07 00 00 02 00 00 00 02 00 00 00")) # 查询 while True: packet = self.read_packet() if len(packet) < 4: continue packet_type = getType(packet) # dump_my_packet(packet) # print('packet_type', packet_type, com_type_name(packet_type)) if packet_type == Flags.COM_QUIT: self.finish() elif packet_type == Flags.COM_REGISTER_SLAVE: logger.info("Received COM_REGISTER_SLAVE") self.send_packet(OK().toPacket()) elif packet_type == Flags.COM_BINLOG_DUMP_GTID: logger.info("Received COM_BINLOG_DUMP_GTID") dump(packet) # https://dev.mysql.com/doc/internals/en/com-binlog-dump-gtid.html filename_len = struct.unpack("<I", packet[11:15])[0] payload = packet[27 + filename_len:] gtid_set = GtidSet.decode(BytesIO(payload)) self.dump_binlog_gtid(gtid_set) elif packet_type == Flags.COM_QUERY: self.handle_query(packet)