From: Janus Varmarken Date: Wed, 25 Jul 2018 22:16:21 +0000 (-0700) Subject: Implement grouping of conversations by hostname X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f358b412fc0db65931289c0ef169944379fc8fb0;p=pingpong.git Implement grouping of conversations by hostname --- diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/DnsMap.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/DnsMap.java index d88f0cf..0db01f8 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/DnsMap.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/DnsMap.java @@ -103,4 +103,9 @@ public class DnsMap implements PacketListener { public boolean isRelatedToCloudServer(String address, String hostname) { return ipToHostnameMap.getOrDefault(address, EMPTY_SET).contains(hostname); } + + public Set getHostnamesForIp(String ip) { + Set hostnames = ipToHostnameMap.get(ip); + return hostnames != null ? Collections.unmodifiableSet(hostnames) : null; + } } diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Main.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Main.java index c96e36a..4a05501 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Main.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Main.java @@ -11,10 +11,7 @@ import org.pcap4j.packet.namednumber.DataLinkType; import java.io.EOFException; import java.net.UnknownHostException; import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.concurrent.TimeoutException; /** @@ -222,7 +219,9 @@ public class Main { } System.out.println("packet length frequency map created"); - + Map> hostnameConversationMap = + TcpConversationUtils.groupConversationsByHostname(tcpReassembler.getTcpConversations(), dnsMap); + System.out.println("hostnameConversationMap created"); // ---------------------------- } diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/analysis/TcpConversationUtils.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/analysis/TcpConversationUtils.java index a598f81..2f5f415 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/analysis/TcpConversationUtils.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/analysis/TcpConversationUtils.java @@ -1,13 +1,13 @@ package edu.uci.iotproject.analysis; import edu.uci.iotproject.Conversation; +import edu.uci.iotproject.DnsMap; import edu.uci.iotproject.util.PcapPacketUtils; import org.pcap4j.core.PcapPacket; import org.pcap4j.packet.IpV4Packet; import org.pcap4j.packet.TcpPacket; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * TODO add class documentation. @@ -48,4 +48,53 @@ public class TcpConversationUtils { // TODO: what if there is long time between response and reply packet? Should we add a threshold and exclude those cases? } + + public static Map> groupConversationsByHostname(List tcpConversations, DnsMap ipHostnameMappings) { + HashMap> result = new HashMap<>(); + for (Conversation c : tcpConversations) { + if (c.getPackets().size() == 0) { + String warningStr = String.format("Detected a %s [%s] with no payload packets.", + c.getClass().getSimpleName(), c.toString()); + System.err.println(warningStr); + continue; + } + IpV4Packet firstPacketIp = c.getPackets().get(0).get(IpV4Packet.class); + String ipSrc = firstPacketIp.getHeader().getSrcAddr().getHostAddress(); + String ipDst = firstPacketIp.getHeader().getDstAddr().getHostAddress(); + // Check if src or dst IP is associated with one or more hostnames. + Set hostnames = ipHostnameMappings.getHostnamesForIp(ipSrc); + if (hostnames == null) { + // No luck with src ip (possibly because it's a client->srv packet), try dst ip. + hostnames = ipHostnameMappings.getHostnamesForIp(ipDst); + } + if (hostnames != null) { + // Put a reference to the conversation for each of the hostnames that the conversation's IP maps to. + for (String hostname : hostnames) { + List newValue = new ArrayList<>(); + newValue.add(c); + result.merge(hostname, newValue, (l1, l2) -> { l1.addAll(l2); return l1; }); + } + if (hostnames.size() > 1) { + // Print notice of IP mapping to multiple hostnames (debugging) + System.err.println(String.format("%s: encountered an IP that maps to multiple (%d) hostnames", + TcpConversationUtils.class.getSimpleName(), hostnames.size())); + } + } else { + // If no hostname mapping, store conversation under the key that is the concatenation of the two IPs. + // In order to ensure consistency when mapping conversations, use lexicographic order to select which IP + // goes first. + String delimiter = "_"; + // Note that the in case the comparison returns 0, the strings are equal, so it doesn't matter which of + // ipSrc and ipDst go first (also, this case should not occur in practice as it means that the device is + // communicating with itself!) + String key = ipSrc.compareTo(ipDst) <= 0 ? ipSrc + delimiter + ipDst : ipDst + delimiter + ipSrc; + List newValue = new ArrayList<>(); + newValue.add(c); + result.merge(key, newValue, (l1, l2) -> { l1.addAll(l2); return l1; }); + } + } + return result; + } + + }