Getting pairs of packets from the client-server communications.
authorrtrimana <rtrimana@uci.edu>
Fri, 15 Jun 2018 18:29:37 +0000 (11:29 -0700)
committerrtrimana <rtrimana@uci.edu>
Fri, 15 Jun 2018 18:29:37 +0000 (11:29 -0700)
Code/Projects/SmartPlugDetector/.idea/modules/SmartPlugDetector.iml
Code/Projects/SmartPlugDetector/.idea/modules/SmartPlugDetector_main.iml
Code/Projects/SmartPlugDetector/.idea/modules/SmartPlugDetector_test.iml
Code/Projects/SmartPlugDetector/.idea/vcs.xml [new file with mode: 0644]
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/ConversationPair.java [new file with mode: 0644]
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/FlowPatternFinder.java
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Main.java

index 3451475bf424c5d13ad11cfa1c5a3a2de81423fd..202c5acf66a4e5a6a14730748b747a21fda9c373 100644 (file)
@@ -5,6 +5,7 @@
     <content url="file://$MODULE_DIR$/../..">
       <excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
       <excludeFolder url="file://$MODULE_DIR$/../../build" />
+      <excludeFolder url="file://$MODULE_DIR$/../../out" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
index 802e727eb81d81a2a8f7888fba69c05b073e89c6..0932ae09f252045eb7dd24107daed23c34b62067 100644 (file)
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module external.linked.project.id="SmartPlugDetector:main" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="edu.uci.iotproject" external.system.module.type="sourceSet" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/../../build/classes/main" />
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output url="file://$MODULE_DIR$/../../out/production/classes" />
     <exclude-output />
     <content url="file://$MODULE_DIR$/../../src/main">
       <sourceFolder url="file://$MODULE_DIR$/../../src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/../../src/main/resources" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
index 98985cef83b7ac3c02d3f661091c07870c6c8251..f4752a0d54ef41f4b37288936744d5fa41272462 100644 (file)
@@ -1,12 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module external.linked.project.id="SmartPlugDetector:test" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="edu.uci.iotproject" external.system.module.type="sourceSet" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
-    <output-test url="file://$MODULE_DIR$/../../build/classes/test" />
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output-test url="file://$MODULE_DIR$/../../out/test/classes" />
     <exclude-output />
