work on direct connections

This commit is contained in:
Kevin Froman 2019-03-19 00:09:53 -05:00
parent a87d1bf1e8
commit 2da5e0479a
6 changed files with 62 additions and 53 deletions

View File

@ -24,7 +24,7 @@ from dependencies import secrets
from utils import networkmerger from utils import networkmerger
import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block
from communicatorutils import onionrdaemontools from communicatorutils import onionrdaemontools
import onionrsockets, onionr, onionrproofs import onionrservices, onionr, onionrproofs
from communicatorutils import onionrcommunicatortimers, proxypicker from communicatorutils import onionrcommunicatortimers, proxypicker
OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers
@ -126,9 +126,9 @@ class OnionrCommunicatorDaemon:
#forwardSecrecyTimer.count = (forwardSecrecyTimer.frequency - 990) #forwardSecrecyTimer.count = (forwardSecrecyTimer.frequency - 990)
if config.get('general.socket_servers'): if config.get('general.socket_servers'):
self.socketServer = threading.Thread(target=onionrsockets.OnionrSocketServer, args=(self._core,)) self.services = onionrservices.OnionrServices(self._core)
self.socketServer.start() else:
self.socketClient = onionrsockets.OnionrSocketClient(self._core) self.services = None
# Main daemon loop, mainly for calling timers, don't do any complex operations here to avoid locking # Main daemon loop, mainly for calling timers, don't do any complex operations here to avoid locking
try: try:
@ -565,19 +565,6 @@ class OnionrCommunicatorDaemon:
i.count = (i.frequency - 1) i.count = (i.frequency - 1)
elif cmd[0] == 'uploadBlock': elif cmd[0] == 'uploadBlock':
self.blocksToUpload.append(cmd[1]) self.blocksToUpload.append(cmd[1])
elif cmd[0] == 'startSocket':
# Create our own socket server
socketInfo = json.loads(cmd[1])
socketInfo['id'] = uuid.uuid4()
self._core.startSocket = socketInfo
elif cmd[0] == 'addSocket':
# Socket server was created for us
socketInfo = json.loads(cmd[1])
peer = socketInfo['peer']
reason = socketInfo['reason']
threading.Thread(target=self.socketClient.startSocket, args=(peer, reason)).start()
else:
logger.info('Recieved daemonQueue command:' + cmd[0])
if cmd[0] not in ('', None): if cmd[0] not in ('', None):
if response != '': if response != '':

View File

@ -355,7 +355,6 @@ class Core:
conn = sqlite3.connect(self.queueDB, timeout=30) conn = sqlite3.connect(self.queueDB, timeout=30)
c = conn.cursor() c = conn.cursor()
t = (command, data, date, responseID) t = (command, data, date, responseID)
try: try:
c.execute('INSERT INTO commands (command, data, date, responseID) VALUES(?, ?, ?, ?)', t) c.execute('INSERT INTO commands (command, data, date, responseID) VALUES(?, ?, ?, ?)', t)
conn.commit() conn.commit()

View File

@ -1,16 +1,28 @@
import time
import stem import stem
import core import core
from . import connectionserver, connectionclient, bootstrapservice from . import connectionserver, bootstrapservice
class OnionrServices: class OnionrServices:
def __init__(self, onionr_core): def __init__(self, onionr_core):
assert isinstance(onionr_core, core.Core) assert isinstance(onionr_core, core.Core)
self._core = onionr_core self._core = onionr_core
self.servers = {} self.servers = {}
self.clients = {} self.clients = {}
self.shutdown = False
return return
def create_server(self): def create_server(self, peer, address):
return assert self._core._utils.validateID(address)
BOOTSTRAP_TRIES = 10
TRY_WAIT = 3
for x in range(BOOTSTRAP_TRIES):
if self._core._utils.doGetRequest('http://' + address + '/ping') == 'pong!':
connectionserver.ConnectionServer(peer, address, core_inst=self._core)
return True
else:
time.sleep(TRY_WAIT)
else:
return False
def create_client(self, peer): def create_client(self, peer):
# Create ephemeral onion service to bootstrap connection # Create ephemeral onion service to bootstrap connection

View File

