Adding coordinates for the SmartThings app button.
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / Main.java
1 package edu.uci.iotproject;
2
3 import edu.uci.iotproject.analysis.PcapPacketPair;
4 import edu.uci.iotproject.analysis.TcpConversationUtils;
5 import edu.uci.iotproject.analysis.TriggerTrafficExtractor;
6 import edu.uci.iotproject.io.TriggerTimesFileReader;
7 import org.pcap4j.core.*;
8 import org.pcap4j.packet.IpV4Packet;
9 import org.pcap4j.packet.namednumber.DataLinkType;
10
11 import java.io.EOFException;
12 import java.net.UnknownHostException;
13 import java.time.Instant;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.concurrent.TimeoutException;
19
20 /**
21  * This is a system that reads PCAP files to compare
22  * patterns of DNS hostnames, packet sequences, and packet
23  * lengths with training data to determine certain events
24  * or actions for smart home devices.
25  *
26  * @author Janus Varmarken
27  * @author Rahmadi Trimananda (rtrimana@uci.edu)
28  * @version 0.1
29  */
30 public class Main {
31
32
33     public static void main(String[] args) throws PcapNativeException, NotOpenException, EOFException, TimeoutException, UnknownHostException {
34         // -------------------------------------------------------------------------------------------------------------
35         // Example/debug code for searching for a pattern at the MAC layer.
36 //        String fileName = "./pcap/mac-tplink.local.pcapng";
37 //        PcapHandle handle;
38 //        try {
39 //            handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
40 //        } catch (PcapNativeException pne) {
41 //            handle = Pcaps.openOffline(fileName);
42 //        }
43 //        Arrays.asList(1590, 1590, 1590, 1001, 337, 197, 636, 1311, 177) // Full pattern (all non-zero payload packets).
44 //        MacLayerFlowPattern pattern = new MacLayerFlowPattern("TP_LINK_LOCAL_OFF_MAC", "50:c7:bf:33:1f:09", Arrays.asList(637, 1312));
45 //        MacLayerFlowPatternFinder finder = new MacLayerFlowPatternFinder(handle, pattern);
46 //        finder.findFlowPattern();
47         // -------------------------------------------------------------------------------------------------------------
48 //
49 //        //final String fileName = args.length > 0 ? args[0] : "/home/rtrimana/pcap_processing/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.dns.pcap";
50 //        final String fileName = args.length > 0 ? args[0] : "/scratch/June-2018/TPLink/wlan1/tplink.wlan1.local.pcap";
51 //        //final String fileName = args.length > 0 ? args[0] : "/scratch/June-2018/DLink/wlan1/dlink.wlan1.local.pcap";
52 //        final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON_SUBSET.pcap";
53 ////        final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON.pcap";
54 ////
55 ////        // ====== Debug code ======
56 //        PcapHandle handle;
57 //        PcapHandle trainingPcap;
58 //        try {
59 //            handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
60 //            trainingPcap = Pcaps.openOffline(trainingFileName, PcapHandle.TimestampPrecision.NANO);
61 //        } catch (PcapNativeException pne) {
62 //            handle = Pcaps.openOffline(fileName);
63 //            trainingPcap = Pcaps.openOffline(trainingFileName);
64 //        }
65 ////
66 ////        // TODO: The followings are the way to extract multiple hostnames and their associated packet lengths lists
67 ////        //List<String> list = new ArrayList<>();
68 ////        //list.add("events.tplinkra.com");
69 ////        //FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", list, trainingPcap);
70 ////        //List<String> list2 = new ArrayList<>();
71 ////        //list2.add("devs.tplinkcloud.com");
72 ////        //list2.add("events.tplinkra.com");
73 ////        //FlowPattern fp3 = new FlowPattern("TP_LINK_REMOTE_ON", list2, trainingPcap);
74 ////
75 //        FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", "events.tplinkra.com", trainingPcap);
76 //        //FlowPattern fp = new FlowPattern("DLINK_LOCAL_ON", "rfe-us-west-1.dch.dlink.com", trainingPcap);
77 //        FlowPatternFinder fpf = new FlowPatternFinder(handle, fp);
78 //        fpf.start();
79 ////
80 ////        // ========================
81
82         /*
83         PcapReader pcapReader = new PcapReader(args[0]);
84         PcapProcessingPipeline pipeline = new PcapProcessingPipeline(pcapReader);
85         TcpReassembler tcpReassembler = new TcpReassembler();
86         pipeline.addPcapPacketConsumer(tcpReassembler);
87         pipeline.executePipeline();
88         System.out.println("Pipeline terminated");
89
90         List<List<PcapPacketPair>> pairs = new ArrayList<>();
91         for (Conversation c : tcpReassembler.getTcpConversations()) {
92             pairs.add(TcpConversationUtils.extractPacketPairs(c));
93         }
94         */
95
96         /*
97         // -------- 07-17-2018 --------
98         // Only consider packets to/from the TP-Link plug.
99         PcapReader pcapReader = new PcapReader(args[0], "ip host 192.168.1.159");
100         TcpReassembler tcpReassembler = new TcpReassembler();
101         PcapPacket packet;
102         while((packet = pcapReader.readNextPacket()) != null) {
103             tcpReassembler.consumePacket(packet);
104         }
105         // Now we have a set of reassembled TCP conversations.
106         List<Conversation> conversations = tcpReassembler.getTcpConversations();
107         for(Conversation c : conversations) {
108             List<PcapPacketPair> pairs = TcpConversationUtils.extractPacketPairs(c);
109             for (PcapPacketPair pair : pairs) {
110                 // TODO ...
111                 // 1. discard packets that are not within X seconds after trigger time
112                 // 2. conversations may be (are) with different servers - so need to plot in different plots, one per hostname?
113             }
114         }
115
116         // ----------------------------
117         */
118
119         // -------- 07-19-2018 --------
120         TriggerTimesFileReader ttfr = new TriggerTimesFileReader();
121         List<Instant> triggerTimes = ttfr.readTriggerTimes("/Users/varmarken/Downloads/tplink-feb-13-2018.timestamps", false);
122 //        triggerTimes.stream().forEach(i -> System.out.println(i.atZone(TriggerTimesFileReader.ZONE_ID_LOS_ANGELES).toString()));
123         String pcapFile = "/Users/varmarken/Development/Repositories/UCI/NetworkingGroup/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.dns.pcap";
124         String tpLinkPlugIp = "192.168.1.159";
125         TriggerTrafficExtractor tte = new TriggerTrafficExtractor(pcapFile, triggerTimes, tpLinkPlugIp);
126         final PcapDumper outputter = Pcaps.openDead(DataLinkType.EN10MB, 65536).dumpOpen("/Users/varmarken/temp/traces/output/tplink-filtered.pcap");
127         DnsMap dnsMap = new DnsMap();
128         TcpReassembler tcpReassembler = new TcpReassembler();
129         tte.performExtraction(pkt -> {
130             try {
131                 outputter.dump(pkt);
132             } catch (NotOpenException e) {
133                 e.printStackTrace();
134             }
135         }, dnsMap, tcpReassembler);
136         outputter.flush();
137         outputter.close();
138
139         int packets = 0;
140         for (Conversation c : tcpReassembler.getTcpConversations()) {
141             packets += c.getPackets().size();
142             packets += c.getSynPackets().size();
143             // only count the FIN packets, not the ACKs; every FinAckPair holds a FIN packet
144             packets += c.getFinAckPairs().size();
145         }
146         // Produces 271 packets for the Feb 13 experiment
147         // Applying filter: "(tcp and not tcp.len == 0 and not tcp.analysis.retransmission and not tcp.analysis.fast_retransmission)  or (tcp.flags.syn == 1) or (tcp.flags.fin == 1)"
148         // to the file gives 295 packets, but there are 24 TCP-Out-Of-Order SYN/SYNACKs which are filtered as retransmissions in Conversation, so the numbers seem to match.
149         System.out.println("number of packets: " + packets);
150
151         List<List<PcapPacketPair>> pairs = new ArrayList<>();
152         for (Conversation c : tcpReassembler.getTcpConversations()) {
153             pairs.add(TcpConversationUtils.extractPacketPairs(c));
154         }
155         // Sort pairs according to timestamp of first packet of conversation for (debugging) convenience.
156         Collections.sort(pairs, (l1, l2) -> {
157             if (l1.get(0).getFirst().getTimestamp().isBefore(l2.get(0).getFirst().getTimestamp())) return -1;
158             else if (l2.get(0).getFirst().getTimestamp().isBefore(l1.get(0).getFirst().getTimestamp())) return 1;
159             else return 0;
160         });
161         System.out.println("list of pairs produced");
162         List<PcapPacketPair> eventstplinkraPairs = new ArrayList<>();
163         List<List<PcapPacketPair>> otherPairs = new ArrayList<>();
164         String hostname = "events.tplinkra.com";
165         for (List<PcapPacketPair> lppp : pairs) {
166             IpV4Packet ipPacket = lppp.get(0).getFirst().get(IpV4Packet.class);
167             // If packets are associated with the hostname
168             if (dnsMap.isRelatedToCloudServer(ipPacket.getHeader().getSrcAddr().getHostAddress(), hostname) ||
169                     dnsMap.isRelatedToCloudServer(ipPacket.getHeader().getDstAddr().getHostAddress(), hostname)) {
170                 eventstplinkraPairs.addAll(lppp);
171             } else {
172                 // Pairs associated with different server
173                 otherPairs.add(lppp);
174             }
175         }
176         HashMap<String, Integer> pairCount = new HashMap<>();
177         for (PcapPacketPair ppp : eventstplinkraPairs) {
178             if (pairCount.containsKey(ppp.toString())) {
179                 pairCount.put(ppp.toString(), pairCount.get(ppp.toString()) + 1);
180             } else {
181                 pairCount.put(ppp.toString(), 1);
182             }
183         }
184         System.out.println("pairCount map built");
185         // ----------------------------
186     }
187
188 }
189
190
191 // TP-Link MAC 50:c7:bf:33:1f:09 and usually IP 192.168.1.159 (remember to verify per file)