From a52465a54fcbef3ed04b8b3bfa76312e6e40efe4 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 6 Apr 2020 08:51:20 -0500 Subject: [PATCH] work on lan --- src/httpapi/sse/README.md | 5 ++- src/lan/__init__.py | 1 - src/lan/client/__init__.py | 43 ++++++++++++++++++++--- src/lan/discover.py | 16 ++++----- src/lan/server/__init__.py | 13 +++++-- src/onionrblocks/__init__.py | 2 +- src/onionrblocks/blocklist.py | 41 +++++++++++++++++++++ src/onionrutils/basicrequests.py | 9 ++--- src/onionrutils/blockmetadata/fromdata.py | 3 +- src/runtests/lanservertest.py | 2 +- static-data/default_config.json | 16 ++++----- tests/runtime-result.txt | 2 +- tests/test_blocklist_class.py | 31 ++++++++++++++++ 13 files changed, 151 insertions(+), 33 deletions(-) create mode 100644 src/onionrblocks/blocklist.py create mode 100644 tests/test_blocklist_class.py diff --git a/src/httpapi/sse/README.md b/src/httpapi/sse/README.md index b01ca67a..9f3f6a41 100644 --- a/src/httpapi/sse/README.md +++ b/src/httpapi/sse/README.md @@ -1,3 +1,6 @@ # sse -This folder contains a wrapper for handling server sent event loops \ No newline at end of file +This folder contains a wrapper for handling server sent event loops + + + diff --git a/src/lan/__init__.py b/src/lan/__init__.py index 230312df..15a106f4 100644 --- a/src/lan/__init__.py +++ b/src/lan/__init__.py @@ -36,5 +36,4 @@ class LANManager: def start(self): Thread(target=learn_services, args=[self.too_many.get(Client)], daemon=True).start() Thread(target=advertise_service, daemon=True).start() - Thread(target=self.too_many.get(Client, (self.peers,)).start, daemon=True).start() diff --git a/src/lan/client/__init__.py b/src/lan/client/__init__.py index b7d5b913..77562cac 100644 --- a/src/lan/client/__init__.py +++ b/src/lan/client/__init__.py @@ -4,9 +4,15 @@ LAN transport client thread """ from typing import List +import watchdog +from requests.exceptions import ConnectionError + from onionrcrypto.cryptoutils.randomshuffle import random_shuffle from utils.bettersleep import better_sleep from onionrutils.basicrequests import do_post_request, do_get_request +from threading import Thread +from onionrblocks import BlockList +from onionrblocks.blockimporter import import_block_from_data """ 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 @@ -29,17 +35,46 @@ class Client: self.lookup_time = {} self.poll_delay = 10 + def get_lookup_time(self, peer): try: return self.lookup_time[peer] except KeyError: return 0 - def start(self): + def peer_work(self, peer): + port = 1024 + + self.peers.append(peer) + for port in range(port, 65535): + print(port) + try: + if do_get_request(f'http://{peer}:{port}/ping', proxyType='lan', ignoreAPI=True, connect_timeout=0.3) == 'onionr!': + port = port + print(f'{peer}:{port} found') + break + except (AttributeError, ConnectionError): + pass + else: + self.peers.remove(peer) + return + self.peers.append(peer) + while True: - self.peers = random_shuffle(self.peers) + block_list = self._too_many.get(BlockList).get() + last_time = self.get_lookup_time(peer) + new_blocks = set('\n'.join(do_get_request(f'http://{peer}:{port}/blist/{last_time}', proxyType='lan', ignoreAPI=True))) ^ set(block_list) + for bl in new_blocks: + import_block_from_data( + do_get_request( + f'http://{peer}:{port}/get/{bl}', proxyType='lan', ignoreAPI=True)) + better_sleep(10) + self.peers.remove(peer) - - better_sleep(self.poll_delay) + def connect_peer(self, peer): + if peer in self.peers: + return + print(f'connecting to {peer}') + Thread(target=self.peer_work, args=[peer], daemon=True).start() diff --git a/src/lan/discover.py b/src/lan/discover.py index 3f6ed819..33c87551 100644 --- a/src/lan/discover.py +++ b/src/lan/discover.py @@ -9,7 +9,7 @@ from typing import List from ipaddress import ip_address from socket import SHUT_RDWR -from .getip import lan_ips +from .getip import lan_ips, best_ip from utils.bettersleep import better_sleep """ This program is free software: you can redistribute it and/or modify @@ -52,17 +52,17 @@ def learn_services(lan_client): if 'onionr' not in service_ips: continue service_ips = service_ips.replace('onionr-', '').split('-') + print(service_ips) port = 0 for service in service_ips: try: ip_address(service) if not ip_address(service).is_private: raise ValueError if service in lan_ips: raise ValueError - if service in lan_client.peers: raise ValueError except ValueError: - service_ips.remove(service) - p = list(lan_client.peers) - lan_client.peers = list(set(service_ips + p)) + pass + else: + lan_client.connect_peer(service) def advertise_service(specific_ips=None): @@ -71,10 +71,8 @@ def advertise_service(specific_ips=None): # for all packets sent, after three hops on the network the packet will not # be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html) MULTICAST_TTL = 3 - if specific_ips is None: - ips = '-'.join(lan_ips) - else: - ips = '-'.join(specific_ips) + + ips = best_ip sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL) diff --git a/src/lan/server/__init__.py b/src/lan/server/__init__.py index fe45a386..8c8ea737 100644 --- a/src/lan/server/__init__.py +++ b/src/lan/server/__init__.py @@ -6,6 +6,7 @@ from gevent.pywsgi import WSGIServer from flask import Flask from flask import Response from flask import request +from flask import abort from onionrblocks.onionrblockapi import Block from httpapi.fdsafehandler import FDSafeHandler @@ -15,6 +16,7 @@ from coredb.blockmetadb import get_block_list from lan.getip import best_ip from onionrutils import stringvalidators from httpapi.miscpublicapi.upload import accept_upload +import logger """ 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 @@ -41,6 +43,13 @@ class LANServer: self.host = best_ip self.port = None + @app.before_request + def dns_rebinding_prevention(): + if request.host != f'{self.host}:{self.port}': + logger.warn('Potential DNS rebinding attack on LAN server:') + logger.warn(f'Hostname {request.host} was used instead of {self.host}:{self.port}') + abort(403) + @app.route('/blist/