commit a91384c90639c71dad3486813f85b9bbf79bf2c4 Author: Tom Ritter tom@ritter.vg Date: Fri Apr 20 10:30:59 2018 -0500
Add Clock Skew. Closes #25767 --- data/consensus.cfg | 3 +++ utility.py | 28 +++++++++++++++++++++++++++ website.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++- write_website.py | 5 ++++- 4 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/data/consensus.cfg b/data/consensus.cfg index 02f39b1..e4af54a 100644 --- a/data/consensus.cfg +++ b/data/consensus.cfg @@ -9,6 +9,9 @@ graph_logical_min 125 # do not show values values greater than this on the graph. You can leave this high graph_logical_max 25000
+# we highlight clockskew that is 20 seconds or greater +clockskew_threshold 20 + # recognized tor consensus parameters
known_params bwweightscale diff --git a/utility.py b/utility.py old mode 100644 new mode 100755 index 6b2cfae..d4f9a68 --- a/utility.py +++ b/utility.py @@ -1,4 +1,7 @@ +#!/usr/bin/env python + import time +import urllib import datetime
import stem.descriptor @@ -81,6 +84,26 @@ def _get_documents(label, resource):
return documents, issues, runtimes
+def get_clockskew(): + clockskew = {} + for (nickname, authority) in get_dirauths().items(): + authority_address = "http://" + str(authority.address) + ":" + str(authority.dir_port) + try: + startTimeStamp = datetime.datetime.utcnow() + startTime = time.time() + f = urllib.urlopen(authority_address) + for h in f.info().headers: + if h.upper().startswith('DATE:'): + clockskew[nickname] = datetime.datetime.strptime(h[6:].strip(), '%a, %d %b %Y %H:%M:%S %Z') + processing = time.time() - startTime + if processing > 5: + clockskew[nickname] -= datetime.timedelta(seconds=(processing / 2)) + clockskew[nickname] -= startTimeStamp + clockskew[nickname] = clockskew[nickname].total_seconds() + except: + continue + return clockskew + def unix_time(dt): return (dt - datetime.datetime.utcfromtimestamp(0)).total_seconds() * 1000.0
@@ -98,3 +121,8 @@ class FileMock(): pass def write(self, str): pass + +if __name__ == "__main__": + skew = get_clockskew() + for c in skew: + print c, skew[c] \ No newline at end of file diff --git a/website.py b/website.py index 02fbdce..d3fa842 100755 --- a/website.py +++ b/website.py @@ -24,6 +24,7 @@ class WebsiteWriter: consensus = None votes = None fallback_dirs = None + clockskew = None known_authorities = [] bandwidth_authorities = [] consensus_expiry = datetime.timedelta(hours=3) @@ -51,6 +52,7 @@ class WebsiteWriter: self._write_recommended_versions() self._write_consensus_parameters() self._write_authority_keys() + self._write_authority_clocks() self._write_shared_random() self._write_protocols() self._write_bandwidth_weights() @@ -82,6 +84,8 @@ class WebsiteWriter: self.known_params = config['known_params'] def set_fallback_dirs(self, fallback_dirs): self.fallback_dirs = fallback_dirs + def set_clockskew(self, clockskew): + self.clockskew = clockskew def get_consensus_time(self): return self.consensus.valid_after def all_votes_present(self): @@ -691,6 +695,55 @@ class WebsiteWriter: + "</p>\n")
#----------------------------------------------------------------------------------------- + def _write_authority_clocks(self): + """ + Write authority clock skew + """ + self.site.write("<br>\n\n\n" + + " <!-- ================================================================= -->" + + "<a name="authorityclocks">\n" + + "<h3><a href="#authorityclocks" class="anchor">" + + "Authority Clock Skew</a></h3>\n" + + "<br>\n" + + "<table border="0" cellpadding="4" cellspacing="0" summary="">\n" + + " <colgroup>\n" + + " <col width="160">\n" + + " <col width="640">\n" + + " </colgroup>\n" + + " <tr>\n" + + " <th>Name</th>" + + " <th>Approximate Clock Skew</th>" + + " </tr>\n") + + if not self.clockskew: + self.site.write(" <tr><td>(No clock skew data.)</td><td></td></tr>\n") + else: + for dirauth_nickname in self.known_authorities: + if dirauth_nickname in self.clockskew: + clock = self.clockskew[dirauth_nickname] + + if clock > self.config['clockskew_threshold']: + self.site.write(" <tr>\n" + + " <td class="oiv">" + dirauth_nickname + "</td>\n" + + " <td class="oiv">" + + str(clock) + " seconds</td>\n </tr>\n") + else: + self.site.write(" <tr>\n" + + " <td>" + dirauth_nickname + "</td>\n" + + " <td>" + + str(clock) + " seconds</td>\n </tr>\n") + else: + self.site.write(" <tr>\n" + + " <td>" + dirauth_nickname + "</td>\n" + + " <td><span class="oiv">Could not query authority<span></td>\n" + + " </tr>\n") + + self.site.write("</table>\n" + + "<br>\n" + + "<p><i>Times are roughly accurate, anything below a couple seconds should be fine. Please use this table as a guide rather than an authoritative source.</i>" + + "</p>\n") + + #----------------------------------------------------------------------------------------- def sharedRandomToStr(self, sr): s = "[" s += "V:" + str(sr.version) + " " @@ -1632,7 +1685,8 @@ if __name__ == '__main__': 'known_params': [], 'ignore_fallback_authorities': False, 'graph_logical_min': 125, - 'graph_logical_max': 25000 + 'graph_logical_max': 25000, + 'clockskew_threshold': 0, }) config = stem.util.conf.get_config("consensus") config.load(os.path.join(os.path.dirname(__file__), 'data', 'consensus.cfg')) diff --git a/write_website.py b/write_website.py index d8d3e3f..f79e2c3 100755 --- a/write_website.py +++ b/write_website.py @@ -48,7 +48,8 @@ CONFIG = stem.util.conf.config_dict('consensus', { 'known_params': [], 'ignore_fallback_authorities' : False, 'graph_logical_min' : 125, - 'graph_logical_max' : 25000 + 'graph_logical_max' : 25000, + 'clockskew_threshold': 0, })
def main(): @@ -58,6 +59,7 @@ def main():
consensuses, consensus_fetching_issues, consensus_fetching_runtimes = get_consensuses() votes, vote_fetching_issues, vote_fetching_runtimes = get_votes() + clockskew = get_clockskew()
# updates the download statistics file f = open(os.path.join(os.path.dirname(__file__), 'out', 'download-stats.csv'), 'a') @@ -299,6 +301,7 @@ def main(): w.set_consensuses(consensuses) w.set_votes(votes) w.set_fallback_dirs(fallback_dirs) + w.set_clockskew(clockskew) w.write_website(os.path.join(os.path.dirname(__file__), 'out', 'consensus-health.html'), \ True, os.path.join(os.path.dirname(__file__), 'out', 'relay-indexes.txt')) w.write_website(os.path.join(os.path.dirname(__file__), 'out', 'index.html'), False)
tor-commits@lists.torproject.org