commit e3bed9a7319989c20e75bf8352293346812e5b79
Author: Damian Johnson <atagar(a)torproject.org>
Date: Mon Oct 5 08:36:30 2015 -0700
Only notify for endpoints once per day
Relays can cycle their fingerprint every hour. No need to cause a deluge of
noise - only notifying for an endpoint once per day.
---
fingerprint_change_checker.py | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/fingerprint_change_checker.py b/fingerprint_change_checker.py
index 1f9319f..45ae4e0 100755
--- a/fingerprint_change_checker.py
+++ b/fingerprint_change_checker.py
@@ -8,6 +8,7 @@ This can indicate malicious intent toward hidden services.
"""
import datetime
+import os
import time
import traceback
@@ -24,12 +25,21 @@ The following relays are frequently changing their fingerprints...
"""
FINGERPRINT_CHANGES_FILE = util.get_path('data', 'fingerprint_changes')
+ONE_DAY = 24 * 60 * 60
THIRTY_DAYS = 30 * 24 * 60 * 60
log = util.get_logger('fingerprint_change_checker')
def main():
+ last_notified_config = conf.get_config('last_notified')
+ last_notified_path = util.get_path('data', 'fingerprint_change_last_notified.cfg')
+
+ if os.path.exists(last_notified_path):
+ last_notified_config.load(last_notified_path)
+ else:
+ last_notified_config._path = last_notified_path
+
fingerprint_changes = load_fingerprint_changes()
downloader = DescriptorDownloader(timeout = 15)
alarm_for = set()
@@ -54,7 +64,7 @@ def main():
if len(prior_fingerprints) >= 3:
alarm_for.add((relay.address, relay.or_port))
- if alarm_for:
+ if alarm_for and not is_notification_suppressed(alarm_for):
log.debug("Sending a notification for %i relays..." % len(alarm_for))
body = EMAIL_BODY
@@ -131,6 +141,33 @@ def save_fingerprint_changes(fingerprint_changes):
log.debug(" unable to save '%s': %s" % (FINGERPRINT_CHANGES_FILE, exc))
+def is_notification_suppressed(fingerprint_changes):
+ """
+ Check to see if we've already notified for all these endpoints today. No
+ point in causing too much noise.
+ """
+
+ is_all_suppressed = True
+ log.debug("Checking if notification should be suppressed...")
+ last_notified_config = conf.get_config('last_notified')
+
+ for address, or_port in fingerprint_changes:
+ key = '%s:%s' % (address, or_port)
+ current_time = int(time.time())
+ suppression_time = ONE_DAY - (current_time - last_notified_config.get(key, 0))
+
+ if suppression_time < 0:
+ log.debug("* notification for %s isn't suppressed" % key)
+ is_all_suppressed = False
+ else:
+ log.debug("* we already notified for %s recently, suppressed for %i hours" % (key, suppression_time / 3600))
+
+ last_notified_config.set(key, str(current_time), overwrite = True)
+
+ last_notified_config.save()
+ return is_all_suppressed
+
+
if __name__ == '__main__':
try:
main()