private void LoadAndTest(FlowProfile profile, IEnumerable <IPacketRecord> packets) { var getFlowKeyFunc = FlowKey.GetFlowKeyFunc(profile.FlowAggregation); var getModelKeyFunc = profile.ProtocolFactory.GetModelKeyFunc(profile.ModelKey); var startTime = packets.First().TimeEpoch; var packetBins = packets.GroupBy(p => (int)Math.Floor((p.TimeEpoch - startTime) / profile.WindowSize)); var normalTotal = 0; var abnormalTotal = 0; var unknownTotal = 0; foreach (var group in packetBins) { var flows = profile.ProtocolFactory.CollectCoapFlows(group, getModelKeyFunc, getFlowKeyFunc); var testResults = TestAndPrint(profile, flows, $"{DateTime.UnixEpoch.AddSeconds((long)startTime + (group.Key * profile.WindowSize))}"); normalTotal += testResults.Normal; abnormalTotal += testResults.Abnormal; unknownTotal += testResults.Unknown; } var measuresTable = new DataTable(); measuresTable.Columns.Add("Metric", typeof(string)); measuresTable.Columns.Add("Value", typeof(double)); measuresTable.Rows.Add("Normal", normalTotal); measuresTable.Rows.Add("Abnormal", abnormalTotal); measuresTable.Rows.Add("Unknown", unknownTotal); Console.WriteLine("Measures:"); ConsoleTableBuilder.From(measuresTable) .WithFormat(ConsoleTableBuilderFormat.MarkDown) .ExportAndWriteLine(); }
private static void ComputeProfile(FlowProfile profile, IEnumerable <IFlowRecord> flows) { foreach (var flow in flows) { var modelObject = flow.Model.ToString(); if (!profile.TryGetValue(modelObject, out var model)) { model = profile.NewModel(); profile[modelObject] = model; } model.Samples.Add(new double[] { flow.FlowPackets, flow.FlowOctets }); } }
private void StoreProfile(FlowProfile profile, string outputFile) { var fullPath = Path.GetFullPath(outputFile); var sw = new Stopwatch(); sw.Start(); Console.WriteLine("┌ Saving profile:"); var formatter = new BinaryFormatter(); using (var s = new FileStream(outputFile, FileMode.Create)) { formatter.Serialize(s, profile); s.Close(); } Console.WriteLine($"├─ profile written to {fullPath}"); Console.WriteLine($"└ done [{sw.Elapsed}]."); }
private void LoadAndCompute(FlowProfile profile, string inputFile, IList <CoapPacketRecord> packets, double windowSize, LearningWindow learningWindows, ProtocolFactory protocolFactory, Enum modelKey, FlowKey.Fields flowAggregation = FlowKey.Fields.None) { var getFlowKeyFunc = FlowKey.GetFlowKeyFunc(flowAggregation); var getModelKeyFunc = protocolFactory.GetModelKeyFunc(modelKey); Console.WriteLine("┌ Load packets and compute profile:"); Console.WriteLine($"├─ input file: {inputFile}"); Console.WriteLine($"├─ packets count: {packets.Count}"); Console.WriteLine($"├─ window size: {windowSize} seconds"); Console.WriteLine($"├─ learning window: {learningWindows.Meassure}({learningWindows.Value})"); Console.WriteLine($"├─ protocol: {protocolFactory.Name}"); Console.WriteLine($"├─ model key: {modelKey}"); Console.WriteLine($"├─ flow aggregation: {flowAggregation}"); var sw = new Stopwatch(); sw.Start(); var startTime = packets.First().TimeEpoch; var packetBins = packets.GroupBy(p => (int)Math.Floor((p.TimeEpoch - startTime) / windowSize)).ToList(); var learningBins = learningWindows.Meassure == LearningWindow.ValueType.Absolute ? packetBins.Take((int)learningWindows.Value) : packetBins.Take((int)(packetBins.Count() * learningWindows.Value)); var pb1 = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new ProgressBar(packetBins.Count()) : null; foreach (var group in packetBins) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { pb1.Next($"├─ processing bin {group.Key}: {group.Count()} items"); } var flows = protocolFactory.CollectCoapFlows(group, getModelKeyFunc, getFlowKeyFunc); ComputeProfile(profile, flows); } var pb2 = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new ProgressBar(profile.Count) : null; profile.Commit(() => { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { pb2.Next($"├─ fitting models"); } }); Console.WriteLine($"└ done [{sw.Elapsed}]."); }
public void Configuration(CommandLineApplication command) { command.Description = "Tests the differences of the communication to the CoAP profile."; command.HelpOption("-?|-Help"); var inputCsvOption = command.Option("-InputCsvFile <string>", "A name of an input file in csv format that contains decoded CoAP packets.", CommandOptionType.MultipleValue); var inputCapOption = command.Option("-InputCapFile <string>", "A name of an input file in cap format that contains CoAP packets.", CommandOptionType.MultipleValue); var profileOption = command.Option("-ProfileFile <string>", "A name of a profile file.", CommandOptionType.MultipleValue); var tresholdOption = command.Option("-TresholdFactor <double>", "A Factor used to scale the treshold. The usual values are between 0-1. Default is 1.", CommandOptionType.SingleValue); command.OnExecute(() => { var thresholdMultiplier = tresholdOption.HasValue() ? Double.Parse(tresholdOption.Value()) : 1; if (profileOption.HasValue()) { var profiles = profileOption.Values.Select(PrintProfile.LoadProfile).ToList(); var profile = profiles.Count == 1 ? profiles.First() : FlowProfile.MergeProfiles(profiles); profile.ThresholdMultiplier = thresholdMultiplier; if (inputCsvOption.HasValue()) { var packets = PacketLoader.LoadCoapPacketsFromCsv(inputCsvOption.Value()); LoadAndTest(profile, packets); } if (inputCapOption.HasValue()) { var packets = PacketLoader.LoadCoapPacketsFromCap(inputCapOption.Value()); LoadAndTest(profile, packets); } return(0); } throw new CommandParsingException(command, $"Missing required arguments: {inputCsvOption.ShortName}, {profileOption.ShortName}."); }); }
private (int Normal, int Abnormal, int Unknown) TestAndPrint(FlowProfile profile, IEnumerable <IFlowRecord> flows, string label = "") { var normalCount = 0; var abnormalCount = 0; var unknownCount = 0; var matchingTable = new DataTable(); matchingTable.Columns.Add("CoAP Flow", typeof(string)); matchingTable.Columns.Add("Packets", typeof(string)); matchingTable.Columns.Add("Octets", typeof(string)); matchingTable.Columns.Add("Score", typeof(double)); matchingTable.Columns.Add("Threshold", typeof(double)); matchingTable.Columns.Add("Label", typeof(string)); foreach (var flow in flows) { var observation = new double[] { flow.FlowPackets, flow.FlowOctets }; if (profile.TryGetValue(flow.Model.ToString(), out var matchingProfile)) { var score = matchingProfile.Score(observation); var matches = (score > (matchingProfile.Threshold * profile.ThresholdMultiplier)); matchingTable.Rows.Add($"{flow.Key} {flow.Model}", flow.FlowPackets, flow.FlowOctets, score, matchingProfile.Threshold, matches ? "normal" : "abnormal"); if (matches) { normalCount++; } else { abnormalCount++; } } else { matchingTable.Rows.Add($"{flow.Key} {flow.Model}", flow.FlowPackets, flow.FlowOctets, double.NaN, double.NaN, "unknown"); unknownCount++; } } Console.WriteLine($"{label}:"); ConsoleTableBuilder.From(matchingTable) .WithFormat(ConsoleTableBuilderFormat.MarkDown) .ExportAndWriteLine(); return(normalCount, abnormalCount, unknownCount); }
/// <summary> /// Prints PDF of all models as CSV suitable for visualization. /// </summary> /// <param name="profile"></param> private void DumpPdf(FlowProfile profile) { foreach (var model in profile) { Console.WriteLine($"{model.Key}:"); Console.WriteLine($"x,y,score"); var samples = model.Value.Samples; var xmin = samples.Select(x => x[0]).Min(); var xmax = samples.Select(x => x[0]).Max(); var ymin = samples.Select(x => x[1]).Min(); var ymax = samples.Select(x => x[1]).Max(); var xdelta = (xmax - xmin) / 10; var ydelta = (ymax - ymin) / 10; for (var x = xmin; x < xmax; x += xdelta) { for (var y = ymin; y < ymax; y += ydelta) { Console.WriteLine($"{x},{y},{model.Value.Score(new[] { x,y})}"); } } Console.WriteLine(); } }
private void ComputeDistances(FlowProfile profile1, FlowProfile profile2) { var measuresTable = new DataTable(); measuresTable.Columns.Add("Target", typeof(string)); measuresTable.Columns.Add("Count 1", typeof(double)); measuresTable.Columns.Add("Count 2", typeof(double)); measuresTable.Columns.Add("Distance", typeof(double)); foreach (var m1 in profile1) { if (profile2.TryGetValue(m1.Key, out var m2)) { var b = new Bhattacharyya(); var dist = b.Distance(m1.Value.Samples.ToArray(), m2.Samples.ToArray()); measuresTable.Rows.Add(m1.Key, m1.Value.Samples.Count, m2.Samples.Count, dist); } } Console.WriteLine("Distances:"); ConsoleTableBuilder.From(measuresTable) .WithFormat(ConsoleTableBuilderFormat.MarkDown) .ExportAndWriteLine(); }