UnsupervisedAnomalyDetectionExample.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import java.util.ArrayList;
  2. import java.util.HashMap;
  3. import java.util.Iterator;
  4. import java.util.LinkedList;
  5. import java.util.Map.Entry;
  6. import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
  7. import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
  8. import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PacketSniffer;
  9. import weka.clusterers.SimpleKMeans;
  10. import weka.core.Attribute;
  11. import weka.core.DenseInstance;
  12. import weka.core.Instance;
  13. import weka.core.Instances;
  14. /**
  15. * Unsupervised Example - maybe Clustering
  16. *
  17. * @author Andreas T. Meyer-Berg
  18. */
  19. public class UnsupervisedAnomalyDetectionExample implements PacketSniffer {
  20. /**
  21. * Clusterer
  22. */
  23. private SimpleKMeans clusterer;
  24. /**
  25. * True, if instances should be used for training
  26. */
  27. private boolean training = true;
  28. /**
  29. * Attributes which should be taken into account
  30. */
  31. private ArrayList<Attribute> atts = new ArrayList<Attribute>();
  32. /**
  33. * Collected Packets
  34. */
  35. private Instances dataset;
  36. /**
  37. * HashMap for calculating transmission delay
  38. */
  39. private HashMap<Link, LinkedList<Packet>> lastPackets = new HashMap<Link, LinkedList<Packet>>();
  40. /**
  41. * Number of Clusters
  42. */
  43. private int NUMBER_OF_CLUSTERS = 2;
  44. /**
  45. * Number of packets used for number of packets per second
  46. */
  47. private int NUMBER_OF_PACKETS = 30;
  48. /**
  49. *
  50. */
  51. private HashMap<String,Integer> link_mappings = new HashMap<String, Integer>();
  52. private HashMap<String,Integer> source_mappings = new HashMap<String, Integer>();
  53. private HashMap<String,Integer> destination_mappings = new HashMap<String, Integer>();
  54. private HashMap<String,Integer> protocol_mappings = new HashMap<String, Integer>();
  55. /**
  56. *
  57. */
  58. public UnsupervisedAnomalyDetectionExample() {
  59. // Initialize Attribute list
  60. link_mappings.put("unknown", 0);
  61. atts.add(new Attribute("Link-Name", false));//TODO:??
  62. source_mappings.put("unknown", 0);
  63. atts.add(new Attribute("Source-Device", false));
  64. atts.add(new Attribute("Source-Port-number", false));
  65. destination_mappings.put("unknown", 0);
  66. atts.add(new Attribute("Destination-Device", false));
  67. atts.add(new Attribute("Destination-Port-number", false));
  68. protocol_mappings.put("unknown", 0);
  69. atts.add(new Attribute("Protocol-name", false));
  70. atts.add(new Attribute("Packets-per-second", false));
  71. // Initialize data set
  72. dataset = new Instances("Packets", atts, 100000);
  73. // Initialize Clusterer
  74. clusterer = new SimpleKMeans();
  75. clusterer.setSeed(42);
  76. try {
  77. clusterer.setNumClusters(NUMBER_OF_CLUSTERS);
  78. } catch (Exception e) {
  79. System.out.println("Error while building cluster");
  80. e.printStackTrace();
  81. }
  82. }
  83. @Override
  84. public void processPackets(HashMap<Link, LinkedList<Packet>> packets) {
  85. if(training)
  86. try {
  87. training(packets);
  88. } catch (Exception e) {
  89. e.printStackTrace();
  90. }
  91. else
  92. classify(packets);
  93. }
  94. /**
  95. * Estimates the current Packets per second (depending on the last 100 packets of the link)
  96. * @param link Link which should be checked
  97. * @param packet Packet which should investigated
  98. * @return estimated number of packets per second
  99. */
  100. private double getEstimatedPacketsPerSecond(Link link, Packet packet) {
  101. /**
  102. * Packets used to calculated the packets per second
  103. */
  104. LinkedList<Packet> list = lastPackets.get(link);
  105. if(list == null) {
  106. /**
  107. * Add list if not present
  108. */
  109. list = new LinkedList<Packet>();
  110. lastPackets.put(link, list);
  111. }
  112. if(list.isEmpty()) {
  113. list.addLast(packet);
  114. // Default 1 packet per second
  115. return 1.0;
  116. }
  117. if(list.size() == NUMBER_OF_PACKETS){
  118. list.removeFirst();
  119. }
  120. list.addLast(packet);
  121. /**
  122. * elapsed time in milliseconds since last packet
  123. */
  124. long elapsed_time = packet.getTimestamp()-list.getFirst().getTimestamp()/list.size();
  125. if(elapsed_time<=0)
  126. return Double.POSITIVE_INFINITY;
  127. /**
  128. * Return number of packets per second
  129. */
  130. return 1000.0/elapsed_time;
  131. }
  132. /**
  133. * Returns the instance representation of the given packet and link
  134. * @param link link the packet was sent on
  135. * @param packet packet which should be transformed
  136. * @param dataset distribution the packet is part of
  137. * @return instance representation
  138. */
  139. private Instance packet2Instance(Link link, Packet packet, Instances dataset) {
  140. /**
  141. * Instance for the given Packet
  142. */
  143. DenseInstance instance = new DenseInstance(dataset.numAttributes());
  144. instance.setDataset(dataset);
  145. // link
  146. instance.setValue(0, link == null ? 0 : stringToNumber(link_mappings, link.getName()));
  147. // source
  148. if(packet.getSource()==null) {
  149. instance.setValue(1, 0);
  150. instance.setValue(2, Double.NEGATIVE_INFINITY);
  151. }else if(packet.getSource().getOwner()==null){
  152. instance.setValue(1, 0);
  153. instance.setValue(2, packet.getSource().getPortNumber());
  154. }else {
  155. instance.setValue(1, stringToNumber(source_mappings, packet.getSource().getOwner().getName()));
  156. instance.setValue(2, packet.getSource().getPortNumber());
  157. }
  158. // Destination
  159. if(packet.getDestination()==null) {
  160. instance.setValue(3, 0);
  161. instance.setValue(4, Double.NEGATIVE_INFINITY);
  162. }else if(packet.getDestination().getOwner()==null){
  163. instance.setValue(3, 0);
  164. instance.setValue(4, packet.getDestination().getPortNumber());
  165. }else {
  166. instance.setValue(3, stringToNumber(destination_mappings, packet.getDestination().getOwner().getName()));
  167. instance.setValue(4, packet.getDestination().getPortNumber());
  168. }
  169. // Protocol name
  170. instance.setValue(5, stringToNumber(protocol_mappings, packet.getProtocolName()));
  171. // Packets per second
  172. instance.setValue(6, getEstimatedPacketsPerSecond(link, packet));
  173. return instance;
  174. }
  175. /**
  176. * Transforms the String into an Number
  177. * @param map
  178. * @param s
  179. * @return
  180. */
  181. double stringToNumber(HashMap<String, Integer> map, String s) {
  182. Integer i = map.get(s);
  183. if(i == null) {
  184. int size = map.size();
  185. map.put(s, size);
  186. return size;
  187. }else {
  188. return i;
  189. }
  190. }
  191. /**
  192. * Train the clusterer by collecting the packets
  193. *
  194. * @param packets packets to be learned
  195. */
  196. private void training(HashMap<Link, LinkedList<Packet>> packets) {
  197. for (Iterator<Entry<Link, LinkedList<Packet>>> it = packets.entrySet().iterator(); it.hasNext();) {
  198. Entry<Link, LinkedList<Packet>> entry = it.next();
  199. /**
  200. * Link the packet was captured on
  201. */
  202. Link l = entry.getKey();
  203. for (Iterator<Packet> itPacket = entry.getValue().iterator(); itPacket.hasNext();) {
  204. /**
  205. * Packets to be added to the dataset
  206. */
  207. Packet packet = (Packet) itPacket.next();
  208. dataset.add(packet2Instance(l, packet, dataset));
  209. }
  210. }
  211. }
  212. /**
  213. * Finishes the collection and trains the clusterer on the collected packets
  214. *
  215. * @throws Exception
  216. */
  217. private void finishDataCollection() throws Exception{
  218. /**
  219. * Build the clusterer for the given dataset
  220. */
  221. clusterer.buildClusterer(dataset);
  222. }
  223. /**
  224. * Try to classify the given packets and detect anomalies
  225. * @param packets packets to be classified
  226. */
  227. private void classify(HashMap<Link, LinkedList<Packet>> packets) {
  228. for (Iterator<Entry<Link, LinkedList<Packet>>> it = packets.entrySet().iterator(); it.hasNext();) {
  229. /**
  230. * Link & its packets
  231. */
  232. Entry<Link, LinkedList<Packet>> entry = it.next();
  233. /**
  234. * Link the packets were captured on
  235. */
  236. Link l = entry.getKey();
  237. for (Iterator<Packet> itPacket = entry.getValue().iterator(); itPacket.hasNext();) {
  238. /**
  239. * Packet which should be checked
  240. */
  241. Packet packet = (Packet) itPacket.next();
  242. /**
  243. * Instance Representation
  244. */
  245. Instance packet_instance = packet2Instance(l, packet, dataset);
  246. try {
  247. /**
  248. * Try to classify (find appropriate cluster)
  249. */
  250. clusterer.clusterInstance(packet_instance);
  251. } catch (Exception e) {
  252. /**
  253. * Anomaly found
  254. */
  255. System.out.println("Anomaly: "+packet.getTextualRepresentation());
  256. //e.printStackTrace();
  257. }
  258. }
  259. }
  260. }
  261. @Override
  262. public void setMode(boolean testing) {
  263. training = !testing;
  264. if(testing) {
  265. // Build Clusterer
  266. try {
  267. finishDataCollection();
  268. } catch (Exception e) {
  269. System.out.println("Clustering failed");
  270. e.printStackTrace();
  271. }
  272. }
  273. }
  274. @Override
  275. public boolean getMode() {
  276. return !training;
  277. }
  278. }