fixed config and other bugs, improved connection server

This commit is contained in:
Kevin Froman 2019-05-15 18:25:36 -05:00
parent 4e3ad27485
commit b582377c8c
11 changed files with 56 additions and 34 deletions

View File

@ -27,10 +27,12 @@ Users are identified by ed25519/curve25519 public keys, which can be used to sig
Onionr can be used for mail, as a social network, instant messenger, file sharing software, or for encrypted group discussion.
The whitepaper (subject to change prior to first alpha release) is available [here](docs/whitepaper.md).
The whitepaper (subject to change prior to alpha release) is available [here](docs/whitepaper.md).
![node web illustration](docs/onionr-web.png)
![Tor stinks slide image](docs/tor-stinks-02.png)
## Main Features
* [X] 🌐 Fully p2p/decentralized, no trackers or other single points of failure
@ -117,6 +119,4 @@ The 'open source badge' is by Maik Ellerbrock and is licensed under a Creative C
The Onionr logo was created by [Anhar Ismail](https://github.com/anharismail) under the [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).
If you modify and redistribute our code ("forking"), please use a different logo and project name to avoid confusion. Please do not use our logo in a way that makes it seem like we endorse you without our permission.
![Tor stinks slide image](docs/tor-stinks-02.png)
If you modify and redistribute our code ("forking"), please use a different logo and project name to avoid confusion. Please do not use our logo in a way that makes it seem like we endorse you without our permission.

View File

@ -81,7 +81,7 @@ class PublicAPI:
def validateRequest():
'''Validate request has the correct hostname'''
# If high security level, deny requests to public (HS should be disabled anyway for Tor, but might not be for I2P)
if config.get('general.security_level', default=0) > 0:
if config.get('general.security_level', default=1) > 0:
abort(403)
if type(self.torAdder) is None and type(self.i2pAdder) is None:
# abort if our hs addresses are not known

View File

@ -33,6 +33,7 @@ OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers
config.reload()
class OnionrCommunicatorDaemon:
def __init__(self, onionrInst, proxyPort, developmentMode=config.get('general.dev_mode', False)):
config.reload()
onionrInst.communicatorInst = self
# configure logger and stuff
onionr.Onionr.setupConfig('data/', self = self)

View File

@ -18,11 +18,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import communicator, onionrexceptions
import logger
import logger, onionrpeers
def download_blocks_from_communicator(comm_inst):
assert isinstance(comm_inst, communicator.OnionrCommunicatorDaemon)
for blockHash in list(comm_inst.blockQueue):
if len(comm_inst.onlinePeers) == 0:
break
triedQueuePeers = [] # List of peers we've tried for a block
try:
blockPeers = list(comm_inst.blockQueue[blockHash])

View File

@ -98,9 +98,6 @@ def check():
if not os.path.exists(os.path.dirname(get_config_file())):
os.makedirs(os.path.dirname(get_config_file()))
if not os.path.isfile(get_config_file()):
open(get_config_file(), 'a', encoding="utf8").close()
save()
def save():
'''

View File

@ -103,7 +103,7 @@ CookieAuthentication 1
ControlPort ''' + str(controlPort) + '''
HashedControlPassword ''' + str(password) + '''
'''
if config.get('general.security_level') == 0:
if config.get('general.security_level', 1) == 0:
torrcData += '''\nHiddenServiceDir ''' + self.dataDir + '''hs/
\n''' + hsVer + '''\n
HiddenServicePort 80 ''' + self.apiServerIP + ''':''' + str(self.hsPort)

View File

@ -71,7 +71,7 @@ class Onionr:
logger.set_file(os.environ.get('LOG_DIR', 'data') + '/onionr.log')
# Load global configuration data
data_exists = Onionr.setupConfig(self.dataDir, self = self)
data_exists = Onionr.setupConfig(self.dataDir, self)
if netcontroller.torBinary() is None:
logger.error('Tor is not installed')
@ -122,7 +122,6 @@ class Onionr:
config.set('client.client.port', randomPort, savefile=True)
if type(config.get('client.public.port')) is type(None):
randomPort = netcontroller.getOpenPort()
print(randomPort)
config.set('client.public.port', randomPort, savefile=True)
if type(config.get('client.participate')) is type(None):
config.set('client.participate', True, savefile=True)

View File

@ -50,7 +50,7 @@ def daemon(o_inst):
except FileNotFoundError:
pass
time.sleep(0.5)
onionr.Onionr.setupConfig('data/', self = o_inst)
#onionr.Onionr.setupConfig('data/', self = o_inst)
if o_inst._developmentMode:
logger.warn('DEVELOPMENT MODE ENABLED (NOT RECOMMENDED)', timestamp = False)
@ -59,7 +59,7 @@ def daemon(o_inst):
if not net.startTor():
o_inst.onionrUtils.localCommand('shutdown')
sys.exit(1)
if len(net.myID) > 0 and o_inst.onionrCore.config.get('general.security_level') == 0:
if len(net.myID) > 0 and o_inst.onionrCore.config.get('general.security_level', 1) == 0:
logger.debug('Started .onion service: %s' % (logger.colors.underline + net.myID))
else:
logger.debug('.onion service disabled')

View File

@ -23,6 +23,9 @@ import core
from . import connectionserver, bootstrapservice
class OnionrServices:
'''
Create a client or server for connecting to peer interfaces
'''
def __init__(self, onionr_core):
assert isinstance(onionr_core, core.Core)
self._core = onionr_core
@ -32,13 +35,19 @@ class OnionrServices:
return
def create_server(self, peer, address):
'''
When a client wants to connect, contact their bootstrap address and tell them our
ephemeral address for our service by creating a new ConnectionServer instance
'''
assert self._core._utils.validateID(address)
BOOTSTRAP_TRIES = 10
TRY_WAIT = 3
BOOTSTRAP_TRIES = 10 # How many times to attempt contacting the bootstrap server
TRY_WAIT = 3 # Seconds to wait before trying bootstrap again
# HTTP is fine because .onion/i2p is encrypted/authenticated
base_url = 'http://%s/' % (address,)
socks = self._core.config.get('tor.socksport')
for x in range(BOOTSTRAP_TRIES):
if self._core._utils.doGetRequest(base_url + 'ping', port=socks, ignoreAPI=True) == 'pong!':
# if bootstrap sever is online, tell them our service address
connectionserver.ConnectionServer(peer, address, core_inst=self._core)
else:
time.sleep(TRY_WAIT)

View File

@ -22,6 +22,7 @@ from gevent.pywsgi import WSGIServer, WSGIHandler
from stem.control import Controller
from flask import Flask
import core, logger, httpapi
import onionrexceptions
from netcontroller import getOpenPort
import api
from . import httpheaders
@ -66,11 +67,23 @@ class ConnectionServer:
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
# Create the v3 onion service for the peer to connect to
response = controller.create_ephemeral_hidden_service({80: service_port}, await_publication = True, key_type='NEW', key_content = 'ED25519-V3')
self.core_inst.keyStore.put('dc-' + response.service_id, self.core_inst._utils.bytesToStr(peer))
self.core_inst._utils.doPostRequest('http://' + address + '/bs/' + response.service_id, port=socks)
logger.info('hosting on %s with %s' % (response.service_id, peer))
http_server.serve_forever()
self.core_inst.keyStore.delete('dc-' + response.service_id)
http_server.stop()
try:
for x in range(3):
attempt = self.core_inst._utils.doPostRequest('http://' + address + '/bs/' + response.service_id, port=socks)
if attempt == 'success':
break
else:
raise ConnectionError
except ConnectionError:
# Re-raise
raise ConnectionError('Could not reach %s bootstrap address %s' % (peer, address))
else:
# If no connection error, create the service and save it to local global key store
self.core_inst.keyStore.put('dc-' + response.service_id, self.core_inst._utils.bytesToStr(peer))
logger.info('hosting on %s with %s' % (response.service_id, peer))
http_server.serve_forever()
http_server.stop()
self.core_inst.keyStore.delete('dc-' + response.service_id)

View File

@ -3,21 +3,22 @@ import config, logger
def setup_config(dataDir, o_inst = None):
data_exists = os.path.exists(dataDir)
if not data_exists:
os.mkdir(dataDir)
config.reload()
if not os.path.exists(config._configfile):
if os.path.exists('static-data/default_config.json'):
# this is the default config, it will be overwritten if a config file already exists. Else, it saves it
with open('static-data/default_config.json', 'r') as configReadIn:
config.set_config(json.loads(configReadIn.read()))
else:
# the default config file doesn't exist, try hardcoded config
logger.warn('Default configuration file does not exist, switching to hardcoded fallback configuration!')
config.set_config({'dev_mode': True, 'log': {'file': {'output': True, 'path': dataDir + 'output.log'}, 'console': {'output': True, 'color': True}}})
if os.path.exists('static-data/default_config.json'):
# this is the default config, it will be overwritten if a config file already exists. Else, it saves it
with open('static-data/default_config.json', 'r') as configReadIn:
config.set_config(json.loads(configReadIn.read()))
else:
# the default config file doesn't exist, try hardcoded config
logger.warn('Default configuration file does not exist, switching to hardcoded fallback configuration!')
config.set_config({'dev_mode': True, 'log': {'file': {'output': True, 'path': dataDir + 'output.log'}, 'console': {'output': True, 'color': True}}})
if not data_exists:
config.save()
config.reload() # this will read the configuration file into memory
settings = 0b000
if config.get('log.console.color', True):