diff --git a/nfq2/desync.c b/nfq2/desync.c index cb7f6ad..94fc45a 100644 --- a/nfq2/desync.c +++ b/nfq2/desync.c @@ -1280,80 +1280,79 @@ static uint8_t dpi_desync_tcp_packet_play( process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin); - t_protocol_probe testers[] = { - {L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial}, - {L7P_HTTP_REQ,L7_HTTP,IsHttp,false}, - {L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false}, - {L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false} - }; - protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload); - - if (l7payload==L7P_UNKNOWN) + // do not detect payload if reasm is in progress + if (!ctrack || ReasmIsEmpty(&ctrack->reasm_client)) { - // this is special type. detection requires AES and can be successful only for the first data packet. no reason to AES every packet - if (ctrack && (ctrack->pos.client.seq_last - ctrack->pos.client.seq0)==1) + t_protocol_probe testers[] = { + {L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial}, + {L7P_HTTP_REQ,L7_HTTP,IsHttp,false}, + {L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false}, + {L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false} + }; + protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload); + + if (l7payload==L7P_UNKNOWN) { - t_protocol_probe testers[] = { - {L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto} - }; - protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload); + // this is special type. detection requires AES and can be successful only for the first data packet. no reason to AES every packet + if (ctrack && (ctrack->pos.client.seq_last - ctrack->pos.client.seq0)==1) + { + t_protocol_probe testers[] = { + {L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto} + }; + protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload); + } } } - switch(l7payload) + if (l7payload==L7P_HTTP_REQ) { - case L7P_HTTP_REQ: - // we do not reassemble http - reasm_client_cancel(ctrack); - - bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host)); - if (!bHaveHost) - { - DLOG("not applying tampering to HTTP without Host:\n"); - goto pass; - } - break; - case L7P_TLS_CLIENT_HELLO: - { - bool bReqFull = IsTLSRecordFull(rdata_payload, rlen_payload); - DLOG(bReqFull ? "TLS ClientHello is FULL\n" : "TLS ClientHello is PARTIAL\n"); - - if (bReqFull) TLSDebug(rdata_payload, rlen_payload); - - bHaveHost = TLSHelloExtractHost(rdata_payload, rlen_payload, host, sizeof(host), true); - if (ctrack && !l7_payload_match(l7payload, params.reasm_payload_disable)) - { - // do not reasm retransmissions - if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_client) && !is_retransmission(&ctrack->pos.client)) - { - // do not reconstruct unexpected large payload (they are feeding garbage ?) - if (!reasm_client_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload)) - goto pass_reasm_cancel; - } - - if (!ReasmIsEmpty(&ctrack->reasm_client)) - { - if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout)) - { - DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed)); - } - else - { - DLOG_ERR("rawpacket_queue failed !\n"); - goto pass_reasm_cancel; - } - if (ReasmIsFull(&ctrack->reasm_client)) - { - replay_queue(&ctrack->delayed); - reasm_client_fin(ctrack); - } - return VERDICT_DROP; - } - } - break; - } + bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host)); + if (!bHaveHost) + { + DLOG("not applying tampering to HTTP without Host:\n"); + goto pass; + } } + else if (l7payload==L7P_TLS_CLIENT_HELLO || l7proto==L7_TLS && l7payload==L7P_UNKNOWN && ctrack && !ReasmIsEmpty(&ctrack->reasm_client)) + { + l7payload = L7P_TLS_CLIENT_HELLO; + bool bReqFull = IsTLSRecordFull(rdata_payload, rlen_payload); + DLOG(bReqFull ? "TLS client hello is FULL\n" : "TLS client hello is PARTIAL\n"); + + if (bReqFull) TLSDebug(rdata_payload, rlen_payload); + + bHaveHost = TLSHelloExtractHost(rdata_payload, rlen_payload, host, sizeof(host), true); + if (ctrack && !l7_payload_match(l7payload, params.reasm_payload_disable)) + { + // do not reasm retransmissions + if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_client) && !is_retransmission(&ctrack->pos.client)) + { + // do not reconstruct unexpected large payload (they are feeding garbage ?) + if (!reasm_client_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload)) + goto pass_reasm_cancel; + } + + if (!ReasmIsEmpty(&ctrack->reasm_client)) + { + if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout)) + { + DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed)); + } + else + { + DLOG_ERR("rawpacket_queue failed !\n"); + goto pass_reasm_cancel; + } + if (ReasmIsFull(&ctrack->reasm_client)) + { + replay_queue(&ctrack->delayed); + reasm_client_fin(ctrack); + } + return VERDICT_DROP; + } + } + } } if (bHaveHost)