proberesponseMitigation.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. /**
  2. * This module is part of the TraCINg CIDS and introduces mitigation methodologies
  3. * against the probe response attack by analyzing statistical anomalies. On identification
  4. * of an attack, countermeasures are introduced which modify the way attack events get
  5. * presented to the user (see postHandler.js).
  6. */
  7. // load node modules
  8. var Chance = require("chance");
  9. var fs = require('fs');
  10. var path = require('path');
  11. var readline = require('readline');
  12. var Map = require("collections/map");
  13. var Set = require("collections/set");
  14. var util = require('util');
  15. var es = require("event-stream");
  16. var debugInstance = 0;
  17. var Debug = function(){
  18. var output = "";
  19. var instance = debugInstance++;
  20. this.get = function(){
  21. return output;
  22. };
  23. this.add = function(text){
  24. text = "Proberesponse["+instance+"]: " + text;
  25. console.log(text);
  26. output += text + "\n";
  27. };
  28. };
  29. var debug = new Debug();
  30. var chance = new Chance();
  31. // TBA: duration of one time slot in a window
  32. // 10 fits for destination port, 6ms
  33. var TIMESLOT_SECONDS = 60;
  34. // TBA: amount of "TIMESLOT_SECONDS" for a time window to save, total seconds = WINDOW_MAX_TIMESLOTS_RATIO * TIMESLOT_SECONDS
  35. var WINDOW_MAX_TIMESLOTS_RATIO = 60;
  36. // Attack count for every source IP address: { ip_source : { ip_destination : count}, ... }
  37. var ip_source_dest_count = {};
  38. // List of ip_source_dest_count for every slot in the time window [ ip_count1, ip_count2, ... ]
  39. // This is a round robbin buffer where the oldest entries get overwritten by the newest.
  40. var window_ip_source_dest = [];
  41. // TBA; Ratio of (attacks/unique monitors) for the whole time window which triggers an alarm.
  42. // There should be a save margin upwards to a "normal" ratio.
  43. // ratio can not be lower than 1 (at minimum 1 attack per monitor)
  44. var THRESHOLD_ATTACKS_MONITOR_RATIO = 3; // depends on TIMESLOT_SECONDS and WINDOW_MAX_TIMESLOTS_RATIO and amount of events/s
  45. // >>> TBA: Alarm thresholds for the whole time window WINDOW_MAX_TIMESLOTS_RATIO
  46. // depents on TIMESLOT_SECONDS * WINDOW_MAX_TIMESLOTS_RATIO
  47. // TBA: Amount of unique monitors per source (adress:monitors -> 1:n -> check n)
  48. var THRESHOLD_MONITORS_PER_SOURCE_IP = 50000; // ~20% of all monitor nodes.
  49. // TBA: Amount of unique sources for one monitors (monitor:address -> 1:n -> check n)
  50. var THRESHOLD_SOURCE_IPS_PER_MONITOR = 100;
  51. // TBA: Amount of attacks from one source to a different monitors (monitor:address -> 1:1 -> check amount of attacks)
  52. var THRESHOLD_SOURCE_IPS_MONITOR_ATTACKS = 6000;
  53. // TBA: Amount of total attacks for one monitors (monitor:attacks -> 1:n -> check n)
  54. var THRESHOLD_ATTACKS_PER_MONITOR = 15000;
  55. // >>> Alarm thresholds for destination port statistics
  56. // TBA: amount of "TIMESLOT_SECONDS" for a time windowto save, total seconds = WINDOW_MAX_TIMESLOTS_RATIO * TIMESLOT_SECONDS
  57. var WINDOW_MAX_TIMESLOTS_PORT_DST = 60;
  58. // Attack count for every destination port: { port : count, ...}
  59. var port_dest_count = new Map();
  60. // List of dicts of ports [ port_dest_count1, port_dest_count2, ... ]
  61. // This is a round robbin buffer where the oldest entries get overwritten by the newest.
  62. var window_port_dest = [];
  63. // TBA: max amount of attacked destination ports in TIMESLOT_SECONDS*WINDOW_MAX_TIMESLOTS_PORT_DST seconds
  64. var THRESHOLD_PORT_DEST_ATTACKED = 1000;
  65. // TBA: Ban duration AFTTER source count falls below SOURCE_IP_THRESHOLD
  66. var SOURCE_IP_BAN_MINUTES = 1;
  67. // { ip : ban_time_minutes }
  68. var banned_ips = {}
  69. // Sampling of events: just take 0% -> 100% of all events
  70. var sampling_percent = 100;
  71. var sampling_active = false;
  72. // noise information
  73. var events_dshield_total = 0;
  74. var events_dshield_added = 0;
  75. var events_external_total = 0;
  76. var events_external_added = 0;
  77. // handle mitigation if activated (does NOT influence metrics -> those are further calculated but external events are ignored)
  78. var is_active = true;
  79. var dshield_entries = [];
  80. // 24 events per second
  81. var noise_interval_ms = 37;
  82. //var noise_interval_ms = 7;
  83. var FILE_STATS = "attack_stats.txt";
  84. var dshield_read_linenr = 0;
  85. var init_started = false;
  86. function init_stats_window() {
  87. // attacks=534113, unique monitors=111831, ratio=4.776072824172188, unique ports= 60win/60slot, 5ms add delay=200entries/s
  88. // attacks=321929, unique monitors=52537, ratio=6.127, unique ports=197, 60win/60slot, 10ms add delay=~100events/s
  89. // DShield events/day=8520284 -> ~10ms delay for 1 event
  90. // Amount of events for: TIMESLOT_SECONDS * WINDOW_MAX_TIMESLOTS_RATIO
  91. // DShield: 156,7 events/s
  92. // On VM (zenmap):
  93. // 1 slot mit 7ms delay = ~7405 -> 60*7405 = ~444000
  94. // 1 slot mit 6ms delay = ~9000 -> 60*9000 = ~540000
  95. //var attacks_init_win = 564415;
  96. //var attacks_init_win = 644415;
  97. //var attacks_init_win = 282208;
  98. //var attacks_init_win = 97200;
  99. //var attacks_init_win = 360000;
  100. // 27 events/s = 97200 events/window (60*60 seconds) = ~ ratio 5.8
  101. //var attacks_init_win = 97200;
  102. var attacks_init_win = Math.round(1000/noise_interval_ms)*TIMESLOT_SECONDS*WINDOW_MAX_TIMESLOTS_RATIO;
  103. var attacks_per_slot = Math.round(attacks_init_win / WINDOW_MAX_TIMESLOTS_RATIO);
  104. var port_count = new Map();
  105. debug.add("amount of dshield entries: "+ dshield_entries.length);
  106. debug.add("initiating window ip: "+WINDOW_MAX_TIMESLOTS_RATIO+"*"+TIMESLOT_SECONDS+
  107. " sec, window port: "+WINDOW_MAX_TIMESLOTS_PORT_DST+"*"+TIMESLOT_SECONDS+" sec");
  108. var cnt = 0;
  109. for(var x=0; x < WINDOW_MAX_TIMESLOTS_RATIO; ++x){
  110. //window_ip_source_dest[x] = {"0.0.0.0" : {"0.0.0.0" : 0}};
  111. window_ip_source_dest[x] = {};
  112. window_port_dest[x] = new Map();
  113. for (var y=0; y < attacks_per_slot; ++y) {
  114. entry = dshield_entries.pop();
  115. //entry = dshield_entries.shift();
  116. //l = [ipsrc, ipmon, chance.integer({min:0, max:65535})];
  117. l = [entry[0], entry[2], entry[3]];
  118. if (l in window_ip_source_dest[x]) {
  119. window_ip_source_dest[x][l] += 1;
  120. //debug.add("adding, total: "+ window_ip_source_dest[x][l]);
  121. }
  122. else
  123. window_ip_source_dest[x][l] = 1;
  124. if (port_count.get(entry[3]) == undefined) {
  125. port_count.set(entry[3], 1);
  126. } else {
  127. port_count.set(entry[3], port_count.get(entry[3]) + 1);
  128. }
  129. if (window_port_dest[x].get(entry[3]) == undefined) {
  130. window_port_dest[x].set(entry[3], 1);
  131. } else {
  132. window_port_dest[x].set(entry[3], window_port_dest[x].get(entry[3]) + 1);
  133. }
  134. cnt += 1;
  135. }
  136. }
  137. var port_cnt_check = 0;
  138. port_count.forEach( function merge(count, port, mapObj) {
  139. port_cnt_check += count;
  140. });
  141. debug.add("unique ports: "+ port_count.length);
  142. debug.add("finished initiating, count: "+attacks_init_win+"="+port_cnt_check+"=~"+cnt);
  143. // TODO: activate if needed
  144. // add noise using DShield data
  145. var interval_countermeasure = setInterval(add_entry_dshield, noise_interval_ms);
  146. var check_attack_status_ref = setInterval(check_attack_status, TIMESLOT_SECONDS * 1000);
  147. }
  148. var FILE_DSHIELD_EVENTS = path.join(__dirname, 'dshield_report.csv');
  149. debug.add("reading DShield events from "+FILE_DSHIELD_EVENTS+", standy by");
  150. s = fs.createReadStream(FILE_DSHIELD_EVENTS)
  151. .pipe(es.split())
  152. .pipe(es.mapSync(function(line){
  153. // pause the readstream
  154. s.pause();
  155. dshield_read_linenr += 1;
  156. (function(){
  157. var columns = line.toString().split("\t", -1);
  158. if (columns.length == 9) {
  159. try {
  160. // 3 4 [8 -> IP] 5: ip_src port_src ip_dst port_dst id
  161. // convert monitor ID to an IP address
  162. a = parseInt(columns[8].substring(2, 4), 16);
  163. b = parseInt(columns[8].substring(4, 6), 16);
  164. c = parseInt(columns[8].substring(6, 8), 16);
  165. d = parseInt(columns[8].substring(8, 10), 16);
  166. //debug.add("IP is: " + a+"."+b+"."+c+"."+d);
  167. dshield_entries.push([columns[3],
  168. parseInt(columns[4]),
  169. a+"."+b+"."+c+"."+d,
  170. columns[5],
  171. columns[8]]);
  172. } catch (err) { /* ignore malformed lines */ }
  173. }
  174. // process line here and call s.resume() when rdy
  175. //logMemoryUsage(lineNr);
  176. if (dshield_read_linenr % 200000 == 0) debug.add("read DShield events: "+dshield_read_linenr);
  177. //if (!init_started && dshield_read_linenr > 1000000) {
  178. if (!init_started && dshield_read_linenr > 5000000) {
  179. //if (!init_started && dshield_read_linenr > 7000000) {
  180. //if (!init_started && dshield_read_linenr > 9000000) {
  181. //if (!init_started && dshield_read_linenr > 12000000) {
  182. s.destroy(); init_stats_window(); init_started = true;
  183. }
  184. // resume the readstream
  185. s.resume();
  186. })();
  187. })
  188. .on('error', function(){ debug.add('Error while reading DShield report'); })
  189. .on('end', function(){ debug.add('Read entire DShield report') })
  190. );
  191. function update_slot(monitor_id, ip_source, ip_dest, port_dest) {
  192. //debug.add("updating window: "+monitor_id+" / "+ip_source+" / "+ip_dest+" / "+port_dest);
  193. //if (!is_active) { return; }
  194. /*
  195. if (!(ip_source === undefined) && (ip_source in banned_ips)) {
  196. // don't count banned IP addresses
  197. //debug.add("won't count banned ip: "+ ip_source)
  198. return;
  199. }
  200. */
  201. //l = [ip_source, ip_dest, port_dest];
  202. l = [ip_source, monitor_id, port_dest];
  203. if (ip_source_dest_count[l] == undefined) { ip_source_dest_count[l] = 0; }
  204. ip_source_dest_count[l] += 1;
  205. if (port_dest_count.get(port_dest) == undefined) {
  206. port_dest_count.set(port_dest, 1);
  207. } else {
  208. port_dest_count.set(port_dest, port_dest_count.get(port_dest) + 1);
  209. }
  210. }
  211. // clear old attack stats file
  212. fs.writeFile(FILE_STATS, "ratio\tports\talarm_ratio\talarm_port\tevents_dshield_added\tevents_dshield_total\tevents_external_added\tevents_extern_total\n", function (err) { if (err) throw err; });
  213. // update ban status of any source IP address
  214. function check_attack_status() {
  215. //debug.add("checking attack status");
  216. // >>> Update window with new slot
  217. var time_seconds_now = Math.round(new Date().getTime() / 1000);
  218. var time_minutes_now = Math.round(time_seconds_now / 60);
  219. var timeslot_ratio = Math.round(time_seconds_now / TIMESLOT_SECONDS) % WINDOW_MAX_TIMESLOTS_RATIO;
  220. // window_ip_source_dest[x] = [a, b, c]
  221. window_ip_source_dest[timeslot_ratio] = ip_source_dest_count;
  222. // reset count for next slot
  223. ip_source_dest_count = {};
  224. var timeslot_ports = Math.round(time_seconds_now / TIMESLOT_SECONDS) % WINDOW_MAX_TIMESLOTS_PORT_DST;
  225. window_port_dest[timeslot_ports] = port_dest_count;
  226. // reset count for next slot
  227. port_dest_count = new Map();
  228. var alarm_ratio_triggered = false;
  229. var alarm_portdest_triggered = false;
  230. var alarm_attacks_per_monitor_triggered = false;
  231. var sampling = 100;
  232. // >>> check threshold: amount of unique attacked destination ports
  233. //debug.add("counting ports...");
  234. var port_dest_count_merged = new Map();
  235. var top_ports = new Set();
  236. alarm_portdest_triggered = false;
  237. /*
  238. // TODO: activate if needed
  239. for (var timeslot in window_port_dest) {
  240. window_port_dest[timeslot].forEach( function merge(count, port, mapObj) {
  241. if (port_dest_count_merged.get(port) == undefined) {
  242. port_dest_count_merged.set(port, count);
  243. //debug.add("setting port: "+port+" = count "+count);
  244. } else {
  245. port_dest_count_merged.set(port, port_dest_count_merged.get(port) + count);
  246. }
  247. });
  248. }
  249. // sort keys by value descending
  250. var top_ports_all = port_dest_count_merged.keys().sort(function(a,b){
  251. return port_dest_count_merged.get(b) - port_dest_count_merged.get(a)}
  252. );
  253. for (var x=0; x < 2 && x < top_ports_all.length; ++x) {
  254. top_ports.add(top_ports_all[x]);
  255. }
  256. debug.add("port: slot="+timeslot_ports+", unique dest ports: "+port_dest_count_merged.length+
  257. ", top 3 ports="+top_ports_all[0]+","+top_ports_all[1]+","+top_ports_all[2]);
  258. if (port_dest_count_merged.length > THRESHOLD_PORT_DEST_ATTACKED) {
  259. //debug.add("PRA-WARNING: too many unique destination ports: " +
  260. //" ("+ port_dest_count_merged.length +" > "+ THRESHOLD_PORT_DEST_ATTACKED +")");
  261. // TODO: activate if needed
  262. sampling = ((THRESHOLD_PORT_DEST_ATTACKED / port_dest_count_merged.length) * 100)
  263. alarm_portdest_triggered = true;
  264. }
  265. */
  266. // amount of attacks for one monitor {id : count}
  267. var attacks_per_monitor = new Map();
  268. var attacks_total = 0;
  269. //debug.add("counting monitors...");
  270. var skipped_top_ports = 0;
  271. /**/
  272. // TODO: activate if needed
  273. for (var slot_search in window_ip_source_dest) {
  274. for (var ipsrc_ipdst_portdst in window_ip_source_dest[slot_search]) {
  275. ipsrc_ipdst_portdst_split = ipsrc_ipdst_portdst.split(",");
  276. // TODO: activate for port normalizing
  277. //if (top_ports.contains(ipsrc_ipdst_portdst_split[2])) {
  278. // // skip top x ports
  279. // //debug.add("skipping port: "+ipsrc_ipdst_portdst_split[2]);
  280. // skipped_top_ports += 1;
  281. // continue;
  282. //}
  283. ip_dst = ipsrc_ipdst_portdst_split[1];
  284. count = window_ip_source_dest[slot_search][ipsrc_ipdst_portdst];
  285. //if (count > 100) {debug.add(ip_dst+"="+count);}
  286. if (attacks_per_monitor.get(ip_dst) == undefined) {
  287. //debug.add(ip_dst);
  288. attacks_per_monitor.set(ip_dst, count);
  289. } else {
  290. attacks_per_monitor.set(ip_dst, attacks_per_monitor.get(ip_dst) + count);
  291. }
  292. attacks_total += count;
  293. }
  294. }
  295. /**/
  296. //debug.add("output...");
  297. // >>> check treshold:
  298. // ratio -> attacks / unique monitors
  299. var unique_monitors_total = attacks_per_monitor.length;
  300. var ratio = attacks_total / unique_monitors_total;
  301. var alarm_ratio_triggered = false;
  302. /**/
  303. if (isNaN(ratio)) {
  304. // ratio 0 means: no attacks and/or no monitors -> nothing happened -> no attack
  305. ratio = 0;
  306. }
  307. if (is_active) {
  308. debug.add("mon: slot="+timeslot_ratio+", attacks="+attacks_total+", mon="+unique_monitors_total+
  309. ", ratio="+ratio+", top removed="+skipped_top_ports);
  310. }
  311. if (ratio != 0 && ratio <= THRESHOLD_ATTACKS_MONITOR_RATIO) {
  312. //debug.add("PRA-WARNING: Ratio attacks/monitors is too low: "+ratio+" <= "+THRESHOLD_ATTACKS_MONITOR_RATIO);
  313. // ratio is at minimum 1, so minimum is: 1/(threshold_ratio) -> set minimum to 0/(threshold_ratio-1)
  314. sampling_ratio = (((ratio-1)/(THRESHOLD_ATTACKS_MONITOR_RATIO-1)) * 100);
  315. if (sampling_ratio < sampling) {
  316. sampling = sampling_ratio;
  317. }
  318. alarm_ratio_triggered = true;
  319. }
  320. /**/
  321. alarm_attacks_per_monitor_triggered = false;
  322. /*
  323. // TODO: activate if needed
  324. // >>> check threshold: attacks per monitor
  325. attacks_per_monitor.forEach(function each(amount, monitor, mapObj) {
  326. //debug.add(monitor+"="+amount);
  327. if (amount > THRESHOLD_ATTACKS_PER_MONITOR) {
  328. //debug.add("PRA-WARNING: Monitor "+monitor+" is attacked too many times("+
  329. //amount+" > "+THRESHOLD_ATTACKS_PER_MONITOR+")");
  330. sampling_attack_per_mon = ((THRESHOLD_ATTACKS_PER_MONITOR/amount) * 100);
  331. if (sampling_attack_per_mon < sampling) {
  332. sampling = sampling_attack_per_mon;
  333. }
  334. alarm_attacks_per_monitor_triggered = true;
  335. }
  336. });
  337. */
  338. if (is_active) {
  339. sampling_percent = sampling;
  340. if ((!alarm_ratio_triggered) && (!alarm_portdest_triggered) && (!alarm_attacks_per_monitor_triggered)) {
  341. sampling_percent = 100;
  342. sampling_active = false;
  343. } else if (sampling_percent < 100) {
  344. debug.add("sampling="+sampling_percent+"%, ratio="+alarm_ratio_triggered+
  345. ", port_dest="+alarm_portdest_triggered+", atttacks_per_mon="+alarm_attacks_per_monitor_triggered+
  346. ", noise added/total="+events_dshield_added+"/"+events_dshield_total);
  347. sampling_active = true;
  348. }
  349. } else {
  350. ratio = 0;
  351. }
  352. // unban IPs which ban timeout exceeded
  353. /*
  354. for (var ip in banned_ips) {
  355. if ( (time_minutes_now - banned_ips[ip]) >= SOURCE_IP_BAN_MINUTES) {
  356. debug.add("unbanning ip: "+ ip +" ("+ (time_minutes_now - banned_ips[ip]) +" minutes passed)");
  357. delete banned_ips[ip];
  358. }
  359. }
  360. */
  361. fs.appendFile(FILE_STATS, ratio+"\t"+port_dest_count_merged.length+"\t"+alarm_ratio_triggered+"\t"
  362. +alarm_portdest_triggered+"\t"+events_dshield_added+"\t"
  363. +events_dshield_total+"\t"+events_external_added+"\t"+events_external_total+"\n", function (err) {});
  364. //debug.add("finished checking");
  365. }
  366. // this is exclusively used by addNoiseEvent()
  367. var data = {
  368. sensorname: null,
  369. sensortype: "RandomType",
  370. src: {
  371. ip: null,
  372. port: null,
  373. ll: [0,0],
  374. country: "",
  375. cc: 0,
  376. city: ""
  377. },
  378. dst: {
  379. ip: null,
  380. port: null,
  381. ll: [0,0],
  382. country: "",
  383. cc: 0,
  384. city: ""
  385. },
  386. type: 11,
  387. log: null,
  388. md5sum: "0123456789",
  389. date: new Date(),
  390. authorized: false
  391. };
  392. function addNoiseEvent(ip_src, port_src, ip_dst, port_dst, monitorname, doEmit) {
  393. if (typeof io == 'undefined') {
  394. //debug.add("no io, no emit -> I quit");
  395. return;
  396. }
  397. //debug.add("adding, name/ip/port: " + data.sensorname + " / " + data.src.ip + " / " +
  398. // data.dst.ip + " / " + data.src.port + " / " + data.dst.port);
  399. /*
  400. // not needed for PRA
  401. ipa = lookUpIp(ip_src);
  402. if(ipa){
  403. data.src["ll"] = [ipa.longitude, ipa.latitude];
  404. data.src["country"] = ipa.country_name;
  405. data.src["cc"] = ipa.country_code;
  406. data.src["city"] = ipa.city || "";
  407. }
  408. ipd = lookUpIp(ip_dst);
  409. if(ipd){
  410. data.dst["ll"] = [ipd.longitude, ipd.latitude];
  411. data.dst["country"] = ipd.country_name;
  412. data.dst["cc"] = ipd.country_code;
  413. data.dst["city"] = ipd.city || "";
  414. }
  415. */
  416. //debug.add("> " + chance.integer({min: 0, max: 65535}));
  417. //debug.add("> " + chance.ip());
  418. //debug.add("Sending random entry: " + data["src"]["ip"]);
  419. update_slot(monitorname, ip_src, ip_dst, port_dst);
  420. // do not emit data to client if not sampled
  421. if (doEmit) {
  422. data.src.ip = ip_src;
  423. data.src.port = port_src;
  424. data.dst.ip = ip_dst;
  425. data.dst.port = port_dst;
  426. data.sensorname = monitorname;
  427. io.sockets.emit("markIncident", data);
  428. }
  429. }
  430. // Add artificial noise to the report
  431. function add_entry_random() {
  432. addNoiseEvent(chance.ip(),
  433. chance.integer({min: 0, max: 65535}),
  434. chance.ip(),
  435. chance.integer({min: 0, max: 65535}),
  436. "RandomMonitor_" + chance.integer({min: 0, max: 100}),
  437. true
  438. );
  439. }
  440. function add_entry_dshield() {
  441. e = dshield_entries.pop();
  442. //e = dshield_entries.shift();
  443. //debug.add("adding noise using dshield data: "+e);
  444. // we can not differentiate between PRA and non-PRA events so we have to sample both
  445. // accept entry if: sampling not active (sample 100%) or random value tells us so
  446. // add noise if: attack mitigation is not active, mitigation not triggered or random tells us to
  447. sample_entry = (!is_active || !sampling_active || chance.floating({min: 1, max: 100}) <= sampling_percent);
  448. addNoiseEvent(e[0], e[1], e[2], e[3], e[4], sample_entry);
  449. if (sample_entry) {
  450. events_dshield_added += 1;
  451. }
  452. events_dshield_total += 1;
  453. }
  454. function applyMitigation(ip_src, ip_dst, port_dst, monitor_id) {
  455. // praMitigation.applyMitigation(items[i].src.ip, items[i].dst.ip, items[i].dst.port
  456. events_external_total += 1;
  457. if (!is_active) {
  458. return false;
  459. } else {
  460. update_slot(monitor_id, ip_src, ip_dst, port_dst);
  461. // allow entry if sampling is not active or random tells us to
  462. is_sampled = (!sampling_active || chance.floating({min: 1, max: 100}) > sampling_percent);
  463. if (is_sampled) {
  464. events_external_added += 1;
  465. }
  466. return !is_sampled;
  467. }
  468. }
  469. function setActive(activeState) {
  470. debug.add("setting new PRA mitigation active state: " + activeState);
  471. is_active = activeState;
  472. }
  473. module.exports = {
  474. //init: init,
  475. setActive: setActive,
  476. applyMitigation: applyMitigation
  477. };