Add a 'trustedpeer' option to keys.dat #639
|
@ -22,26 +22,37 @@ class outgoingSynSender(threading.Thread):
|
||||||
self.streamNumber = streamNumber
|
self.streamNumber = streamNumber
|
||||||
self.selfInitiatedConnections = selfInitiatedConnections
|
self.selfInitiatedConnections = selfInitiatedConnections
|
||||||
|
|
||||||
|
def _getPeer(self):
|
||||||
|
# If the user has specified a trusted peer then we'll only
|
||||||
|
# ever connect to that. Otherwise we'll pick a random one from
|
||||||
|
# the known nodes
|
||||||
|
shared.knownNodesLock.acquire()
|
||||||
|
if shared.trustedPeer:
|
||||||
|
peer = shared.trustedPeer
|
||||||
|
shared.knownNodes[self.streamNumber][peer] = time.time()
|
||||||
|
else:
|
||||||
|
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
|
||||||
|
shared.knownNodesLock.release()
|
||||||
|
|
||||||
|
return peer
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
|
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
while shared.safeConfigGetBoolean('bitmessagesettings', 'sendoutgoingconnections'):
|
while shared.safeConfigGetBoolean('bitmessagesettings', 'sendoutgoingconnections'):
|
||||||
while len(self.selfInitiatedConnections[self.streamNumber]) >= 8: # maximum number of outgoing connections = 8
|
maximumConnections = 1 if shared.trustedPeer else 8 # maximum number of outgoing connections = 8
|
||||||
|
while len(self.selfInitiatedConnections[self.streamNumber]) >= maximumConnections:
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
if shared.shutdown:
|
if shared.shutdown:
|
||||||
break
|
break
|
||||||
random.seed()
|
random.seed()
|
||||||
shared.knownNodesLock.acquire()
|
peer = self._getPeer()
|
||||||
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
|
|
||||||
shared.knownNodesLock.release()
|
|
||||||
shared.alreadyAttemptedConnectionsListLock.acquire()
|
shared.alreadyAttemptedConnectionsListLock.acquire()
|
||||||
while peer in shared.alreadyAttemptedConnectionsList or peer.host in shared.connectedHostsList:
|
while peer in shared.alreadyAttemptedConnectionsList or peer.host in shared.connectedHostsList:
|
||||||
shared.alreadyAttemptedConnectionsListLock.release()
|
shared.alreadyAttemptedConnectionsListLock.release()
|
||||||
# print 'choosing new sample'
|
# print 'choosing new sample'
|
||||||
random.seed()
|
random.seed()
|
||||||
shared.knownNodesLock.acquire()
|
peer = self._getPeer()
|
||||||
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
|
|
||||||
shared.knownNodesLock.release()
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
# Clear out the shared.alreadyAttemptedConnectionsList every half
|
# Clear out the shared.alreadyAttemptedConnectionsList every half
|
||||||
# hour so that this program will again attempt a connection
|
# hour so that this program will again attempt a connection
|
||||||
|
|
|
@ -313,6 +313,14 @@ class receiveDataThread(threading.Thread):
|
||||||
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
|
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
|
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
|
||||||
|
|
||||||
|
def _sleepForTimingAttackMitigation(self, sleepTime):
|
||||||
|
# We don't need to do the timing attack mitigation if we are
|
||||||
|
# only connected to the trusted peer because we can trust the
|
||||||
|
# peer not to attack
|
||||||
|
if sleepTime > 0 and doTimingAttackMitigation and shared.trustedPeer == None:
|
||||||
|
with shared.printLock:
|
||||||
|
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
|
||||||
|
time.sleep(sleepTime)
|
||||||
|
|
||||||
# We have received a broadcast message
|
# We have received a broadcast message
|
||||||
def recbroadcast(self, data):
|
def recbroadcast(self, data):
|
||||||
|
@ -341,10 +349,7 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
||||||
(time.time() - self.messageProcessingStartTime)
|
(time.time() - self.messageProcessingStartTime)
|
||||||
if sleepTime > 0 and doTimingAttackMitigation:
|
self._sleepForTimingAttackMitigation(sleepTime)
|
||||||
with shared.printLock:
|
|
||||||
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
|
|
||||||
time.sleep(sleepTime)
|
|
||||||
|
|
||||||
# We have received a msg message.
|
# We have received a msg message.
|
||||||
def recmsg(self, data):
|
def recmsg(self, data):
|
||||||
|
@ -373,10 +378,7 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
||||||
(time.time() - self.messageProcessingStartTime)
|
(time.time() - self.messageProcessingStartTime)
|
||||||
if sleepTime > 0 and doTimingAttackMitigation:
|
self._sleepForTimingAttackMitigation(sleepTime)
|
||||||
with shared.printLock:
|
|
||||||
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
|
|
||||||
time.sleep(sleepTime)
|
|
||||||
|
|
||||||
# We have received a pubkey
|
# We have received a pubkey
|
||||||
def recpubkey(self, data):
|
def recpubkey(self, data):
|
||||||
|
@ -387,11 +389,7 @@ class receiveDataThread(threading.Thread):
|
||||||
lengthOfTimeWeShouldUseToProcessThisMessage = .1
|
lengthOfTimeWeShouldUseToProcessThisMessage = .1
|
||||||
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
|
||||||
(time.time() - self.pubkeyProcessingStartTime)
|
(time.time() - self.pubkeyProcessingStartTime)
|
||||||
if sleepTime > 0 and doTimingAttackMitigation:
|
self._sleepForTimingAttackMitigation(sleepTime)
|
||||||
with shared.printLock:
|
|
||||||
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
|
|
||||||
time.sleep(sleepTime)
|
|
||||||
|
|
||||||
|
|
||||||
# We have received an inv message
|
# We have received an inv message
|
||||||
def recinv(self, data):
|
def recinv(self, data):
|
||||||
|
|
|
@ -22,6 +22,11 @@ class singleListener(threading.Thread):
|
||||||
self.selfInitiatedConnections = selfInitiatedConnections
|
self.selfInitiatedConnections = selfInitiatedConnections
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
# If there is a trusted peer then we don't want to accept
|
||||||
|
# incoming connections so we'll just abandon the thread
|
||||||
|
if shared.trustedPeer:
|
||||||
|
return
|
||||||
|
|
||||||
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
|
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
helper_bootstrap.dns()
|
helper_bootstrap.dns()
|
||||||
|
|
|
@ -12,6 +12,17 @@ from namecoin import ensureNamecoinOptions
|
||||||
|
|
||||||
storeConfigFilesInSameDirectoryAsProgramByDefault = False # The user may de-select Portable Mode in the settings if they want the config files to stay in the application data folder.
|
storeConfigFilesInSameDirectoryAsProgramByDefault = False # The user may de-select Portable Mode in the settings if they want the config files to stay in the application data folder.
|
||||||
|
|
||||||
|
def _loadTrustedPeer():
|
||||||
|
try:
|
||||||
|
trustedPeer = shared.config.get('bitmessagesettings', 'trustedpeer')
|
||||||
|
except ConfigParser.Error:
|
||||||
|
# This probably means the trusted peer wasn't specified so we
|
||||||
|
# can just leave it as None
|
||||||
|
return
|
||||||
|
|
||||||
|
host, port = trustedPeer.split(':')
|
||||||
|
shared.trustedPeer = shared.Peer(host, int(port))
|
||||||
|
|
||||||
def loadConfig():
|
def loadConfig():
|
||||||
if shared.appdata:
|
if shared.appdata:
|
||||||
shared.config.read(shared.appdata + 'keys.dat')
|
shared.config.read(shared.appdata + 'keys.dat')
|
||||||
|
@ -122,6 +133,8 @@ def loadConfig():
|
||||||
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
shared.config.write(configfile)
|
shared.config.write(configfile)
|
||||||
|
|
||||||
|
_loadTrustedPeer()
|
||||||
|
|
||||||
def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
|
def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
|
||||||
try:
|
try:
|
||||||
VER_THIS=StrictVersion(platform.version())
|
VER_THIS=StrictVersion(platform.version())
|
||||||
|
|
|
@ -92,6 +92,18 @@ namecoinDefaultRpcPort = "8336"
|
||||||
# binary distributions vs source distributions.
|
# binary distributions vs source distributions.
|
||||||
frozen = getattr(sys,'frozen', None)
|
frozen = getattr(sys,'frozen', None)
|
||||||
|
|
||||||
|
# If the trustedpeer option is specified in keys.dat then this will
|
||||||
|
# contain a Peer which will be connected to instead of using the
|
||||||
|
# addresses advertised by other peers. The client will only connect to
|
||||||
|
# this peer and the timing attack mitigation will be disabled in order
|
||||||
|
# to download data faster. The expected use case is where the user has
|
||||||
|
# a fast connection to a trusted server where they run a BitMessage
|
||||||
|
# daemon permanently. If they then run a second instance of the client
|
||||||
|
# on a local machine periodically when they want to check for messages
|
||||||
|
# it will sync with the network a lot faster without compromising
|
||||||
|
# security.
|
||||||
|
trustedPeer = None
|
||||||
|
|
||||||
def isInSqlInventory(hash):
|
def isInSqlInventory(hash):
|
||||||
queryreturn = sqlQuery('''select hash from inventory where hash=?''', hash)
|
queryreturn = sqlQuery('''select hash from inventory where hash=?''', hash)
|
||||||
return queryreturn != []
|
return queryreturn != []
|
||||||
|
|
Reference in New Issue
Block a user