api.ophanimclassifier.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. /**
  3. * Basic traffic classifier implementation
  4. */
  5. class OphanimClassifier {
  6. /**
  7. * Contains classified counters base structure [0..11]
  8. *
  9. * @var array
  10. */
  11. protected $baseStruct = array(
  12. 'time' => 0,
  13. 'total' => 0,
  14. 'icmp' => 0,
  15. 'udp' => 0,
  16. 'tcp' => 0,
  17. 'mail' => 0,
  18. 'dns' => 0,
  19. 'vpn' => 0,
  20. 'ftp' => 0,
  21. 'web' => 0,
  22. 'proxy' => 0,
  23. 'quic' => 0,
  24. 'sip' => 0,
  25. );
  26. /**
  27. * Contains TCP proto identifiers as port=>proto
  28. *
  29. * @var array
  30. */
  31. protected $tcpProto = array(
  32. 80 => 'web',
  33. 443 => 'web',
  34. 21 => 'ftp',
  35. 20 => 'ftp',
  36. 110 => 'mail',
  37. 25 => 'mail',
  38. 143 => 'mail',
  39. 587 => 'mail',
  40. 53 => 'dns',
  41. 3128 => 'proxy',
  42. 8080 => 'proxy',
  43. 8888 => 'proxy',
  44. 1080 => 'proxy',
  45. );
  46. /**
  47. * Contains UDP proto identifiers as port=>proto
  48. *
  49. * @var array
  50. */
  51. protected $udpProto = array(
  52. 53 => 'dns',
  53. 1701 => 'vpn',
  54. 51820 => 'vpn',
  55. 443 => 'quic',
  56. 80 => 'quic',
  57. 5060=> 'sip',
  58. );
  59. /**
  60. * some predefined stuff here
  61. */
  62. const DATA_PATH = 'gdata/';
  63. const LR_PATH = 'exports/';
  64. const DELIMITER = ';';
  65. const TABLE_RAW_IN = 'raw_in';
  66. const TABLE_RAW_OUT = 'raw_out';
  67. public function __construct() {
  68. }
  69. /**
  70. * Drops datasource table data
  71. *
  72. * @param string $dataSource
  73. *
  74. * @return void
  75. */
  76. protected function flushSource($dataSource) {
  77. nr_query('TRUNCATE TABLE `' . $dataSource . '`');
  78. }
  79. /**
  80. * Returns record base struct
  81. *
  82. * @return array
  83. */
  84. public function getBaseStruct() {
  85. $result = array();
  86. if (!empty($this->baseStruct)) {
  87. foreach ($this->baseStruct as $class => $io) {
  88. if ($class != 'time') {
  89. $result[] = $class;
  90. }
  91. }
  92. }
  93. return ($result);
  94. }
  95. /**
  96. * Loads and returns all aggregated flows data in source and as ip=>baseStruct
  97. *
  98. * @param string $dataSource
  99. * @param string $ipColumn
  100. * @param string $portColumn
  101. *
  102. * @return array
  103. */
  104. public function aggregateSource($dataSource, $ipColumn, $portColumn) {
  105. $result = array();
  106. $rawData = array();
  107. $databaseLayer = new NyanORM($dataSource);
  108. $rawData = $databaseLayer->getAll();
  109. if (!empty($rawData)) {
  110. foreach ($rawData as $io => $each) {
  111. $ip = $each[$ipColumn];
  112. $time = $each['stamp_inserted'];
  113. $proto = $each['ip_proto'];
  114. $port = $each[$portColumn];
  115. if (!isset($result[$ip][$time])) {
  116. $result[$ip][$time] = $this->baseStruct;
  117. }
  118. $result[$ip][$time]['time'] = $time;
  119. $result[$ip][$time]['total'] += $each['bytes'];
  120. switch ($proto) {
  121. case 'icmp':
  122. $result[$ip][$time]['icmp'] += $each['bytes'];
  123. break;
  124. case 'tcp':
  125. $result[$ip][$time]['tcp'] += $each['bytes'];
  126. if (isset($this->tcpProto[$port])) {
  127. $result[$ip][$time][$this->tcpProto[$port]] += $each['bytes'];
  128. }
  129. break;
  130. case 'udp':
  131. $result[$ip][$time]['udp'] += $each['bytes'];
  132. if (isset($this->udpProto[$port])) {
  133. $result[$ip][$time][$this->udpProto[$port]] += $each['bytes'];
  134. }
  135. break;
  136. case 'gre':
  137. $result[$ip][$time]['vpn'] += $each['bytes'];
  138. break;
  139. case 'esp':
  140. $result[$ip][$time]['vpn'] += $each['bytes'];
  141. break;
  142. default:
  143. break;
  144. }
  145. }
  146. }
  147. $this->flushSource($dataSource);
  148. return ($result);
  149. }
  150. /**
  151. * Saves per-IP aggregated charts data
  152. *
  153. * @param string $direction
  154. * @param array $aggregatedData
  155. *
  156. * @return void
  157. */
  158. public function saveAggregatedData($direction, $aggregatedData) {
  159. if (!empty($aggregatedData)) {
  160. $fnamePrefix = self::DATA_PATH . $direction . '_';
  161. foreach ($aggregatedData as $eachIp => $eachTimeStamp) {
  162. $fileToSave = $fnamePrefix . $eachIp;
  163. $line = '';
  164. if (!empty($eachTimeStamp)) {
  165. foreach ($eachTimeStamp as $timeStamp => $lineData) {
  166. $line = '';
  167. $line .= implode(self::DELIMITER, $lineData);
  168. $line .= PHP_EOL;
  169. file_put_contents($fileToSave, $line, FILE_APPEND);
  170. }
  171. }
  172. }
  173. }
  174. }
  175. /**
  176. * Saves last run totals data, also as 0.0.0.0 chart data
  177. *
  178. * @param string $direction
  179. * @param array $aggregatedData
  180. *
  181. * @return void
  182. */
  183. public function saveLastRunData($direction, $aggregatedData) {
  184. if (!empty($aggregatedData)) {
  185. //raw last run data
  186. $fnameLr = self::LR_PATH . 'LR_' . $direction;
  187. $dataToSaveLr = json_encode($aggregatedData);
  188. file_put_contents($fnameLr, $dataToSaveLr);
  189. //total charts data
  190. $trafTotals = array();
  191. $baseStruct = $this->getBaseStruct();
  192. $tSctruct = array('time' => 0);
  193. foreach ($baseStruct as $io => $each) {
  194. $tSctruct[$each] = 0;
  195. }
  196. if (!empty($aggregatedData)) {
  197. foreach ($aggregatedData as $eachIp => $eachTs) {
  198. if (!empty($eachTs)) {
  199. foreach ($eachTs as $eachTimestamp => $eachBytes) {
  200. if (!isset($trafTotals[$eachTimestamp])) {
  201. $trafTotals[$eachTimestamp]['time'] = $eachTimestamp;
  202. $trafTotals[$eachTimestamp] += $tSctruct;
  203. }
  204. if (!empty($eachBytes)) {
  205. foreach ($eachBytes as $eachProto => $eachCounters) {
  206. if ($eachProto !== 'time') {
  207. $trafTotals[$eachTimestamp][$eachProto] += $eachCounters;
  208. }
  209. }
  210. }
  211. }
  212. }
  213. }
  214. }
  215. }
  216. if (!empty($trafTotals)) {
  217. $fnameTotal = self::DATA_PATH . $direction . '_' . '0.0.0.0';
  218. $line = '';
  219. if (!empty($trafTotals)) {
  220. foreach ($trafTotals as $io => $eachTotalsLine) {
  221. $line .= implode(self::DELIMITER, $eachTotalsLine);
  222. $line .= PHP_EOL;
  223. }
  224. }
  225. file_put_contents($fnameTotal, $line, FILE_APPEND);
  226. }
  227. }
  228. }