diff --git a/src/quic_entry.cpp b/src/quic_entry.cpp index 5881c2a..4e9f6b1 100644 --- a/src/quic_entry.cpp +++ b/src/quic_entry.cpp @@ -172,22 +172,11 @@ extern "C" unsigned char QUIC_ENTRY(struct streaminfo *pstream, void**pme, int t quic_init_context(pme, thread_seq); context=(struct quic_context *)*pme; } - - switch(pstream->opstate) - { - case OP_STATE_PENDING: - state=quic_analyze_entry(pstream, context, thread_seq, a_packet); - break; - case OP_STATE_DATA: - state=quic_call_business_plug(pstream, context, (char *)pstream->pudpdetail->pdata, pstream->pudpdetail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet); - break; - case OP_STATE_CLOSE: - if(pstream->pudpdetail->pdata!=NULL && pstream->pudpdetail->datalen>0) - { - state=quic_call_business_plug(pstream, context, (char *)pstream->pudpdetail->pdata, pstream->pudpdetail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet); - } - state=quic_call_business_plug(pstream, context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet); - break; + + state=quic_analyze_entry(pstream, context, thread_seq, a_packet); + if(pstream->opstate==OP_STATE_CLOSE) + { + state=quic_call_business_plug(pstream, context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet); } if(state&APP_STATE_DROPME || state&APP_STATE_DROPPKT || pstream->opstate==OP_STATE_CLOSE) @@ -214,6 +203,7 @@ extern "C" int QUIC_INIT(void) MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "LOG_PATH", g_quic_param.log_path, sizeof(g_quic_param.log_path), "./log/quic/quic"); MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "DECRYPTED_SWITCH", &g_quic_param.decrypted_switch, 2); + MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "MAX_PARSE_PKT_NUM", &g_quic_param.max_parse_pkt_num, 3); MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "QUIC_PORT_LIST", buff, sizeof(buff), "443;8443;"); g_quic_param.quic_port_num=parse_quic_port(buff, g_quic_param.quic_port_list, SUPPORT_QUIC_PORT_NUM); diff --git a/src/quic_entry.h b/src/quic_entry.h index 96bd3ae..90e080c 100644 --- a/src/quic_entry.h +++ b/src/quic_entry.h @@ -28,6 +28,7 @@ struct quic_param int level; int quic_port_num; int decrypted_switch; + int max_parse_pkt_num; unsigned short quic_port_list[SUPPORT_QUIC_PORT_NUM]; char quic_conf_regionname[MAX_REGION_NUM][REGION_NAME_LEN]; char log_path[128]; diff --git a/src/quic_process.cpp b/src/quic_process.cpp index 97793ae..3284ab2 100644 --- a/src/quic_process.cpp +++ b/src/quic_process.cpp @@ -18,9 +18,14 @@ #include "quic_process.h" #include "quic_deprotection.h" -#define PARSE_RESULT_UNKNOWN 0 -#define PARSE_RESULT_VERSION 1 -#define PARSE_RESULT_CLIENT_HELLO 2 +enum PARSE_RESULT +{ + PARSE_RESULT_UNKNOWN, + PARSE_RESULT_VERSION, + PARSE_RESULT_CLIENT_HELLO, + PARSE_RESULT_PAYLOAD, + PARSE_RESULT_MAX +}; #ifndef PRINTADDR #define PRINTADDR(a, b) ((b)addr), a->threadnum) : "") @@ -748,7 +753,7 @@ enum QUIC_VERSION is_quic_protocol(const char *payload, int payload_len, int *pa return quic_version; } -int parse_quic_all_version(struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq) +unsigned char parse_quic_all_version(struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq) { int ret=0, payload_offset=0; unsigned char decrypt_payload[2048]={0}; @@ -803,24 +808,59 @@ int parse_quic_all_version(struct quic_info *quic_info, const char *payload, int unsigned char quic_analyze_entry(struct streaminfo *pstream, struct quic_context* context, int thread_seq, void* a_packet) { - int ret=PARSE_RESULT_UNKNOWN; + unsigned char parse_result=PARSE_RESULT_UNKNOWN; + char state=APP_STATE_GIVEME; + if(pstream==NULL || pstream->pudpdetail==NULL) { return APP_STATE_DROPME; } + struct udpdetail *udp_detail=pstream->pudpdetail; - ret=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq); - switch(ret) + + switch(context->pre_parse_state) { - case PARSE_RESULT_VERSION: - return quic_call_business_plug(pstream, context, (void *)&(context->quic_info.quic_version), sizeof(unsigned int), QUIC_USEING_VERSION_MASK, a_packet); - case PARSE_RESULT_CLIENT_HELLO: - return quic_call_business_plug(pstream, context, (void *)&(context->quic_info), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet); + case PARSE_RESULT_CLIENT_HELLO: + parse_result=PARSE_RESULT_PAYLOAD; + break; + case PARSE_RESULT_VERSION: + parse_result=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq); + if(parse_result==PARSE_RESULT_VERSION || parse_result==PARSE_RESULT_UNKNOWN) + { + parse_result=PARSE_RESULT_PAYLOAD; + } + break; + case PARSE_RESULT_PAYLOAD: + case PARSE_RESULT_UNKNOWN: default: + if((context->parse_pkt_cnt++)>=g_quic_param.max_parse_pkt_num) + { + parse_result=PARSE_RESULT_PAYLOAD; + break; + } + parse_result=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq); + break; + } + + switch(parse_result) + { + case PARSE_RESULT_VERSION: + context->pre_parse_state=PARSE_RESULT_VERSION; + state=quic_call_business_plug(pstream, context, (void *)&(context->quic_info.quic_version), sizeof(unsigned int), QUIC_USEING_VERSION_MASK, a_packet); + break; + case PARSE_RESULT_CLIENT_HELLO: + context->pre_parse_state=PARSE_RESULT_CLIENT_HELLO; + state=quic_call_business_plug(pstream, context, (void *)&(context->quic_info), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet); + break; + case PARSE_RESULT_PAYLOAD: + state=quic_call_business_plug(pstream, context, udp_detail->pdata, udp_detail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet); + break; + default: + return APP_STATE_DROPME; break; } - return APP_STATE_DROPME; + return state; } static int copy_client_hello_extension(char *src, char *dest, int d_len) @@ -839,7 +879,7 @@ static int copy_client_hello_extension(char *src, char *dest, int d_len) unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, char *out_sni, int *out_sni_len, char *out_ua, int *out_ua_len) { - int ret=APP_STATE_GIVEME; + unsigned char parse_result=APP_STATE_GIVEME; struct quic_info quic_info={0, NULL}; unsigned int quic_version=QUIC_VERSION_UNKNOWN; @@ -848,8 +888,8 @@ unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, return quic_version; } - ret=parse_quic_all_version(&quic_info, (const char *)a_stream->pudpdetail->pdata, a_stream->pudpdetail->datalen, a_stream->threadnum); - if(ret!=PARSE_RESULT_UNKNOWN) + parse_result=parse_quic_all_version(&quic_info, (const char *)a_stream->pudpdetail->pdata, a_stream->pudpdetail->datalen, a_stream->threadnum); + if(parse_result!=PARSE_RESULT_UNKNOWN) { if(quic_info.client_hello!=NULL) { diff --git a/src/quic_process.h b/src/quic_process.h index 6a77769..b3cf8a1 100644 --- a/src/quic_process.h +++ b/src/quic_process.h @@ -282,12 +282,13 @@ enum QUIC_VERSION struct quic_context { unsigned char link_state; - unsigned char padding[7]; + unsigned char parse_pkt_cnt; + unsigned char pre_parse_state; + unsigned char padding[5]; void *business_pme; struct quic_info quic_info; }; -int parse_quic_all_version(struct quic_info* quic_info, const char *payload, int payload_len, int thread_seq); unsigned char quic_analyze_entry(struct streaminfo *pstream, struct quic_context* context, int thread_seq, void* a_packet); unsigned char quic_call_business_plug(struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, void *a_packet); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2422299..a264398 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -58,3 +58,4 @@ add_test(NAME QUIC_RFC9000 COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/p add_test(NAME QUIC_RFC9000_FRAGMENT COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-fragment/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-fragment/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME QUIC_RFC9000_SPECIAL COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-special/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/rfc9000-special/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) add_test(NAME QUIC_AIRPORT COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/airport/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/airport -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) +add_test(NAME QUIC_SPECIAL COMMAND proto_test_main ${CMAKE_CURRENT_SOURCE_DIR}/pcap/special/${lib_name}_result.json -f "find ${CMAKE_CURRENT_SOURCE_DIR}/pcap/special/ -name *.pcap|sort -V" WORKING_DIRECTORY ${PROTO_TEST_RUN_DIR}) diff --git a/test/pcap/gquic/44/quic_result.json b/test/pcap/gquic/44/quic_result.json index 1f08140..c5db421 100644 --- a/test/pcap/gquic/44/quic_result.json +++ b/test/pcap/gquic/44/quic_result.json @@ -57,6 +57,8 @@ }, { "Tuple4": "85.117.117.190.11567>64.233.165.94.443", "VERSION": "Google QUIC 44", + "SNI": "www.google.kz", + "UA": "dev Chrome/73.0.3664.3 Windows NT 6.3; Win64; x64", "name": "QUIC_RESULT_10" }, { "Tuple4": "85.117.117.190.48098>173.194.221.95.443", @@ -67,6 +69,8 @@ }, { "Tuple4": "85.117.119.57.4009>64.233.162.155.443", "VERSION": "Google QUIC 44", + "SNI": "stats.g.doubleclick.net", + "UA": "dev Chrome/73.0.3664.3 Windows NT 6.1; Win64; x64", "name": "QUIC_RESULT_12" }, { "Tuple4": "85.117.126.11.11719>64.233.165.138.443", diff --git a/test/pcap/special/1-no-parse-sni-draft-29-10.83.31.23.37645-142.250.180.42.443.pcap b/test/pcap/special/1-no-parse-sni-draft-29-10.83.31.23.37645-142.250.180.42.443.pcap new file mode 100644 index 0000000..ad40e1d Binary files /dev/null and b/test/pcap/special/1-no-parse-sni-draft-29-10.83.31.23.37645-142.250.180.42.443.pcap differ diff --git a/test/pcap/special/1-no-parse-sni-draft-29.37645.pcap b/test/pcap/special/1-no-parse-sni-draft-29.37645.pcap new file mode 100644 index 0000000..ad40e1d Binary files /dev/null and b/test/pcap/special/1-no-parse-sni-draft-29.37645.pcap differ diff --git a/test/pcap/special/2-no-parse-sni-rfc9000-192.168.1.6.61269-142.250.180.42.443.pcap b/test/pcap/special/2-no-parse-sni-rfc9000-192.168.1.6.61269-142.250.180.42.443.pcap new file mode 100644 index 0000000..ad965e8 Binary files /dev/null and b/test/pcap/special/2-no-parse-sni-rfc9000-192.168.1.6.61269-142.250.180.42.443.pcap differ diff --git a/test/pcap/special/2-no-parse-sni-rfc9000.61269.pcap b/test/pcap/special/2-no-parse-sni-rfc9000.61269.pcap new file mode 100644 index 0000000..ad965e8 Binary files /dev/null and b/test/pcap/special/2-no-parse-sni-rfc9000.61269.pcap differ diff --git a/test/pcap/special/3-no-parse-sni-gquic-43-10.129.24.130.52558-213.55.110.12.443.pcap b/test/pcap/special/3-no-parse-sni-gquic-43-10.129.24.130.52558-213.55.110.12.443.pcap new file mode 100644 index 0000000..9ea020b Binary files /dev/null and b/test/pcap/special/3-no-parse-sni-gquic-43-10.129.24.130.52558-213.55.110.12.443.pcap differ diff --git a/test/pcap/special/4-no-sni-rfc9000-197.156.101.97.12388-142.250.185.46.443.pcap b/test/pcap/special/4-no-sni-rfc9000-197.156.101.97.12388-142.250.185.46.443.pcap new file mode 100644 index 0000000..36d7457 Binary files /dev/null and b/test/pcap/special/4-no-sni-rfc9000-197.156.101.97.12388-142.250.185.46.443.pcap differ diff --git a/test/pcap/special/quic_result.json b/test/pcap/special/quic_result.json new file mode 100644 index 0000000..213bbeb --- /dev/null +++ b/test/pcap/special/quic_result.json @@ -0,0 +1,26 @@ +[{ + "Tuple4": "10.83.31.23.37645>142.250.180.42.443", + "VERSION": "IETF QUIC 29", + "SNI": "play.googleapis.com", + "UA": "com.google.android.gms Cronet/92.0.4515.131", + "VERSION": "IETF QUIC 29", + "name": "QUIC_RESULT_1" + }, { + "Tuple4": "192.168.1.6.61269>142.250.180.42.443", + "VERSION": "IETF QUIC RFC9000", + "SNI": "content-autofill.googleapis.com", + "UA": "Chrome/94.0.4606.81 Windows NT 10.0; Win64; x64", + "VERSION": "IETF QUIC RFC9000", + "name": "QUIC_RESULT_2" + }, { + "Tuple4": "10.129.24.130.52558>213.55.110.12.443", + "VERSION": "Google QUIC 43", + "SNI": "r1---sn-xuj-5qqz.googlevideo.com", + "UA": "com.google.android.youtube Cronet/80.0.3970.3", + "VERSION": "Google QUIC 43", + "name": "QUIC_RESULT_3" +}, { + "Tuple4": "197.156.101.97.12388>142.250.185.46.443", + "VERSION": "IETF QUIC RFC9000", + "name": "QUIC_RESULT_4" +}]