privacy: only store coarse timestamps in the usage table

This commit is contained in:
Brian Warner 2015-12-03 21:15:19 -08:00
parent ee86059b0a
commit 1ab66d2fd0
6 changed files with 35 additions and 10 deletions

View File

@ -41,6 +41,9 @@ sp_start.add_argument("--transit", default="tcp:3001", metavar="tcp:PORT",
help="endpoint specification for the transit-relay port") help="endpoint specification for the transit-relay port")
sp_start.add_argument("--advertise-version", metavar="VERSION", sp_start.add_argument("--advertise-version", metavar="VERSION",
help="version to recommend to clients") help="version to recommend to clients")
sp_start.add_argument("--blur-usage", default=None, type=int,
metavar="SECONDS",
help="round logged access times to improve privacy")
sp_start.add_argument("-n", "--no-daemon", action="store_true") sp_start.add_argument("-n", "--no-daemon", action="store_true")
#sp_start.add_argument("twistd_args", nargs="*", default=None, #sp_start.add_argument("twistd_args", nargs="*", default=None,
# metavar="[TWISTD-ARGS..]", # metavar="[TWISTD-ARGS..]",
@ -61,6 +64,9 @@ sp_restart.add_argument("--transit", default="tcp:3001", metavar="tcp:PORT",
help="endpoint specification for the transit-relay port") help="endpoint specification for the transit-relay port")
sp_restart.add_argument("--advertise-version", metavar="VERSION", sp_restart.add_argument("--advertise-version", metavar="VERSION",
help="version to recommend to clients") help="version to recommend to clients")
sp_restart.add_argument("--blur-usage", default=None, type=int,
metavar="SECONDS",
help="round logged access times to improve privacy")
sp_restart.add_argument("-n", "--no-daemon", action="store_true") sp_restart.add_argument("-n", "--no-daemon", action="store_true")
sp_restart.set_defaults(func=cmd_server.restart_server) sp_restart.set_defaults(func=cmd_server.restart_server)

View File

@ -11,7 +11,7 @@ class MyPlugin:
from .server import RelayServer from .server import RelayServer
return RelayServer(self.args.rendezvous, self.args.transit, return RelayServer(self.args.rendezvous, self.args.transit,
self.args.advertise_version, self.args.advertise_version,
"relay.sqlite") "relay.sqlite", self.args.blur_usage)
def start_server(args): def start_server(args):
from twisted.python import usage from twisted.python import usage

View File