@ -23,7 +23,7 @@ from flask import Flask
import core import core
from netcontroller import getOpenPort from netcontroller import getOpenPort
def bootstrap_client_service(peer, core_inst=None): def bootstrap_client_service(peer, core_inst=None, bootstrap_timeout=120):
''' '''
Bootstrap client services Bootstrap client services
''' '''
@ -33,9 +33,9 @@ def bootstrap_client_service(peer, core_inst=None):
if not core_inst._utils.validatePubKey(peer): if not core_inst._utils.validatePubKey(peer):
raise ValueError('Peer must be valid base32 ed25519 public key') raise ValueError('Peer must be valid base32 ed25519 public key')
http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None)
bootstrap_port = getOpenPort() bootstrap_port = getOpenPort()
bootstrap_app = flask.Flask(__name__) bootstrap_app = Flask(__name__)
http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None)
bootstrap_address = '' bootstrap_address = ''
@ -50,14 +50,14 @@ def bootstrap_client_service(peer, core_inst=None):
bootstrap_address = address bootstrap_address = address
http_server.stop() http_server.stop()
with Controller.from_port() as controller: with Controller.from_port(port=core_inst.config.get('tor.controlPort')) as controller:
# Connect to the Tor process for Onionr # Connect to the Tor process for Onionr
controller.authenticate() controller.authenticate(core_inst.config.get('tor.controlpassword'))
# Create the v3 onion service # Create the v3 onion service
response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, await_publication = True, key_type='ED25519-V3') response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, await_publication = True, key_content = 'ED25519-V3')
core_inst.insertBlock(response.hostname, header='con', sign=True, encryptType='asym', core_inst.insertBlock(response.service_id, header='con', sign=True, encryptType='asym',
asymPeer=peer, disableForward=True) asymPeer=peer, disableForward=True, expire=(core_inst._utils.getEpoch() + bootstrap_timeout))
# Run the bootstrap server # Run the bootstrap server
http_server.serve_forever() http_server.serve_forever()

View File

@ -1,4 +1,27 @@
import stem, flask
import core
class ConnectionServer: class ConnectionServer:
def __init__(self): def __init__(self, peer, address, core_inst=None):
return if core_inst is None:
self.core_inst = core.Core()
else:
self.core_inst = core_inst
if not core_inst._utils.validatePubKey(peer):
raise ValueError('Peer must be valid base32 ed25519 public key')
service_app = flask.Flask(__name__)
service_port = getOpenPort()
http_server = WSGIServer(('127.0.0.1', service_port), service_app, log=None)
@service_app.route('/ping')
def get_ping():
return "pong!"
with Controller.from_port(port=core_inst.config.get('tor.controlPort')) as controller:
# Connect to the Tor process for Onionr
controller.authenticate(core_inst.config.get('tor.controlpassword'))
# Create the v3 onion service
response = controller.create_ephemeral_hidden_service({80: service_port}, await_publication = True, key_type='ED25519-V3')
logger.info('hosting on ' + response.service_id)
http_server.serve_forever()

View File

@ -46,6 +46,8 @@ def on_processblocks(api, data=None):
myBlock = api.data['block'] myBlock = api.data['block']
blockType = api.data['type'] blockType = api.data['type']
logger.info('blockType is ' + blockType) logger.info('blockType is ' + blockType)
utils = api.get_utils()
core = api.get_core()
# Process specific block types # Process specific block types
@ -54,26 +56,12 @@ def on_processblocks(api, data=None):
if api.data['validSig'] == True: if api.data['validSig'] == True:
_processForwardKey(api, myBlock) _processForwardKey(api, myBlock)
# socket blocks # socket blocks
elif blockType == 'socket': elif blockType == 'con':
if api.data['validSig'] == True and myBlock.decrypted: # we check if it is decrypted as a way of seeing if it was for us if api.data['validSig'] == True and myBlock.decrypted: # we check if it is decrypted as a way of seeing if it was for us
myBlock.bcontent = utils.bytesToStr(myBlock.bcontent)
if utils.validateID('%s.onion' % (myBlock.bcontent,)):
logger.info('Detected socket advertised to us...') logger.info('Detected socket advertised to us...')
try: core.keyStore.put('con', (myBlock.content, myBlock.signer))
address = myBlock.getMetadata('address')
except KeyError:
raise onionrexceptions.MissingAddress("Missing address for new socket")
try:
port = myBlock.getMetadata('port')
except KeyError:
raise ValueError("Missing port for new socket")
try:
reason = myBlock.getMetadata('reason')
except KeyError:
raise ValueError("Missing socket reason")
socketInfo = json.dumps({'peer': api.data['signer'], 'address': address, 'port': port, 'create': False, 'reason': reason})
api.get_core().daemonQueueAdd('addSocket', socketInfo)
else:
logger.warn("socket is not for us or is invalid")
def on_init(api, data = None): def on_init(api, data = None):