네트워크 카드를 통과하는 모든 mysql 트래픽을 모니터링하고 분석하며 기존 비즈니스에 영향을 주지 않고 침입 탐지(IDS) 또는 데이터 통합을 수행합니다.
처음에는 mysql-front를 사용하여 액세스합니다. 데이터베이스와 mysql 클라이언트가 접속할 때 데이터 패킷 형식이 달라서 오랫동안 고민했는데 이해가 안 가네요. mysql-front 소스 코드를 살펴보니 델파이가 없더군요. 이해하지 못하고 버렸습니다
mysql에 연결할 때 -C 매개 변수가 활성화된 경우 해당 연결에 대한 데이터는 압축을 활성화하고 압축 형식은 zlib입니다
mysql의 압축 기능은
// mysql-source/mysys/my_compress.c my_bool my_compress(uchar *packet, size_t *len, size_t *complen) { DBUG_ENTER("my_compress"); if (*len < MIN_COMPRESS_LENGTH) { *complen=0; DBUG_PRINT("note",("Packet too short: Not compressed")); } else { uchar *compbuf=my_compress_alloc(packet,len,complen); if (!compbuf) DBUG_RETURN(*complen ? 0 : 1); memcpy(packet,compbuf,*len); my_free(compbuf); } DBUG_RETURN(0); } uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen) { uchar *compbuf; uLongf tmp_complen; int res; *complen= *len * 120 / 100 + 12; if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc, *complen, MYF(MY_WME)))) return 0; /* Not enough memory */ tmp_complen= (uint) *complen; res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len); *complen= tmp_complen; if (res != Z_OK) { my_free(compbuf); return 0; } if (*complen >= *len) { *complen= 0; my_free(compbuf); DBUG_PRINT("note",("Packet got longer on compression; Not compressed")); return 0; } /* Store length of compressed packet in *len */ swap_variables(size_t, *len, *complen); return compbuf; }
Line 35는 zlib에서 compress() 함수를 호출하지만 거기에는 압축()만 캡슐화되어 있고 프로토콜 분석 부분이 없으므로 계속 읽어 보겠습니다.
프로젝트 전체에서 타겟 코드를 찾는 것은 상당히 어렵습니다. 먼저 헤더 파일에서 키 정보를 찾아보면 다음과 같은 코드를 찾을 수 있습니다.
// mysql-source/include/sql_state.h { ER_NET_UNCOMPRESS_ERROR ,"08S01", "" }
mysql이 에러 코드를 만들 때 나타나는 프롬프트 정보 및 오류 코드입니다. 압축된 데이터를 파싱할 때 오류가 발생합니다. 해당 참조를 찾아보니 실제 데이터 패킷 압축 코드
// mysql-source/sql/net_serv.cc static uchar * compress_packet(NET *net, const uchar *packet, size_t *length) { uchar *compr_packet; size_t compr_length; const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE; compr_packet= (uchar *) my_malloc(key_memory_NET_compress_packet, *length + header_length, MYF(MY_WME)); if (compr_packet == NULL) return NULL; memcpy(compr_packet + header_length, packet, *length); /* Compress the encapsulated packet. */ if (my_compress(compr_packet + header_length, length, &compr_length)) { /* If the length of the compressed packet is larger than the original packet, the original packet is sent uncompressed. */ compr_length= 0; } /* Length of the compressed (original) packet. */ int3store(&compr_packet[NET_HEADER_SIZE], static_cast<uint>(compr_length)); /* Length of this packet. */ int3store(compr_packet, static_cast<uint>(*length)); /* Packet number. */ compr_packet[3]= (uchar) (net->compress_pkt_nr++); *length+= header_length; return compr_packet; }
를 찾았습니다. 8~19행에서 압축된 데이터 패킷화 프로세스 앞에 NET_HEADER_SIZE +가 있는 것을 볼 수 있습니다. COMP_HEADER_SIZE 긴 제어 필드
이 매크로를 찾으세요. 정의는 다음과 같습니다
1 // mysql-source/include/mysql_com.h 2 3 /* Constants when using compression */ 4 #define NET_HEADER_SIZE 4 /* standard header size */ 5 #define COMP_HEADER_SIZE 3 /* compression header extra size */
NET_HEADER_SIZE 필드의 길이 필드는 압축이 풀리지 않은 데이터 부분의 길이를 저장합니다.
COMP_HEADER_SIZE 필드는 데이터 부분의 길이를 저장하는 데 사용됩니다. 압축 해제된 데이터의 길이를 순차적으로 적용한 다음 zlib를 호출하여 압축된 콘텐츠를 구문 분석할 수 있습니다.
Wireshark에서 캡처한 데이터를 분석하지 않고 직접 zlib 분석을 수행하면 제어 필드의 존재로 인해 압축 해제가 실패하게 됩니다. Python에서 보고되는 오류는 다음과 같습니다.
Traceback (most recent call last): File "<stdin>", line 1, in <module>zlib.error: Error -3 while decompressing data: incorrect data check
처음에는 머리가 아팠습니다. 이 오류를 보고 zlib 분석의 세부 사항을 보고 싶지 않았습니다. 이제 zlib 압축 문자열의 시작 부분이 x78x9c인 경우가 많다고 기록할 수 있습니다. 맞는지 확인해보세요
위 내용은 MySQL 프로토콜 스니핑이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!