diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h index 9029265bb84..fe8a3816cce 100644 --- a/src/include/ndpi_main.h +++ b/src/include/ndpi_main.h @@ -151,6 +151,7 @@ extern "C" { int ndpi_is_printable_string(char * const str, size_t len); #define NDPI_ENTROPY_ENCRYPTED_OR_RANDOM(entropy) (entropy > 7.0f) float ndpi_entropy(u_int8_t const * const buf, size_t len); + u_int16_t ndpi_calculate_icmp4_checksum(u_int8_t const * const buf, size_t len); void load_common_alpns(struct ndpi_detection_module_struct *ndpi_str); u_int8_t is_a_common_alpn(struct ndpi_detection_module_struct *ndpi_str, const char *alpn_to_check, u_int alpn_to_check_len); diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 335cccba236..8b654e2de30 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -3030,6 +3030,12 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_str, if (NDPI_ENTROPY_ENCRYPTED_OR_RANDOM(flow->entropy) != 0) { ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_ENTROPY); } + + struct ndpi_icmphdr * const icmphdr = (struct ndpi_icmphdr *)packet->payload; + u_int16_t chksm = ndpi_calculate_icmp4_checksum(packet->payload, packet->payload_packet_len); + if (icmphdr->checksum != chksm) { + ndpi_set_risk(ndpi_str, flow, NDPI_MALFORMED_PACKET); + } } } } diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 8cbc2e2df95..26bd348cb78 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -2295,6 +2295,33 @@ float ndpi_entropy(u_int8_t const * const buf, size_t len) { return entropy; } +/* ******************************************************************** */ + +u_int16_t ndpi_calculate_icmp4_checksum(u_int8_t const * const buf, size_t len) { + u_int16_t const * sbuf = (u_int16_t *)buf; + u_int32_t checksum = 0; + + /* + * The first two bytes of the icmp header are required. + * The next two bytes is the checksum, which we want to ignore. + */ + checksum += *sbuf++; len -= 2; /* icmp->type, icmp->code */ + sbuf++; len -= 2; /* icmp->checksum */ + + for (; len > 1; len -= 2) { + checksum += *sbuf++; + } + + if (len == 1) { + checksum += *(u_int8_t *)sbuf; + } + + checksum = (checksum >> 16) + (checksum & 0xFFFF); + checksum += (checksum >> 16); + + return ~checksum; +} + /* ******************************************* */ char* ndpi_get_flow_name(struct ndpi_flow_struct *flow) { diff --git a/tests/pcap/icmp-tunnel.pcap b/tests/pcap/icmp-tunnel.pcap new file mode 100644 index 00000000000..1d2338e93dd Binary files /dev/null and b/tests/pcap/icmp-tunnel.pcap differ diff --git a/tests/result/icmp-tunnel.pcap.out b/tests/result/icmp-tunnel.pcap.out new file mode 100644 index 00000000000..d879183bb39 --- /dev/null +++ b/tests/result/icmp-tunnel.pcap.out @@ -0,0 +1,8 @@ +Guessed flow protos: 0 + +DPI Packets (other): 1 (1.00 pkts/flow) +Confidence DPI : 1 (flows) + +ICMP 863 190810 1 + + 1 ICMP 192.168.154.131:0 <-> 192.168.154.132:0 [proto: 81/ICMP][ClearText][Confidence: DPI][cat: Network/14][448 pkts/98566 bytes <-> 415 pkts/92244 bytes][Goodput ratio: 81/81][1122.51 sec][bytes ratio: 0.033 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 2578/2731 145505/145505 9091/9494][Pkt Len c2s/s2c min/avg/max/stddev: 74/74 220/222 1075/1070 245/245][Risk: ** Malformed Packet **][Risk Score: 10][PLAIN TEXT (OpenSSH5)][Plen Bins: 0,32,24,24,7,3,3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]