From 57d683fd787625aa21656cb256d21f844ed2d41f Mon Sep 17 00:00:00 2001 From: Alfredo Cardigliano Date: Mon, 16 Sep 2024 16:25:17 +0200 Subject: [PATCH] Parse WLAN_SSID and WTP_MAC_ADDRESS from flows and visualize them in flow details --- include/Flow.h | 5 +++++ include/ParsedFlow.h | 8 ++++++++ scripts/lua/flow_details.lua | 13 ++++++++++++ src/Flow.cpp | 40 ++++++++++++++++++++++++++++++++++++ src/ParsedFlow.cpp | 10 +++++++++ src/ParserInterface.cpp | 3 +++ src/ZMQParserInterface.cpp | 36 +++++++++++++++++++++++++------- 7 files changed, 108 insertions(+), 7 deletions(-) diff --git a/include/Flow.h b/include/Flow.h index b812c55944c5..d3660738db7f 100644 --- a/include/Flow.h +++ b/include/Flow.h @@ -78,6 +78,8 @@ class Flow : public GenericHashEntry { } predominant_alert_info; char *json_protocol_info, *riskInfo, *end_reason; + char *wlan_ssid; + u_int8_t wtp_mac_address[6]; /* Calculate the entropy on the first MAX_ENTROPY_BYTES bytes */ struct { @@ -1330,6 +1332,9 @@ inline float get_goodput_bytes_thpt() const { return (goodput_bytes_thpt); }; void setFlowRiskName(char *r); char *getFlowRiskName(); void getJSONRiskInfo(ndpi_serializer *serializer); + void setWLANInfo(char *wlan_ssid, u_int8_t *wtp_mac_address); + char *getWLANSSID() { return (wlan_ssid); }; + u_int8_t *getWTPMACAddress() { return (wtp_mac_address); }; inline FlowTrafficStats *getTrafficStats() { return (&stats); }; inline char *get_custom_category_file() const { diff --git a/include/ParsedFlow.h b/include/ParsedFlow.h index 765eb188e1ee..11f56a0b1105 100644 --- a/include/ParsedFlow.h +++ b/include/ParsedFlow.h @@ -53,6 +53,8 @@ class ParsedFlow : public ParsedFlowCore, public ParsedeBPF { ndpi_risk ndpi_flow_risk_bitmap; char *ndpi_flow_risk_name; FlowSource flow_source; + char *wlan_ssid; + u_int8_t wtp_mac_address[6]; public: ParsedFlow(); @@ -132,6 +134,9 @@ class ParsedFlow : public ParsedFlowCore, public ParsedeBPF { inline void setPreNATDstPort(u_int16_t v) { dst_port_pre_nat = v; }; inline void setPostNATSrcPort(u_int16_t v) { src_port_post_nat = v; }; inline void setPostNATDstPort(u_int16_t v) { dst_port_post_nat = v; }; + inline void setWLANSSID(const char *str) { if(wlan_ssid != NULL) free(wlan_ssid); if(str) { wlan_ssid = strdup(str);} else wlan_ssid = NULL; } + inline void setWTPMACAddress(const char *str) { Utils::parseMac(wtp_mac_address, str); } + /* ****** */ inline char* getL7Info(bool setToNULL = false) { char *r = l7_info; if(setToNULL) l7_info = NULL; return(r); } inline char* getHTTPurl(bool setToNULL = false) { char *r = http_url; if(setToNULL) http_url = NULL; return(r); } @@ -149,6 +154,9 @@ class ParsedFlow : public ParsedFlowCore, public ParsedeBPF { inline char* getSMTPMailFrom(bool setToNull = false) { char *r = smtp_mail_from; if(setToNull) smtp_mail_from = NULL; return(r); } inline char* getDHCPClientName(bool setToNull = false) { char *r = dhcp_client_name; if(setToNull) dhcp_client_name = NULL; return(r); } inline char* getSIPCallId(bool setToNull = false) { char *r = sip_call_id; if(setToNull) sip_call_id = NULL; return(r); } + inline char* getWLANSSID(bool setToNull = false) { char *r = wlan_ssid; if(setToNull) wlan_ssid = NULL; return(r); } + inline u_int8_t *getWTPMACAddress() { return wtp_mac_address; } + inline u_int32_t getPreNATSrcIp() { return src_ip_addr_pre_nat; }; inline u_int32_t getPreNATDstIp() { return dst_ip_addr_pre_nat; }; inline u_int32_t getPostNATSrcIp() { return src_ip_addr_post_nat; }; diff --git a/scripts/lua/flow_details.lua b/scripts/lua/flow_details.lua index 104741c0ef30..628fa1f71403 100644 --- a/scripts/lua/flow_details.lua +++ b/scripts/lua/flow_details.lua @@ -2010,6 +2010,19 @@ else end end + if flow.wlan then + if flow.wlan.ssid then + print("" .. getFlowKey('WLAN_SSID') .. "") + print("" .. flow.wlan["ssid"] .. "") + print("\n") + end + if flow.wlan.wtp_mac_address then + print("" .. getFlowKey('WTP_MAC_ADDRESS') .. "") + print("" .. flow.wlan["wtp_mac_address"] .. "") + print("\n") + end + end + if (flow.flow_payload ~= nil) then local idx diff --git a/src/Flow.cpp b/src/Flow.cpp index 8a8e70ad6134..da3df1719da5 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -103,6 +103,8 @@ Flow::Flow(NetworkInterface *_iface, ndpiFlowRiskName = NULL; viewFlowStats = NULL, suspicious_dga_domain = NULL; flow_payload = NULL, flow_payload_len = 0; + wlan_ssid = NULL; + memset(wtp_mac_address, 0, sizeof(wtp_mac_address)); last_db_dump.partial = NULL; last_db_dump.first_seen = last_db_dump.last_seen = 0; @@ -422,6 +424,7 @@ Flow::~Flow() { if (riskInfo) free(riskInfo); if (end_reason) free(end_reason); + if (wlan_ssid) free(wlan_ssid); if (viewFlowStats) delete (viewFlowStats); if (periodic_stats_update_partial) delete (periodic_stats_update_partial); if (last_db_dump.partial) delete (last_db_dump.partial); @@ -3004,6 +3007,20 @@ void Flow::lua(lua_State *vm, AddressTree *ptree, DetailsLevel details_level, if (end_reason) lua_push_str_table_entry(vm, "flow_end_reason", getEndReason()); + if (wlan_ssid) { + char mac_buf[20]; + + lua_newtable(vm); + + lua_push_str_table_entry(vm, "ssid", wlan_ssid); + lua_push_str_table_entry(vm, "wtp_mac_address", + Utils::formatMac(wtp_mac_address, mac_buf, sizeof(mac_buf))); + + lua_pushstring(vm, "wlan"); + lua_insert(vm, -2); + lua_settable(vm, -3); + } + if (isSMTP() /* Discard SMTP connections that become TLS as the SMTP part is not populated */ && (!isSMTPS())) { @@ -3961,6 +3978,19 @@ void Flow::formatGenericFlow(json_object *my_object) { sizeof(jsonbuf)), json_object_new_string(end_reason)); + if (wlan_ssid) { + char mac_buf[20]; + json_object_object_add(my_object, + Utils::jsonLabel(WLAN_SSID, "WLAN_SSID", jsonbuf, + sizeof(jsonbuf)), + json_object_new_string(wlan_ssid)); + json_object_object_add(my_object, + Utils::jsonLabel(WTP_MAC_ADDRESS, "WTP_MAC_ADDRESS", jsonbuf, + sizeof(jsonbuf)), + json_object_new_string(Utils::formatMac(wtp_mac_address, mac_buf, + sizeof(mac_buf)))); + } + if (protocol == IPPROTO_TCP) { json_object_object_add(my_object, Utils::jsonLabel(TCP_FLAGS, "TCP_FLAGS", jsonbuf, sizeof(jsonbuf)), @@ -8290,6 +8320,16 @@ char *Flow::getEndReason() { return (end_reason); } /* *************************************** */ +void Flow::setWLANInfo(char *_wlan_ssid, u_int8_t *_wtp_mac_address) { + if (_wlan_ssid) { + if (wlan_ssid) free(wlan_ssid); + wlan_ssid = strdup(_wlan_ssid); + } + memcpy(wtp_mac_address, _wtp_mac_address, 6); +} + +/* *************************************** */ + void Flow::setSMTPMailFrom(char *r) { if (!r) return; diff --git a/src/ParsedFlow.cpp b/src/ParsedFlow.cpp index 05fcba31cc75..63cc78f7595f 100644 --- a/src/ParsedFlow.cpp +++ b/src/ParsedFlow.cpp @@ -53,6 +53,8 @@ ParsedFlow::ParsedFlow() : ParsedFlowCore(), ParsedeBPF() { src_ip_addr_pre_nat = dst_ip_addr_pre_nat = src_ip_addr_post_nat = dst_ip_addr_post_nat = 0; memset(&custom_app, 0, sizeof(custom_app)); + wlan_ssid = NULL; + memset(&wtp_mac_address, 0, sizeof(wtp_mac_address)); has_parsed_ebpf = false; } @@ -150,6 +152,13 @@ ParsedFlow::ParsedFlow(const ParsedFlow &pf) : ParsedFlowCore(pf), ParsedeBPF(pf else sip_call_id = NULL; + if(pf.wlan_ssid) + wlan_ssid = strdup(pf.wlan_ssid); + else + wlan_ssid = NULL; + + memcpy(&wtp_mac_address, &pf.wtp_mac_address, sizeof(wtp_mac_address)); + tls_cipher = pf.tls_cipher; tls_unsafe_cipher = pf.tls_unsafe_cipher; ndpi_flow_risk_bitmap = pf.ndpi_flow_risk_bitmap; @@ -322,6 +331,7 @@ void ParsedFlow::freeMemory() { if (smtp_mail_from) { free(smtp_mail_from); smtp_mail_from = NULL; } if (dhcp_client_name) { free(dhcp_client_name); dhcp_client_name = NULL; } if (sip_call_id) { free(sip_call_id); sip_call_id = NULL; } + if (wlan_ssid) { free(wlan_ssid); wlan_ssid = NULL; } } /* *************************************** */ diff --git a/src/ParserInterface.cpp b/src/ParserInterface.cpp index 2677ac6c5a44..61a6e7716021 100644 --- a/src/ParserInterface.cpp +++ b/src/ParserInterface.cpp @@ -360,6 +360,9 @@ bool ParserInterface::processFlow(ParsedFlow *zflow) { flow->setTOS(zflow->src_tos, true), flow->setTOS(zflow->dst_tos, false); flow->setRtt(); + if (zflow->getWLANSSID()) + flow->setWLANInfo(zflow->getWLANSSID(), zflow->getWTPMACAddress()); + if(zflow->getSIPCallId()) flow->setSIPCallId(zflow->getSIPCallId()); diff --git a/src/ZMQParserInterface.cpp b/src/ZMQParserInterface.cpp index 5ca345851cae..937d1994d1ab 100644 --- a/src/ZMQParserInterface.cpp +++ b/src/ZMQParserInterface.cpp @@ -76,11 +76,6 @@ ZMQParserInterface::ZMQParserInterface(const char *endpoint, addMapping("IPV6_DST_ADDR", IPV6_DST_ADDR); addMapping("IP_PROTOCOL_VERSION", IP_PROTOCOL_VERSION); addMapping("PROTOCOL", PROTOCOL); - addMapping("L7_PROTO", L7_PROTO, NTOP_PEN); - addMapping("L7_PROTO_NAME", L7_PROTO_NAME, NTOP_PEN); - addMapping("L7_INFO", L7_INFO, NTOP_PEN); - addMapping("L7_CONFIDENCE", L7_CONFIDENCE, NTOP_PEN); - addMapping("L7_ERROR_CODE", L7_ERROR_CODE, NTOP_PEN); addMapping("IN_BYTES", IN_BYTES); addMapping("IN_PKTS", IN_PKTS); addMapping("OUT_BYTES", OUT_BYTES); @@ -90,8 +85,6 @@ ZMQParserInterface::ZMQParserInterface(const char *endpoint, addMapping("EXPORTER_IPV4_ADDRESS", EXPORTER_IPV4_ADDRESS); addMapping("EXPORTER_IPV6_ADDRESS", EXPORTER_IPV6_ADDRESS); addMapping("TOTAL_FLOWS_EXP", TOTAL_FLOWS_EXP); - addMapping("NPROBE_IPV4_ADDRESS", NPROBE_IPV4_ADDRESS, NTOP_PEN); - addMapping("NPROBE_INSTANCE_NAME", NPROBE_INSTANCE_NAME, NTOP_PEN); addMapping("TCP_FLAGS", TCP_FLAGS); addMapping("INITIATOR_PKTS", INITIATOR_PKTS); addMapping("INITIATOR_OCTETS", INITIATOR_OCTETS); @@ -113,6 +106,17 @@ ZMQParserInterface::ZMQParserInterface(const char *endpoint, addMapping("BGP_NEXT_ADJACENT_ASN", BGP_NEXT_ADJACENT_ASN); addMapping("BGP_PREV_ADJACENT_ASN", BGP_PREV_ADJACENT_ASN); addMapping("FLOW_END_REASON", FLOW_END_REASON); + addMapping("WLAN_SSID", WLAN_SSID); + addMapping("WTP_MAC_ADDRESS", WTP_MAC_ADDRESS); + + /* ntop IEs */ + addMapping("L7_PROTO", L7_PROTO, NTOP_PEN); + addMapping("L7_PROTO_NAME", L7_PROTO_NAME, NTOP_PEN); + addMapping("L7_INFO", L7_INFO, NTOP_PEN); + addMapping("L7_CONFIDENCE", L7_CONFIDENCE, NTOP_PEN); + addMapping("L7_ERROR_CODE", L7_ERROR_CODE, NTOP_PEN); + addMapping("NPROBE_IPV4_ADDRESS", NPROBE_IPV4_ADDRESS, NTOP_PEN); + addMapping("NPROBE_INSTANCE_NAME", NPROBE_INSTANCE_NAME, NTOP_PEN); addMapping("OOORDER_IN_PKTS", OOORDER_IN_PKTS, NTOP_PEN); addMapping("OOORDER_OUT_PKTS", OOORDER_OUT_PKTS, NTOP_PEN); addMapping("RETRANSMITTED_IN_PKTS", RETRANSMITTED_IN_PKTS, NTOP_PEN); @@ -896,6 +900,12 @@ bool ZMQParserInterface::parsePENZeroField(ParsedFlow *const flow, case BGP_PREV_ADJACENT_ASN: flow->prev_adjacent_as = value->int_num; break; + case WLAN_SSID: + if (value->string) flow->setWLANSSID(value->string); + break; + case WTP_MAC_ADDRESS: + if (value->string) flow->setWTPMACAddress(value->string); + break; default: ntop->getTrace()->traceEvent(TRACE_INFO, "Skipping no-PEN flow fieldId %u", field); @@ -1454,6 +1464,18 @@ bool ZMQParserInterface::matchPENZeroField(ParsedFlow *const flow, else return (flow->prev_adjacent_as == value->int_num); + case WLAN_SSID: + if (value->string) { + if (flow->getWLANSSID()) + return (!strcmp(value->string, flow->getWLANSSID())); + } + + case WTP_MAC_ADDRESS: { + u_int8_t mac[6]; + Utils::parseMac(mac, value->string); + return (memcmp(flow->getWTPMACAddress(), mac, sizeof(mac)) == 0); + } + default: ntop->getTrace()->traceEvent(TRACE_INFO, "Skipping no-PEN flow fieldId %u", field);