@@ -29,6 +29,8 @@ class Dot11Tracker:
2929 # pylint: disable=E1101, W0613
3030 def __init__ (self ,
3131 logger ,
32+ threshold ,
33+ power ,
3234 devices_to_watch ,
3335 aps_to_watch ,
3436 trigger_plugin ,
@@ -44,6 +46,9 @@ def __init__(self,
4446 # Same as self.arg = arg for every arg (except devices_to_watch and aps_to_watch)
4547 self .__dict__ .update ({k : v for k , v in locals ().items () if k != 'aps_to_watch' })
4648
49+ # If no particular things are specified to be watched, assume everything should be watched
50+ self .track_all = (not aps_to_watch and not devices_to_watch )
51+
4752 # Creates a map like: {'my_ssid1': {'threshold': 5000, 'last_alert': timestamp}, 'bssid2': {...} }
4853 self .bssids_to_watch = {}
4954 self .ssids_to_watch = {}
@@ -57,32 +62,78 @@ def __init__(self,
5762 self .ssids_to_watch [ap_identifier ] = watch_entry
5863
5964 def add_frame (self , frame ):
60- self .eval_device_triggers (frame .macs )
61- self .eval_bssid_triggers (frame .bssid )
62- self .eval_ssid_triggers (frame .ssid )
65+ if self .track_all :
66+ self .eval_general_mac_trigger (frame .macs , frame )
67+ self .eval_general_bssid_trigger (frame .bssid , frame )
68+ self .eval_general_ssid_trigger (frame .ssid , frame )
69+ else :
70+ self .eval_mac_triggers (frame .macs )
71+ self .eval_bssid_triggers (frame .bssid )
72+ self .eval_ssid_triggers (frame .ssid )
73+
74+ def eval_general_mac_trigger (self , macs , frame ):
75+ for mac in macs :
76+ dev_node = self .dot11_map .get_dev_node (mac )
77+ if not dev_node :
78+ continue
79+
80+ if self .threshold :
81+ # Calculate bytes received in the alert_window
82+ bytes_in_window = (self .get_bytes_in_window (dev_node ['frames_in' ]) +
83+ self .get_bytes_in_window (dev_node ['frames_out' ]))
84+ if bytes_in_window >= self .threshold :
85+ self .do_trigger_alert (mac , 'mac' , num_bytes = bytes_in_window )
86+
87+ if self .power and frame .signal_strength > self .power :
88+ self .do_trigger_alert (mac , 'mac' , power = dev_node ['signal' ])
89+
90+ def eval_general_bssid_trigger (self , bssid , frame ):
91+ bssid_node = self .dot11_map .get_ap_by_bssid (bssid )
92+ if self .threshold :
93+ bytes_in_window = self .get_bytes_in_window (bssid_node ['frames' ])
94+ if bytes_in_window >= self .threshold :
95+ self .do_trigger_alert (bssid , 'bssid' , num_bytes = bytes_in_window )
6396
64- def eval_device_triggers (self , macs ):
97+ if self .power and frame .signal_strength >= self .power :
98+ self .do_trigger_alert (bssid , 'bssid' , power = frame .signal_strength )
99+
100+ def eval_general_ssid_trigger (self , ssid , frame ):
101+ bssid_nodes = self .dot11_map .get_ap_nodes_by_ssid (ssid )
102+ if bssid_nodes :
103+ if self .threshold :
104+ bytes_in_window = reduce (lambda acc , bssid_bytes : acc + bssid_bytes ,
105+ [bssid_node ['frames' ] for bssid_node in bssid_nodes ],
106+ 0 )
107+ if bytes_in_window >= self .threshold :
108+ self .do_trigger_alert (ssid , 'ssid' , num_bytes = bytes_in_window )
109+
110+ if self .power and frame .signal_strength >= self .power :
111+ self .do_trigger_alert (ssid , 'bssid' , power = frame .signal_strength )
112+
113+ def eval_mac_triggers (self , macs ):
65114 # Only eval macs both on the "to watch" list and in the frame
66115 devices_to_eval = macs & self .devices_to_watch .keys ()
67116 for mac in devices_to_eval :
68117 dev_watch_node = self .devices_to_watch [mac ]
69118 dev_node = self .dot11_map .get_dev_node (mac )
70119 bytes_in_window = 0
120+ triggered = False
71121
72122 if dev_node :
73- if dev_watch_node ['power' ] and dev_node ['signal' ] > dev_watch_node ['power' ]:
74- self .do_trigger_alert (mac , 'device' , power = dev_node ['signal' ])
75- continue
76- elif dev_watch_node ['threshold' ]:
123+ if dev_watch_node ['threshold' ]:
77124 # Calculate bytes received in the alert_window
78125 bytes_in_window = (self .get_bytes_in_window (dev_node ['frames_in' ]) +
79126 self .get_bytes_in_window (dev_node ['frames_out' ]))
80127 if bytes_in_window >= dev_watch_node ['threshold' ]:
81- self .do_trigger_alert (mac , 'device' , num_bytes = bytes_in_window )
82- continue
128+ self .do_trigger_alert (mac , 'mac' , num_bytes = bytes_in_window )
129+ triggered = True
130+ if dev_watch_node ['power' ] and dev_node ['signal' ] > dev_watch_node ['power' ]:
131+ self .do_trigger_alert (mac , 'mac' , power = dev_node ['signal' ])
132+ triggered = True
83133
84- self .logger .debug ('Bytes received for {} (threshold: {}) in last {} seconds: {}'
85- .format (mac , dev_watch_node ['threshold' ], self .threshold_window , bytes_in_window ))
134+ if not triggered :
135+ self .logger .debug ('Bytes received for {} (threshold: {}) in last {} seconds: {}'
136+ .format (mac , dev_watch_node ['threshold' ], self .threshold_window , bytes_in_window ))
86137
87138 def eval_bssid_triggers (self , bssid ):
88139 if bssid not in self .bssids_to_watch :
@@ -91,15 +142,21 @@ def eval_bssid_triggers(self, bssid):
91142 bssid_watch_node = self .bssids_to_watch [bssid ]
92143 bssid_node = self .dot11_map .get_ap_by_bssid (bssid )
93144 bytes_in_window = 0
145+ triggered = False
94146
95147 if bssid_node :
148+ if bssid_watch_node ['power' ] and bssid_node ['signal' ] >= bssid_watch_node ['power' ]:
149+ self .do_trigger_alert (bssid , 'bssid' , power = bssid_node ['signal' ])
150+ triggered = True
151+
96152 bytes_in_window = self .get_bytes_in_window (bssid_node ['frames' ])
97- if bytes_in_window >= bssid_watch_node ['threshold' ]:
153+ if bssid_watch_node [ 'threshold' ] and bytes_in_window >= bssid_watch_node ['threshold' ]:
98154 self .do_trigger_alert (bssid , 'bssid' , num_bytes = bytes_in_window )
99- return
155+ triggered = True
100156
101- self .logger .info ('Bytes received for {} in last {} seconds: {}'
102- .format (bssid , self .threshold_window , bytes_in_window ))
157+ if not triggered :
158+ self .logger .info ('Bytes received for {} in last {} seconds: {}'
159+ .format (bssid , self .threshold_window , bytes_in_window ))
103160
104161 def eval_ssid_triggers (self , ssid ):
105162 if ssid not in self .ssids_to_watch :
0 commit comments