@ -207,10 +207,11 @@ class Deallocator(RelayResource):
class Channel: class Channel:
def __init__(self, app, db, welcome, appid, channelid): def __init__(self, app, db, welcome, blur_usage, appid, channelid):
self._app = app self._app = app
self._db = db self._db = db
self._welcome = welcome self._welcome = welcome
self._blur_usage = blur_usage
self._appid = appid self._appid = appid
self._channelid = channelid self._channelid = channelid
self._listeners = set() # callbacks that take JSONable object self._listeners = set() # callbacks that take JSONable object
@ -297,6 +298,8 @@ class Channel:
def _store_summary(self, summary): def _store_summary(self, summary):
(started, result, total_time, waiting_time) = summary (started, result, total_time, waiting_time) = summary
if self._blur_usage:
started = self._blur_usage * (started // self._blur_usage)
self._db.execute("INSERT INTO `usage`" self._db.execute("INSERT INTO `usage`"
" (`type`, `started`, `result`," " (`type`, `started`, `result`,"
" `total_time`, `waiting_time`)" " `total_time`, `waiting_time`)"
@ -382,9 +385,10 @@ class Channel:
class AppNamespace: class AppNamespace:
def __init__(self, db, welcome, appid): def __init__(self, db, welcome, blur_usage, appid):
self._db = db self._db = db
self._welcome = welcome self._welcome = welcome
self._blur_usage = blur_usage
self._appid = appid self._appid = appid
self._channels = {} self._channels = {}
@ -420,6 +424,7 @@ class AppNamespace:
if not channelid in self._channels: if not channelid in self._channels:
log.msg("spawning #%d for appid %s" % (channelid, self._appid)) log.msg("spawning #%d for appid %s" % (channelid, self._appid))
self._channels[channelid] = Channel(self, self._db, self._welcome, self._channels[channelid] = Channel(self, self._db, self._welcome,
self._blur_usage,
self._appid, channelid) self._appid, channelid)
return self._channels[channelid] return self._channels[channelid]
@ -448,11 +453,12 @@ class AppNamespace:
return bool(self._channels) return bool(self._channels)
class Relay(resource.Resource, service.MultiService): class Relay(resource.Resource, service.MultiService):
def __init__(self, db, welcome): def __init__(self, db, welcome, blur_usage):
resource.Resource.__init__(self) resource.Resource.__init__(self)
service.MultiService.__init__(self) service.MultiService.__init__(self)
self._db = db self._db = db
self._welcome = welcome self._welcome = welcome
self._blur_usage = blur_usage
self._apps = {} self._apps = {}
t = internet.TimerService(EXPIRATION_CHECK_PERIOD, self.prune) t = internet.TimerService(EXPIRATION_CHECK_PERIOD, self.prune)
t.setServiceParent(self) t.setServiceParent(self)
@ -476,7 +482,8 @@ class Relay(resource.Resource, service.MultiService):
assert isinstance(appid, type(u"")) assert isinstance(appid, type(u""))
if not appid in self._apps: if not appid in self._apps:
log.msg("spawning appid %s" % (appid,)) log.msg("spawning appid %s" % (appid,))
self._apps[appid] = AppNamespace(self._db, self._welcome, appid) self._apps[appid] = AppNamespace(self._db, self._welcome,
self._blur_usage, appid)
return self._apps[appid] return self._apps[appid]
def prune(self): def prune(self):

View File

@ -1,4 +1,5 @@
from __future__ import print_function from __future__ import print_function
from twisted.python import log
from twisted.internet import reactor, endpoints from twisted.internet import reactor, endpoints
from twisted.application import service from twisted.application import service
from twisted.web import server, static, resource from twisted.web import server, static, resource
@ -16,8 +17,9 @@ class Root(resource.Resource):
class RelayServer(service.MultiService): class RelayServer(service.MultiService):
def __init__(self, relayport, transitport, advertise_version, def __init__(self, relayport, transitport, advertise_version,
db_url=":memory:"): db_url=":memory:", blur_usage=None):
service.MultiService.__init__(self) service.MultiService.__init__(self)
self._blur_usage = blur_usage
self.db = get_db(db_url) self.db = get_db(db_url)
welcome = { welcome = {
"current_version": __version__, "current_version": __version__,
@ -35,11 +37,18 @@ class RelayServer(service.MultiService):
r = endpoints.serverFromString(reactor, relayport) r = endpoints.serverFromString(reactor, relayport)
self.relayport_service = ServerEndpointService(r, site) self.relayport_service = ServerEndpointService(r, site)
self.relayport_service.setServiceParent(self) self.relayport_service.setServiceParent(self)
self.relay = Relay(self.db, welcome) # accessible from tests self.relay = Relay(self.db, welcome, blur_usage) # accessible from tests
self.root.putChild(b"wormhole-relay", self.relay) self.root.putChild(b"wormhole-relay", self.relay)
if transitport: if transitport:
self.transit = Transit(self.db) self.transit = Transit(self.db, blur_usage)
self.transit.setServiceParent(self) # for the timer self.transit.setServiceParent(self) # for the timer
t = endpoints.serverFromString(reactor, transitport) t = endpoints.serverFromString(reactor, transitport)
self.transport_service = ServerEndpointService(t, self.transit) self.transport_service = ServerEndpointService(t, self.transit)
self.transport_service.setServiceParent(self) self.transport_service.setServiceParent(self)
def startService(self):
service.MultiService.startService(self)
log.msg("Wormhole relay server (Rendezvous and Transit) running")
if self._blur_usage:
log.msg("blurring access times to %d seconds" % self._blur_usage)
else:
log.msg("not blurring access times")

View File

@ -148,9 +148,10 @@ class Transit(protocol.ServerFactory, service.MultiService):
MAXTIME = 60*SECONDS MAXTIME = 60*SECONDS
protocol = TransitConnection protocol = TransitConnection
def __init__(self, db): def __init__(self, db, blur_usage):
service.MultiService.__init__(self) service.MultiService.__init__(self)
self._db = db self._db = db
self._blur_usage = blur_usage
self._pending_requests = {} # token -> TransitConnection self._pending_requests = {} # token -> TransitConnection
self._active_connections = set() # TransitConnection self._active_connections = set() # TransitConnection
@ -170,6 +171,8 @@ class Transit(protocol.ServerFactory, service.MultiService):
def recordUsage(self, started, result, total_bytes, def recordUsage(self, started, result, total_bytes,
total_time, waiting_time): total_time, waiting_time):
log.msg("Transit.recordUsage (%dB)" % total_bytes) log.msg("Transit.recordUsage (%dB)" % total_bytes)
if self._blur_usage:
started = self._blur_usage * (started // self._blur_usage)
self._db.execute("INSERT INTO `usage`" self._db.execute("INSERT INTO `usage`"
" (`type`, `started`, `result`, `total_bytes`," " (`type`, `started`, `result`, `total_bytes`,"
" `total_time`, `waiting_time`)" " `total_time`, `waiting_time`)"

View File

@ -363,7 +363,7 @@ class OneEventAtATime:
class Summary(unittest.TestCase): class Summary(unittest.TestCase):
def test_summarize(self): def test_summarize(self):
c = relay_server.Channel(None, None, None, None, None) c = relay_server.Channel(None, None, None, None, None, None)
A = relay_server.ALLOCATE A = relay_server.ALLOCATE
D = relay_server.DEALLOCATE D = relay_server.DEALLOCATE