import java.time.format.FormatStyle;
import java.util.*;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Detects an event signature that spans one or multiple TCP connections.
// Test client
public static void main(String[] args) throws PcapNativeException, NotOpenException {
- String path = "/scratch/July-2018"; // Rahmadi
- //String path = "/Users/varmarken/temp/UCI IoT Project/experiments"; // Janus
+ if (args.length < 3) {
+ String errMsg = String.format("Usage: %s inputPcapFile onSignatureFile offSignatureFile",
+ SignatureDetector.class.getSimpleName());
+ System.out.println(errMsg);
+ return;
+ }
+ final String inputPcapFile = args[0];
+ final String onSignatureFile = args[1];
+ final String offSignatureFile = args[2];
+
+// String path = "/scratch/July-2018"; // Rahmadi
+// String path = "/Users/varmarken/temp/UCI IoT Project/experiments"; // Janus
+// String path = "/home/jvarmark/iot_project/datasets"; // Hera (server)
+// String path = "/raid/varmarken/iot_project/datasets"; // Zeus (server)
// No activity test
//final String inputPcapFile = path + "/evaluation/no-activity/no-activity.wlan1.pcap";
// final String inputPcapFile = path + "/UNSW/16-10-10.pcap"; // TODO: Seems to be broken!
// final String inputPcapFile = path + "/UNSW/16-10-11.pcap"; // TODO: Seems to be broken!
-
// final String inputPcapFile = path + "/UNSW/16-09-23.pcap";
// final String inputPcapFile = path + "/UNSW/16-09-24.pcap";
// final String inputPcapFile = path + "/UNSW/16-09-25.pcap";
// final String inputPcapFile = path + "/UNSW/16-09-27.pcap";
// final String inputPcapFile = path + "/UNSW/16-09-29.pcap";
// final String inputPcapFile = path + "/UNSW/16-10-01.pcap";
- final String inputPcapFile = path + "/UNSW/16-10-06.pcap";
+// final String inputPcapFile = path + "/UNSW/16-10-06.pcap";
+ // Negative test: dataset from UNB
+// final String inputPcapFile = path + "/evaluation/negative-datasets/UNB/Monday-WorkingHours_one-local-endpoint.pcap";
// TODO: The following one is very long!!!
// final String inputPcapFile = path + "/UNSW/16-10-12.pcap";
// D-Link Siren PHONE signatures
// final String onSignatureFile = path + "/experimental_result/standalone/dlink-siren/signatures/dlink-siren-onSignature-phone-side.sig";
// final String offSignatureFile = path + "/experimental_result/standalone/dlink-siren/signatures/dlink-siren-offSignature-phone-side.sig";
+// final String onSignatureFile = path + "/training/signatures/dlink-siren/dlink-siren-onSignature-phone-side.sig";
+// final String offSignatureFile = path + "/training/signatures/dlink-siren/dlink-siren-offSignature-phone-side.sig";
// TP-Link Plug experiment
//final String inputPcapFile = path + "/training/tplink-plug/wlan1/tplink-plug.wlan1.local.pcap";
// // SmartThings Plug PHONE signatures
// final String onSignatureFile = path + "/experimental_result/standalone/st-plug/signatures/st-plug-onSignature-phone-side.sig";
// final String offSignatureFile = path + "/experimental_result/standalone/st-plug/signatures/st-plug-offSignature-phone-side.sig";
-
+// final String onSignatureFile = path + "/training/signatures/st-plug/st-plug-onSignature-phone-side.sig";
+// final String offSignatureFile = path + "/training/signatures/st-plug/st-plug-offSignature-phone-side.sig";
// LiFX Bulb experiment
// final String inputPcapFile = path + "/training/lifx-bulb/wlan1/lifx-bulb.wlan1.local.pcap";
// final String inputPcapFile = path + "/experimental_result/smarthome/wemo-insight-plug/wlan1/wemo-insight-plug.wlan1.detection.pcap";
// final String inputPcapFile = path + "/experimental_result/smarthome/wemo-insight-plug/eth0/wemo-insight-plug.eth0.detection.pcap";
// WeMo Insight Plug PHONE signatures
- final String onSignatureFile = path + "/experimental_result/standalone/wemo-insight-plug/signatures/wemo-insight-plug-onSignature-phone-side.sig";
- final String offSignatureFile = path + "/experimental_result/standalone/wemo-insight-plug/signatures/wemo-insight-plug-offSignature-phone-side.sig";
+// final String onSignatureFile = path + "/experimental_result/standalone/wemo-insight-plug/signatures/wemo-insight-plug-onSignature-phone-side.sig";
+// final String offSignatureFile = path + "/experimental_result/standalone/wemo-insight-plug/signatures/wemo-insight-plug-offSignature-phone-side.sig";
// Kwikset Doorlock Sep 12 experiment
//// // Kwikset Door lock PHONE signatures
// final String onSignatureFile = path + "/experimental_result/standalone/kwikset-doorlock/signatures/kwikset-doorlock-onSignature-phone-side.sig";
// final String offSignatureFile = path + "/experimental_result/standalone/kwikset-doorlock/signatures/kwikset-doorlock-offSignature-phone-side.sig";
+// final String onSignatureFile = path + "/training/signatures/kwikset-doorlock/kwikset-doorlock-onSignature-phone-side.sig";
+// final String offSignatureFile = path + "/training/signatures/kwikset-doorlock/kwikset-doorlock-offSignature-phone-side.sig";
- /*
// D-Link Siren experiment
- final String inputPcapFile = path + "/2018-08/dlink-siren/dlink-siren.wlan1.local.pcap";
+// final String inputPcapFile = path + "/2018-08/dlink-siren/dlink-siren.wlan1.local.pcap";
// D-Link Siren DEVICE signatures
//final String onSignatureFile = path + "/2018-08/dlink-siren/onSignature-DLink-Siren-device.sig";
//final String offSignatureFile = path + "/2018-08/dlink-siren/offSignature-DLink-Siren-device.sig";
// D-Link Siren PHONE signatures
- final String onSignatureFile = path + "/2018-08/dlink-siren/onSignature-DLink-Siren-phone.sig";
- final String offSignatureFile = path + "/2018-08/dlink-siren/offSignature-DLink-Siren-phone.sig";
- */
+// final String onSignatureFile = path + "/2018-08/dlink-siren/onSignature-DLink-Siren-phone.sig";
+// final String offSignatureFile = path + "/2018-08/dlink-siren/offSignature-DLink-Siren-phone.sig";
+
+
+ // Output file names used (to make it easy to catch if one forgets to change them)
+ System.out.println("ON signature file in use is " + onSignatureFile);
+ System.out.println("OFF signature file in use is " + offSignatureFile);
+ System.out.println("PCAP file that is the target of detection is " + inputPcapFile);
List<List<List<PcapPacket>>> onSignature = PrintUtils.deserializeSignatureFromFile(onSignatureFile);
List<List<List<PcapPacket>>> offSignature = PrintUtils.deserializeSignatureFromFile(offSignatureFile);
// LAN
-// SignatureDetector onDetector = new SignatureDetector(onSignature, null);
-// SignatureDetector offDetector = new SignatureDetector(offSignature, null);
+ SignatureDetector onDetector = new SignatureDetector(onSignature, null);
+ SignatureDetector offDetector = new SignatureDetector(offSignature, null);
// WAN
- SignatureDetector onDetector = new SignatureDetector(onSignature, "128.195.205.105");
- SignatureDetector offDetector = new SignatureDetector(offSignature, "128.195.205.105");
+// SignatureDetector onDetector = new SignatureDetector(onSignature, "128.195.205.105");
+// SignatureDetector offDetector = new SignatureDetector(offSignature, "128.195.205.105");
final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).
withLocale(Locale.US).withZone(ZoneId.of("America/Los_Angeles"));
// times file.
Collections.sort(detectedEvents, Comparator.comparing(UserAction::getTimestamp));
-
// Output the detected events
- //detectedEvents.forEach(outputter);
+ detectedEvents.forEach(outputter);
+
+ System.out.println("Number of detected events of type " + UserAction.Type.TOGGLE_ON + ": " +
+ detectedEvents.stream().filter(ua -> ua.getType() == UserAction.Type.TOGGLE_ON).count());
+ System.out.println("Number of detected events of type " + UserAction.Type.TOGGLE_OFF + ": " +
+ detectedEvents.stream().filter(ua -> ua.getType() == UserAction.Type.TOGGLE_OFF).count());
+
// TODO: Temporary clean up until we clean the pipeline
- List<UserAction> cleanedDetectedEvents = SignatureDetector.removeDuplicates(detectedEvents);
- cleanedDetectedEvents.forEach(outputter);
+// List<UserAction> cleanedDetectedEvents = SignatureDetector.removeDuplicates(detectedEvents);
+// cleanedDetectedEvents.forEach(outputter);
}
/**
--- /dev/null
+package edu.uci.iotproject.evaluation;
+
+import edu.uci.iotproject.Conversation;
+import edu.uci.iotproject.TcpReassembler;
+import edu.uci.iotproject.io.PcapHandleReader;
+import edu.uci.iotproject.util.PrintUtils;
+import org.pcap4j.core.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Hacky utility for producing a sanity signature for negative test sets.
+ * <p>
+ * More precisely, given information about packet lengths and packet directions known to be present in an input trace,
+ * this class locates the first occurrence of a matching sequence in the input trace and outputs it to a file in the
+ * signature format (i.e., a {@code List<List<List<PcapPacket>>>}.
+ * </p>
+ * <p>
+ * Note: can only produce simplistic signatures, i.e., a signature that is a <em>single</em> packet sequence that
+ * occurs on a single TCP connection.
+ * </p>
+ *
+ *
+ * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
+ * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
+ */
+public class SanitySignatureGenerator {
+
+ public static void main(String[] args) throws PcapNativeException, NotOpenException {
+ // The pcap file
+ final String pcapPath = "/Users/varmarken/temp/UCI IoT Project/experiments/evaluation/negative-datasets/UNB/Monday-WorkingHours_one-local-endpoint.pcap";
+ final String sigOutputPath = "/Users/varmarken/temp/UCI IoT Project/experiments/evaluation/negative-datasets/UNB/Monday-WorkingHours_one-local-endpoint_sanity.sig";
+ // The sequence of packet lengths known to be present in the trace
+ final List<Integer> pktLengths = new ArrayList<>();
+ pktLengths.add(340);
+ pktLengths.add(295);
+ // ...and their corresponding directions
+ final List<Conversation.Direction> pktDirections = new ArrayList<>();
+ pktDirections.add(Conversation.Direction.CLIENT_TO_SERVER);
+ pktDirections.add(Conversation.Direction.SERVER_TO_CLIENT);
+ // Is the signature a TLS sequence?
+ final boolean tlsSequence = false;
+
+
+ PcapHandle handle;
+ try {
+ handle = Pcaps.openOffline(pcapPath, PcapHandle.TimestampPrecision.NANO);
+ } catch (PcapNativeException pne) {
+ handle = Pcaps.openOffline(pcapPath);
+ }
+ SequenceFinder seqFinder = new SequenceFinder(pktLengths, pktDirections, tlsSequence, sigOutputPath);
+ final PcapHandleReader reader = new PcapHandleReader(handle, p -> true, seqFinder);
+ seqFinder.setPcapHandleReader(reader);
+ reader.readFromHandle();
+ }
+
+
+ private static class SequenceFinder implements PacketListener {
+ private final TcpReassembler mTcpReassembler = new TcpReassembler();
+ private final List<Integer> mPktLengths;
+ private final List<Conversation.Direction> mPktDirections;
+ private final boolean mTlsSequence;
+ private PcapHandleReader mReader;
+ private final String mSignatureOutputPath;
+
+ private SequenceFinder(List<Integer> pktLengths,
+ List<Conversation.Direction> pktDirections,
+ boolean tlsSequence,
+ String sigOutputPath) {
+ mPktLengths = pktLengths;
+ mPktDirections = pktDirections;
+ mTlsSequence = tlsSequence;
+ mSignatureOutputPath = sigOutputPath;
+ }
+
+ @Override
+ public void gotPacket(PcapPacket packet) {
+ // Skip packets not matching expected length
+ if (!mPktLengths.contains(packet.getOriginalLength())) {
+ return;
+ }
+ // Otherwise forward to TCP reassembler.
+ mTcpReassembler.gotPacket(packet);
+ // We are done as soon as we have one conversation that has the expected number of packets with the expected
+ // directions.
+ Optional<Conversation> match = mTcpReassembler.getTcpConversations().stream().filter(c -> {
+ List<PcapPacket> cPkts = mTlsSequence ? c.getTlsApplicationDataPackets() : c.getPackets();
+ if (cPkts.size() != mPktLengths.size()) {
+ return false;
+ }
+ for (int i = 0; i < cPkts.size(); i++) {
+ if (c.getDirection(cPkts.get(i)) != mPktDirections.get(i) ||
+ cPkts.get(i).getOriginalLength() != mPktLengths.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }).findFirst();
+ if (match.isPresent()) {
+ System.out.println("match found");
+ // Terminate reader; no need to process the full file as we already have the data to produce the signature.
+ mReader.stopReading();
+ // Convert sequence to signature format.
+ List<List<List<PcapPacket>>> signature = new ArrayList<>();
+ List<List<PcapPacket>> cluster = new ArrayList<>();
+ List<PcapPacket> sequence = mTlsSequence ? match.get().getTlsApplicationDataPackets() : match.get().getPackets();
+ cluster.add(sequence);
+ signature.add(cluster);
+ // Output the signature to a file.
+ PrintUtils.serializeSignatureIntoFile(mSignatureOutputPath, signature);
+ }
+ }
+
+ private void setPcapHandleReader(PcapHandleReader reader) {
+ mReader = reader;
+ }
+ }
+
+}