work on torgossip
This commit is contained in:
parent
18d4a87973
commit
8a6129f4e2
@ -9,7 +9,7 @@ from utils.identifyhome import identify_home
|
|||||||
from .servicecontrol import create_new_service, restore_service
|
from .servicecontrol import create_new_service, restore_service
|
||||||
|
|
||||||
|
|
||||||
ONION_KEY_DATABASE_FILE = identify_home() + "torgossip-onion-address-keys.db"
|
ONION_KEY_DATABASE_FILE = identify_home() + "onion-address-keys.db"
|
||||||
|
|
||||||
|
|
||||||
class OnionServiceTarget(NamedTuple):
|
class OnionServiceTarget(NamedTuple):
|
||||||
@ -17,27 +17,34 @@ class OnionServiceTarget(NamedTuple):
|
|||||||
unix_socket_path: str
|
unix_socket_path: str
|
||||||
|
|
||||||
|
|
||||||
|
class NoServices(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def load_services(controller):
|
def load_services(controller):
|
||||||
db = SafeDB(ONION_KEY_DATABASE_FILE, protected=True)
|
db = SafeDB(ONION_KEY_DATABASE_FILE, protected=True)
|
||||||
keys = db.keys()
|
keys = db.db_conn.keys()
|
||||||
|
keys.remove(b'enc')
|
||||||
|
restored = []
|
||||||
|
|
||||||
if not keys:
|
if not keys:
|
||||||
db.close()
|
db.close()
|
||||||
raise ValueError("No addresses to restore")
|
raise NoServices("No addresses to restore")
|
||||||
|
|
||||||
while keys:
|
while keys:
|
||||||
# Not most pythonic but reduces mem usage as it runs
|
# Not most pythonic but reduces mem usage as it runs
|
||||||
key = keys.pop()
|
key = keys.pop()
|
||||||
if len(len) > 3:
|
|
||||||
try:
|
try:
|
||||||
service = unpackb(db.get(key))
|
service = unpackb(db.get(key))
|
||||||
restore_service(
|
service_id = restore_service(
|
||||||
controller, service['k'], service['p'],
|
controller, service['k'], int(service['p']),
|
||||||
unix_socket=service['s'])
|
unix_socket=service['s'])[0]
|
||||||
|
restored.append((service_id, service['s']))
|
||||||
except Exception as _: # noqa
|
except Exception as _: # noqa
|
||||||
db.close()
|
db.close()
|
||||||
raise
|
raise
|
||||||
db.close()
|
db.close()
|
||||||
|
return restored
|
||||||
|
|
||||||
|
|
||||||
def run_new_and_store_service(controller, target: OnionServiceTarget) -> bytes:
|
def run_new_and_store_service(controller, target: OnionServiceTarget) -> bytes:
|
||||||
|
@ -27,16 +27,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
def _add_ephemeral_service(
|
def _add_ephemeral_service(
|
||||||
controller: 'Controller', virtual_port, target, key_content=None):
|
controller: 'Controller', virtual_port, target, key_content=None):
|
||||||
|
|
||||||
key_type = "ED25519-V3"
|
|
||||||
if not key_content:
|
|
||||||
key_type = "NEW"
|
key_type = "NEW"
|
||||||
|
if not key_content:
|
||||||
|
key_content = "ED25519-V3"
|
||||||
|
else:
|
||||||
|
key_type = "ED25519-V3"
|
||||||
hs = controller.create_ephemeral_hidden_service(
|
hs = controller.create_ephemeral_hidden_service(
|
||||||
{virtual_port: target},
|
{virtual_port: target},
|
||||||
key_type=key_type,
|
key_type=key_type,
|
||||||
key_content=key_content,
|
key_content=key_content,
|
||||||
await_publication=True,
|
|
||||||
detached=True
|
detached=True
|
||||||
)
|
)
|
||||||
|
|
||||||
return (hs.service_id, hs.private_key)
|
return (hs.service_id, hs.private_key)
|
||||||
|
|
||||||
|
|
||||||
@ -65,10 +67,15 @@ def restore_service(
|
|||||||
bind_location: str = None):
|
bind_location: str = None):
|
||||||
if unix_socket and bind_location or (not unix_socket and not bind_location):
|
if unix_socket and bind_location or (not unix_socket and not bind_location):
|
||||||
raise ValueError("Must pick unix socket or ip:port, and not both")
|
raise ValueError("Must pick unix socket or ip:port, and not both")
|
||||||
key = base64.b64encode(key)
|
|
||||||
|
key = base64.b64encode(key).decode()
|
||||||
|
|
||||||
target = unix_socket
|
target = unix_socket
|
||||||
if bind_location:
|
if bind_location:
|
||||||
target = bind_location
|
target = bind_location
|
||||||
return _add_ephemeral_service(controller, virtual_port, target, key)
|
if not target.startswith("unix:"):
|
||||||
|
target = "unix:" + target
|
||||||
|
return _add_ephemeral_service(
|
||||||
|
controller, virtual_port, target, key_content=key)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ from deadsimplekv import DeadSimpleKV
|
|||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
from netcontroller.torcontrol import onionservice, torcontroller
|
||||||
import onionrstatistics
|
import onionrstatistics
|
||||||
from onionrstatistics import serializeddata
|
from onionrstatistics import serializeddata
|
||||||
import apiservers
|
import apiservers
|
||||||
@ -246,6 +247,13 @@ def daemon():
|
|||||||
_setup_online_mode(use_existing_tor, net, security_level)
|
_setup_online_mode(use_existing_tor, net, security_level)
|
||||||
|
|
||||||
_show_info_messages()
|
_show_info_messages()
|
||||||
|
|
||||||
|
with torcontroller.get_controller() as c:
|
||||||
|
try:
|
||||||
|
onionservice.load_services(c)
|
||||||
|
except onionservice.NoServices:
|
||||||
|
pass
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Onionr daemon is running under " + str(os.getpid()), terminal=True)
|
"Onionr daemon is running under " + str(os.getpid()), terminal=True)
|
||||||
events.event('init', threaded=False, data=shared_state)
|
events.event('init', threaded=False, data=shared_state)
|
||||||
|
@ -4,6 +4,7 @@ Torgossip client
|
|||||||
|
|
||||||
Create streams to random peers
|
Create streams to random peers
|
||||||
"""
|
"""
|
||||||
|
import sys
|
||||||
from base64 import b32encode
|
from base64 import b32encode
|
||||||
from os import path
|
from os import path
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
@ -17,6 +18,9 @@ from netcontroller.torcontrol import torcontroller
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .peerdb import TorGossipPeers
|
from .peerdb import TorGossipPeers
|
||||||
from stem.control import Controller
|
from stem.control import Controller
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
|
||||||
|
from commands import GossipCommands
|
||||||
"""
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -31,6 +35,7 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
controller = torcontroller.get_controller()
|
||||||
|
|
||||||
|
|
||||||
def _add_bootstrap_peers(peer_db: 'TorGossipPeers'):
|
def _add_bootstrap_peers(peer_db: 'TorGossipPeers'):
|
||||||
@ -38,13 +43,18 @@ def _add_bootstrap_peers(peer_db: 'TorGossipPeers'):
|
|||||||
with open(bootstap_peers, 'r') as bs_peers:
|
with open(bootstap_peers, 'r') as bs_peers:
|
||||||
peers = bs_peers.split(',')
|
peers = bs_peers.split(',')
|
||||||
for peer in peers:
|
for peer in peers:
|
||||||
if peer:
|
try:
|
||||||
|
peer_db.get(peer)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if peer and service_online_recently(controller, peer):
|
||||||
peer_db.add_peer(peer)
|
peer_db.add_peer(peer)
|
||||||
|
|
||||||
|
|
||||||
def _client_pool(shared_state, controller: 'Controller'):
|
def _client_pool(shared_state, socket_pool: dict):
|
||||||
peer_db: 'TorGossipPeers' = shared_state.get_by_string('TorGossipPeers')
|
peer_db: 'TorGossipPeers' = shared_state.get_by_string('TorGossipPeers')
|
||||||
socket_pool = {}
|
|
||||||
socks_port = shared_state.get_by_string('NetController').socksPort
|
socks_port = shared_state.get_by_string('NetController').socksPort
|
||||||
|
|
||||||
peers = peer_db.get_highest_score_peers(20)
|
peers = peer_db.get_highest_score_peers(20)
|
||||||
@ -61,20 +71,23 @@ def _client_pool(shared_state, controller: 'Controller'):
|
|||||||
try:
|
try:
|
||||||
socket_pool[peer] = s.connect(
|
socket_pool[peer] = s.connect(
|
||||||
(b32encode(peer).decode().lower() + ".onion", 2021))
|
(b32encode(peer).decode().lower() + ".onion", 2021))
|
||||||
|
|
||||||
except socket.GeneralProxyError:
|
except socket.GeneralProxyError:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
|
def client_loop(shared_state, socket_pool):
|
||||||
def client_pool(shared_state):
|
while True:
|
||||||
controller = torcontroller.get_controller()
|
if not socket_pool:
|
||||||
# Pass the stem Controller and then close it even if an exception raises
|
_client_pool(shared_state, socket_pool)
|
||||||
try:
|
|
||||||
_client_pool(shared_state, controller)
|
|
||||||
except Exception:
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
# Calls before the above raise no matter what
|
|
||||||
controller.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def start_client(shared_state):
|
||||||
|
# add boot strap peers to db if we need peers
|
||||||
|
_add_bootstrap_peers(shared_state.get_by_string('TorGossipPeers'))
|
||||||
|
# create and fill pool of sockets to peers (over tor socks)
|
||||||
|
socket_pool = {}
|
||||||
|
_client_pool(shared_state, socket_pool)
|
||||||
|
client_loop(shared_state, socket_pool)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
from utils.identifyhome import identify_home
|
from utils.identifyhome import identify_home
|
||||||
SERVER_SOCKET = identify_home() + "torgossip.sock"
|
SERVER_SOCKET = identify_home() + "torgossip.sock"
|
||||||
|
HOSTNAME_FILE = identify_home() + "torgossip-hostname"
|
||||||
GOSSIP_PORT = 2020
|
GOSSIP_PORT = 2020
|
@ -3,14 +3,18 @@ Onionr - Private P2P Communication
|
|||||||
|
|
||||||
Default plugin which allows users to encrypt/decrypt messages w/o using blocks
|
Default plugin which allows users to encrypt/decrypt messages w/o using blocks
|
||||||
"""
|
"""
|
||||||
from inspect import trace
|
from base64 import b32encode
|
||||||
import locale
|
import locale
|
||||||
|
|
||||||
|
from netcontroller.torcontrol import torcontroller
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
locale.setlocale(locale.LC_ALL, '')
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from netcontroller.torcontrol import onionservice
|
||||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
from constants import SERVER_SOCKET, GOSSIP_PORT, HOSTNAME_FILE
|
||||||
"""
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -44,5 +48,27 @@ def on_init(api, data=None):
|
|||||||
|
|
||||||
shared_state.get(TorGossipPeers)
|
shared_state.get(TorGossipPeers)
|
||||||
|
|
||||||
|
hs = ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(HOSTNAME_FILE, "rb") as f:
|
||||||
|
hs = f.read()
|
||||||
|
if not hs:
|
||||||
|
raise FileNotFoundError
|
||||||
|
except FileNotFoundError:
|
||||||
|
with torcontroller.get_controller() as c:
|
||||||
|
|
||||||
|
try:
|
||||||
|
hs = onionservice.run_new_and_store_service(
|
||||||
|
c, onionservice.OnionServiceTarget(
|
||||||
|
GOSSIP_PORT, SERVER_SOCKET))
|
||||||
|
except Exception:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
raise
|
||||||
|
|
||||||
|
with open(HOSTNAME_FILE, "wb") as hf:
|
||||||
|
hf.write(hs)
|
||||||
|
|
||||||
|
|
||||||
Thread(target=start_server, daemon=True, args=[shared_state]).start()
|
Thread(target=start_server, daemon=True, args=[shared_state]).start()
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TorGossipPeers: # name it this way to avoid collisions in SharedState
|
class TorGossipPeers: # name it this way to avoid collisions in SharedState
|
||||||
|
|
||||||
PACK_FORMAT = "qQ"
|
PACK_FORMAT = "qQ"
|
||||||
|
@ -14,7 +14,7 @@ sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
|||||||
from commands import GossipCommands # noqa
|
from commands import GossipCommands # noqa
|
||||||
import commandhandlers
|
import commandhandlers
|
||||||
|
|
||||||
from .constants import SERVER_SOCKET
|
from constants import SERVER_SOCKET
|
||||||
"""
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
Loading…
Reference in New Issue
Block a user