-    <content url="file://$MODULE_DIR$/../../src/test">
-      <sourceFolder url="file://$MODULE_DIR$/../../src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/../../src/test/resources" type="java-test-resource" />
-    </content>
+    <content url="file://$MODULE_DIR$/../../src/test" />
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="SmartPlugDetector_main" />
diff --git a/Code/Projects/SmartPlugDetector/.idea/vcs.xml b/Code/Projects/SmartPlugDetector/.idea/vcs.xml
new file mode 100644 (file)
index 0000000..c2365ab
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/ConversationPair.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/ConversationPair.java
new file mode 100644 (file)
index 0000000..7d5ddb6
--- /dev/null
@@ -0,0 +1,108 @@
+package edu.uci.iotproject;
+
+import org.pcap4j.core.PcapHandle;
+import org.pcap4j.core.PcapPacket;
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Models a (TCP) conversation/connection/session/flow (packet's belonging to the same session between a client and a
+ * server).
+ * Holds a pair of packet lengths from {@link PcapPacket}s identified as pertaining to the flow.
+ * Here we consider pairs of packet lengths, e.g., from device to cloud and cloud to device.
+ * We collect these pairs of data points as signatures that we can plot on a graph.
+ *
+ * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
+ * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
+ */
+public class ConversationPair {
+
+    /* Begin instance properties */
+    /**
+     * The PrintWriter object that writes data points into file
+     */
+    private PrintWriter pw;
+
+    /**
+     * The direction of conversation
+     * true = device to server to device
+     */
+    private Direction direction;
+
+    /**
+     * If this is the first packet processed then the value is true (it is false otherwise).
+     */
+    private boolean firstPacket;
+
+    /**
+     * Four possible directions of conversations.
+     * E.g., DEVICE_TO_SERVER means the conversation is started from
+     * a device-server packet and then a server-device as a response.
+     * SERVER_TO_DEVICE means the conversation is started from a
+     * server-device packet and then a device-server packet as a response.
+     * The same pattern applies to PHONE_TO_SERVER and SERVER_TO_PHONE
+     * directions.
+     */
+    public enum Direction {
+        DEVICE_TO_SERVER,
+        SERVER_TO_DEVICE,
+        PHONE_TO_SERVER,
+        SERVER_TO_PHONE
+    }
+
+    /**
+     * Constructs a ConversationPair object.
+     * @param fileName The file name to write data points into.
+     * @param direction The direction of the first packet of the pair.
+     */
+    public ConversationPair(String fileName, Direction direction) {
+        try {
+            this.pw = new PrintWriter(fileName, "UTF-8");
+            this.direction = direction;
+            this.firstPacket = true;
+        } catch(UnsupportedEncodingException |
+                FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Writes conversation pair's packet lengths.
+     * @param packet The {@link PcapPacket} object that has packet information.
+     * @param fromClient If true then this packet comes from client, e.g., device.
+     * @param fromServer If true then this packet comes from server.
+     */
+    public void writeConversationPair(PcapPacket packet, boolean fromClient, boolean fromServer) {
+
+        // Write device data point first and then server
+        if (direction == Direction.DEVICE_TO_SERVER || direction == Direction.PHONE_TO_SERVER) {
+            if (fromClient && firstPacket) { // first packet
+                pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+                System.out.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+                firstPacket = false;
+            } else if (fromServer && !firstPacket) { // second packet
+                pw.println(packet.getPayload().length());
+                System.out.println(packet.getPayload().length());
+                firstPacket = true;
+            }
+        // Write server data point first and then device
+        } else if (direction == Direction.SERVER_TO_DEVICE || direction == Direction.SERVER_TO_PHONE) {
+            if (fromServer && firstPacket) { // first packet
+                pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+                firstPacket = false;
+            } else if (fromClient && !firstPacket) { // second packet
+                pw.println(packet.getPayload().length());
+                firstPacket = true;
+            }
+        }
+    }
+
+    /**
+     * Close the PrintWriter object.
+     */
+    public void close() {
+        pw.close();
+    }
+}
\ No newline at end of file
index 27c35273ddce410c636880ef987afe4f60b1018e..4e3bc1a0f5d903ff878dd605861b7d1acbfad2fe 100644 (file)
@@ -59,6 +59,8 @@ public class FlowPatternFinder {
     private final DnsMap mDnsMap;
     private final PcapHandle mPcap;
     private final FlowPattern mPattern;
+    private final ConversationPair mConvPair;
+    private final String FILE = "./datapoints.csv";
 
     private final List<Future<CompleteMatchPatternComparisonResult>> mPendingComparisons = new ArrayList<>();
     /* End instance properties */
@@ -75,6 +77,7 @@ public class FlowPatternFinder {
                 String.format("Argument of type '%s' cannot be null", PcapHandle.class.getSimpleName()));
         this.mPattern = Objects.requireNonNull(pattern,
                 String.format("Argument of type '%s' cannot be null", FlowPattern.class.getSimpleName()));
+        this.mConvPair = new ConversationPair(FILE, ConversationPair.Direction.DEVICE_TO_SERVER);
     }
 
     /**
@@ -140,7 +143,10 @@ public class FlowPatternFinder {
                 }
                 // Note: does not make sense to call attemptAcknowledgementOfFin here as the new packet has no FINs
                 // in its list, so if this packet is an ACK, it would not be added anyway.
-
+                // Record the conversation pairs
+                if (tcpPacket.getPayload() != null) {
+                    mConvPair.writeConversationPair(packet, fromClient, fromServer);
+                }
                 // Need to retain a final reference to get access to the packet in the lambda below.
                 final PcapPacket finalPacket = packet;
                 // Add the new conversation to the map if an equal entry is not already present.
@@ -171,10 +177,12 @@ public class FlowPatternFinder {
                             new PatternComparisonTask<>(conversation, mPattern, ComparisonFunctions.SUB_SEQUENCE_COMPLETE_MATCH);
                     mPendingComparisons.add(EXECUTOR_SERVICE.submit(comparisonTask));
                     // Increment hostIndex to find the next
-                    
+
                 }
             }
         } catch (EOFException eofe) {
+            mConvPair.close();
+            System.out.println("[ findFlowPattern ] ConversationPair writer closed!");
             // TODO should check for leftover conversations in map here and fire tasks for those.
             // TODO [cont'd] such tasks may be present if connections did not terminate gracefully or if there are longlived connections.
             System.out.println("[ findFlowPattern ] Finished processing entire PCAP stream!");
index 9696bd6d56053e2d34a576e042a08b77a00fe2a6..c94f335e6395d7cf326bbfa251b3d72c28b07364 100644 (file)
@@ -25,33 +25,33 @@ public class Main {
     public static void main(String[] args) throws PcapNativeException, NotOpenException, EOFException, TimeoutException, UnknownHostException {
         // -------------------------------------------------------------------------------------------------------------
         // Example/debug code for searching for a pattern at the MAC layer.
-        String fileName = "./pcap/mac-tplink.local.pcapng";
-        PcapHandle handle;
-        try {
-            handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
-        } catch (PcapNativeException pne) {
-            handle = Pcaps.openOffline(fileName);
-        }
-//        Arrays.asList(1590, 1590, 1590, 1001, 337, 197, 636, 1311, 177) // Full pattern (all non-zero payload packets).
-        MacLayerFlowPattern pattern = new MacLayerFlowPattern("TP_LINK_LOCAL_OFF_MAC", "50:c7:bf:33:1f:09", Arrays.asList(637, 1312));
-        MacLayerFlowPatternFinder finder = new MacLayerFlowPatternFinder(handle, pattern);
-        finder.findFlowPattern();
-        // -------------------------------------------------------------------------------------------------------------
-
-//        final String fileName = args.length > 0 ? args[0] : "/home/rtrimana/pcap_processing/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.remote.dns.pcap";
-//        final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON_SUBSET.pcap";
-//        //final String trainingFileName = "./pcap/TP_LINK_REMOTE_ON.pcap";
-//
-//        // ====== Debug code ======
+//        String fileName = "./pcap/mac-tplink.local.pcapng";
 //        PcapHandle handle;
-//        PcapHandle trainingPcap;
 //        try {
 //            handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
-//            trainingPcap = Pcaps.openOffline(trainingFileName, PcapHandle.TimestampPrecision.NANO);
 //        } catch (PcapNativeException pne) {
 //            handle = Pcaps.openOffline(fileName);
-//            trainingPcap = Pcaps.openOffline(trainingFileName);
 //        }
+//        Arrays.asList(1590, 1590, 1590, 1001, 337, 197, 636, 1311, 177) // Full pattern (all non-zero payload packets).
+//        MacLayerFlowPattern pattern = new MacLayerFlowPattern("TP_LINK_LOCAL_OFF_MAC", "50:c7:bf:33:1f:09", Arrays.asList(637, 1312));
+//        MacLayerFlowPatternFinder finder = new MacLayerFlowPatternFinder(handle, pattern);
+//        finder.findFlowPattern();
+        // -------------------------------------------------------------------------------------------------------------
+
+        final String fileName = args.length > 0 ? args[0] : "/home/rtrimana/pcap_processing/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.dns.pcap";
+        final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON_SUBSET.pcap";
+//        final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON.pcap";
+//
+//        // ====== Debug code ======
+        PcapHandle handle;
+        PcapHandle trainingPcap;
+        try {
+            handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
+            trainingPcap = Pcaps.openOffline(trainingFileName, PcapHandle.TimestampPrecision.NANO);
+        } catch (PcapNativeException pne) {
+            handle = Pcaps.openOffline(fileName);
+            trainingPcap = Pcaps.openOffline(trainingFileName);
+        }
 //
 //        // TODO: The followings are the way to extract multiple hostnames and their associated packet lengths lists
 //        //List<String> list = new ArrayList<>();
@@ -62,9 +62,9 @@ public class Main {
 //        //list2.add("events.tplinkra.com");
 //        //FlowPattern fp3 = new FlowPattern("TP_LINK_REMOTE_ON", list2, trainingPcap);
 //
-//        FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", "events.tplinkra.com", trainingPcap);
-//        FlowPatternFinder fpf = new FlowPatternFinder(handle, fp);
-//        fpf.start();
+        FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", "events.tplinkra.com", trainingPcap);
+        FlowPatternFinder fpf = new FlowPatternFinder(handle, fp);
+        fpf.start();
 //
 //        // ========================
     }