Compare commits

..

No commits in common. "61051d5711c4c3d02b150b49c05f09a5cf4ff910" and "8712a1c40123cb8e01642ce6749d3fc96ce6ba5b" have entirely different histories.

11 changed files with 193 additions and 74 deletions

View File

@ -1 +1,7 @@
This directory contains useful scripts and utilities that don't make sense to include as official Onionr features.
passphrase-generator.py: very simple utility to generate and print a strong passphrase to stdout. 256 bits of entropy by default.
enable-dev-config.py/disable-dev-config.py: enable/disable dev default config setup
block-spammer.py: attack tool for spamming blocks
announce-attack.py: flood a node with false nodes
run-unit-test-by-name: runs a unit test (no browser, runtime or intgegration test) by name

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Craft and send requests to the local client API"""
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import atexit
import readline
histfile = os.path.join(os.path.expanduser("~"), ".onionr_history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
from onionrutils.localcommand import local_command
from onionrutils.localcommand import get_hostname
try:
print('API file found, probably running on ' + get_hostname())
except TypeError:
print('Onionr not running')
sys.exit(1)
print('1. get request (default)')
print('2. post request')
choice = input(">").lower().strip()
post = False
post_data = {}
json = False
endpoint = input("URL Endpoint: ")
data = input("Data url param: ")
if choice in ("2", "post", "post request"):
post = True
print("Enter post data")
post_data = input()
if post_data:
print("Is this JSON?")
json = input("y/n").lower().strip()
if json == "y":
json = True
ret = local_command(endpoint, data=data, post=post, post_data=post_data, is_json=json)
print("Response: \n", ret)

41
scripts/generate-onions.py Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import sys
import os
import stem
from stem import process
from stem.control import Controller
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
try:
sys.argv[1]
except IndexError:
sys.exit(1)
tor_process = process.launch_tor_with_config(
completion_percent=0,
config = {
'ControlPort': '2778',
'DisableNetwork': '1',
'Log': [
'NOTICE stdout',
'ERR file /tmp/tor_error_log',
],
},
)
with Controller.from_port('127.0.0.1', 2778) as controller:
controller.authenticate()
for i in range(1024, 1024 + int(sys.argv[1])):
hs = controller.create_ephemeral_hidden_service(
{80: i},
key_type='NEW',
key_content='ED25519-V3',
await_publication=False,
detached=True)
print(hs.service_id + ".onion")
controller.remove_ephemeral_hidden_service(hs.service_id)
tor_process.kill()

16
scripts/show-blocks.py Normal file
View File

@ -0,0 +1,16 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from coredb.blockmetadb import get_block_list
from onionrblocks.onionrblockapi import Block
for bl in get_block_list():
bl_obj = Block(bl, decrypt=False)
b_type = bl_obj.getType()
if not b_type:
b_type = "encrypted"
print(bl + " - " + str(bl_obj.date) + " - " + b_type)

40
scripts/sybil-attack.py Normal file
View File

@ -0,0 +1,40 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from onionrutils import stringvalidators
from onionrutils import basicrequests
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)

12
scripts/testblock.py Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env python3
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import onionrblocks
expire = 600
print(onionrblocks.insert(data=os.urandom(32), expire=expire))

View File

@ -1,4 +1,3 @@
import traceback
from typing import TYPE_CHECKING
from typing import List
import secrets
@ -62,18 +61,10 @@ async def accept_stem_blocks(
if not raw_block:
break
try:
bl = Block(block_id, raw_block, auto_verify=True)
except Exception as e:
logging.warn(
f"Error in received stem block {block_id} {str(e)}")
logging.debug(traceback.format_exc())
break
logging.debug("Got a stem block, put into queue")
block_queue_to_use.put(bl)
block_queue_to_use.put(
Block(block_id, raw_block, auto_verify=True)
)
# Regardless of stem phase, we add to queue
# Client will decide if they are to be stemmed

View File

@ -2,16 +2,20 @@
"""
import threading
import os
import time
import traceback
import collections
from typing import Union
import ujson
import jsonrpc
from logger import log as logging
rpc_results = collections.deque(maxlen=10000)
def get_results(id) -> Union[str, None]:
final = None
for result in rpc_results:
@ -25,12 +29,10 @@ def get_results(id) -> Union[str, None]:
def _exec_rpc(rpc_json_str):
json_resp = jsonrpc.JSONRPCResponseManager.handle(
rpc_json_str, jsonrpc.dispatcher)
json_resp = jsonrpc.JSONRPCResponseManager.handle(rpc_json_str, jsonrpc.dispatcher)
data = json_resp.data
rpc_results.append(data)
def threaded_rpc(rpc_json_str):
threading.Thread(
target=_exec_rpc,

View File

@ -57,7 +57,6 @@ import longrpc
plugin_apis['rpc.add_module_to_api'] = add_module_to_api
def _detect_cors_and_add_headers():
cherrypy.response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
@ -66,7 +65,6 @@ def _detect_cors_and_add_headers():
return True
return False
class OnionrRPC(object):
@cherrypy.expose
def threaded_rpc(self):

View File

@ -1,39 +1,26 @@
from secrets import randbits
import base64
from typing import Union
from base64 import b85decode
from onionrblocks import Block
import onionrblocks
from jsonrpc import dispatcher
from gossip.blockqueues import gossip_block_queues
import blockdb
from blockdb import get_blocks_after_timestamp
from utils import multiproc
@dispatcher.add_method
def get_block(block_id: str) -> dict:
bl = blockdb.get_block(block_id)
@dispatcher.add_method
def get_blocks(timestamp):
blocks = []
for block in blockdb.get_blocks_after_timestamp(timestamp):
blocks.append({
'id': block.id,
'raw': base64.b64encode(block.raw).decode('utf-8')
})
return blocks
return [block.raw for block in get_blocks_after_timestamp(timestamp)]
@dispatcher.add_method
def create_block(
block_data: 'base64', block_type: str, ttl: int, metadata: dict):
# Wrapper for onionrblocks.create_block
# (take base64 to be compatible with RPC)
bl: Block = multiproc.subprocess_compute(
# Wrapper for onionrblocks.create_block (take base64 to be compatible with RPC)
bl = multiproc.subprocess_compute(
onionrblocks.create_anonvdf_block,
3600,
base64.b64decode(block_data),
@ -41,35 +28,14 @@ def create_block(
ttl,
**metadata
)
try:
block_id = bl.id.decode('utf-8')
except AttributeError:
block_id = bl.id
bl_json = {
'id': block_id,
'raw': base64.b64encode(bl.raw).decode('utf-8')
}
return bl_json
return base64.b85encode(bl.raw).decode('utf-8')
@dispatcher.add_method
def create_and_insert_block(
block_data: 'base64',
block_type: str, ttl: int, metadata: dict) -> str:
bl = create_block(block_data, block_type, ttl, metadata)['id']
insert_block(bl)
return bl['id']
# As per dandelion++ spec the edge should be the same.
# We keep it the same for each daemon life time.
queue_to_use = randbits(1)
@dispatcher.add_method
def insert_block(block: Union[dict, Block]):
if isinstance(block, dict):
block = Block(
block['id'], base64.b64decode(block['raw']), auto_verify=False)
def insert_block(block):
block = Block(
block['id'], b85decode(block['raw']), auto_verify=False)
gossip_block_queues[queue_to_use].put_nowait(block)
return "ok"

View File

@ -66,11 +66,7 @@ def on_init(api, data=None):
load_identities_from_blocks())
)
# Expose WOT to RPC if the RPC plugin is loaded
try:
plugin_apis['rpc.add_module_to_api'](wot)
except KeyError:
pass
plugin_apis['rpc.add_module_to_api'](wot)
# load active identity, from there load our trust graph
active_identity = config.get('wot.active_identity_name', '')