Merge pull request #834 from MuxZeroNet/patch-13
[Open for more Tests] StemPort Plugin
This commit is contained in:
commit
409841a3cf
3 changed files with 170 additions and 9 deletions
135
plugins/disabled-StemPort/StemPortPlugin.py
Normal file
135
plugins/disabled-StemPort/StemPortPlugin.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
import logging
|
||||
import traceback
|
||||
|
||||
import socket
|
||||
import stem
|
||||
from stem import Signal
|
||||
from stem.control import Controller
|
||||
from stem.socket import ControlPort
|
||||
|
||||
from Plugin import PluginManager
|
||||
from Config import config
|
||||
from Debug import Debug
|
||||
|
||||
if config.tor != "disable":
|
||||
from gevent import monkey
|
||||
monkey.patch_time()
|
||||
monkey.patch_socket(dns=False)
|
||||
monkey.patch_thread()
|
||||
print "Stem Port Plugin: modules are patched."
|
||||
else:
|
||||
print "Stem Port Plugin: Tor mode disabled. Module patching skipped."
|
||||
|
||||
|
||||
class PatchedControlPort(ControlPort):
|
||||
def _make_socket(self):
|
||||
try:
|
||||
if "socket_noproxy" in dir(socket): # Socket proxy-patched, use non-proxy one
|
||||
control_socket = socket.socket_noproxy(socket.AF_INET, socket.SOCK_STREAM)
|
||||
else:
|
||||
control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
# TODO: repeated code - consider making a separate method
|
||||
|
||||
control_socket.connect((self._control_addr, self._control_port))
|
||||
return control_socket
|
||||
except socket.error as exc:
|
||||
raise stem.SocketError(exc)
|
||||
|
||||
def from_port(address = '127.0.0.1', port = 'default'):
|
||||
import stem.connection
|
||||
|
||||
if not stem.util.connection.is_valid_ipv4_address(address):
|
||||
raise ValueError('Invalid IP address: %s' % address)
|
||||
elif port != 'default' and not stem.util.connection.is_valid_port(port):
|
||||
raise ValueError('Invalid port: %s' % port)
|
||||
|
||||
if port == 'default':
|
||||
raise ValueError('Must specify a port')
|
||||
else:
|
||||
control_port = PatchedControlPort(address, port)
|
||||
|
||||
return Controller(control_port)
|
||||
|
||||
|
||||
@PluginManager.registerTo("TorManager")
|
||||
class TorManagerPlugin(object):
|
||||
|
||||
def connectController(self):
|
||||
self.log.info("Authenticate using Stem... %s:%s" % (self.ip, self.port))
|
||||
|
||||
try:
|
||||
with self.lock:
|
||||
if config.tor_password:
|
||||
controller = from_port(port=self.port, password=config.tor_password)
|
||||
else:
|
||||
controller = from_port(port=self.port)
|
||||
controller.authenticate()
|
||||
self.controller = controller
|
||||
self.status = u"Connected (via Stem)"
|
||||
except Exception, err:
|
||||
print("\n")
|
||||
traceback.print_exc()
|
||||
print("\n")
|
||||
|
||||
self.controller = None
|
||||
self.status = u"Error (%s)" % err
|
||||
self.log.error("Tor stem connect error: %s" % Debug.formatException(err))
|
||||
|
||||
return self.controller
|
||||
|
||||
|
||||
def disconnect(self):
|
||||
self.controller.close()
|
||||
self.controller = None
|
||||
|
||||
|
||||
def resetCircuits(self):
|
||||
try:
|
||||
self.controller.signal(Signal.NEWNYM)
|
||||
except Exception, err:
|
||||
self.status = u"Stem reset circuits error (%s)" % err
|
||||
self.log.error("Stem reset circuits error: %s" % err)
|
||||
|
||||
|
||||
def makeOnionAndKey(self):
|
||||
try:
|
||||
service = self.controller.create_ephemeral_hidden_service(
|
||||
{self.fileserver_port: self.fileserver_port},
|
||||
await_publication = False
|
||||
)
|
||||
if service.private_key_type != "RSA1024":
|
||||
raise Exception("ZeroNet doesn't support crypto " + service.private_key_type)
|
||||
|
||||
self.log.debug("Stem created %s.onion (async descriptor publication)" % service.service_id)
|
||||
|
||||
return (service.service_id, service.private_key)
|
||||
|
||||
except Exception, err:
|
||||
self.status = u"AddOnion error (Stem: %s)" % err
|
||||
self.log.error("Failed to create hidden service with Stem: " + err)
|
||||
return False
|
||||
|
||||
|
||||
def delOnion(self, address):
|
||||
try:
|
||||
self.controller.remove_ephemeral_hidden_service(address)
|
||||
return True
|
||||
except Exception, err:
|
||||
self.status = u"DelOnion error (Stem: %s)" % err
|
||||
self.log.error("Stem failed to delete %s.onion: %s" % (address, err))
|
||||
self.disconnect() # Why?
|
||||
return False
|
||||
|
||||
|
||||
def request(self, cmd):
|
||||
with self.lock:
|
||||
if not self.enabled:
|
||||
return False
|
||||
else:
|
||||
self.log.error("[WARNING] StemPort self.request should not be called")
|
||||
return ""
|
||||
|
||||
def send(self, cmd, conn=None):
|
||||
self.log.error("[WARNING] StemPort self.send should not be called")
|
||||
return ""
|
10
plugins/disabled-StemPort/__init__.py
Normal file
10
plugins/disabled-StemPort/__init__.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
try:
|
||||
from stem.control import Controller
|
||||
stem_found = True
|
||||
except Exception, err:
|
||||
print "STEM NOT FOUND! %s" % err
|
||||
stem_found = False
|
||||
|
||||
if stem_found:
|
||||
print "Starting Stem plugin..."
|
||||
import StemPortPlugin
|
|
@ -20,9 +20,11 @@ except:
|
|||
from gevent.lock import RLock
|
||||
from util import helper
|
||||
from Debug import Debug
|
||||
from Plugin import PluginManager
|
||||
|
||||
|
||||
class TorManager:
|
||||
@PluginManager.acceptPlugins
|
||||
class TorManager(object):
|
||||
def __init__(self, fileserver_ip=None, fileserver_port=None):
|
||||
self.privatekeys = {} # Onion: Privatekey
|
||||
self.site_onions = {} # Site address: Onion
|
||||
|
@ -58,7 +60,7 @@ class TorManager:
|
|||
assert self.connect(), "No connection"
|
||||
self.log.debug("Tor proxy port %s check ok" % config.tor_proxy)
|
||||
except Exception, err:
|
||||
self.log.debug("Tor proxy port %s check error: %s" % (config.tor_proxy, err))
|
||||
self.log.info("Starting self-bundled Tor, due to Tor proxy port %s check error: %s" % (config.tor_proxy, err))
|
||||
self.enabled = False
|
||||
# Change to self-bundled Tor ports
|
||||
from lib.PySocks import socks
|
||||
|
@ -148,12 +150,15 @@ class TorManager:
|
|||
self.site_onions = {}
|
||||
self.privatekeys = {}
|
||||
|
||||
return self.connectController()
|
||||
|
||||
def connectController(self):
|
||||
if "socket_noproxy" in dir(socket): # Socket proxy-patched, use non-proxy one
|
||||
conn = socket.socket_noproxy(socket.AF_INET, socket.SOCK_STREAM)
|
||||
else:
|
||||
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
self.log.debug("Connecting to %s:%s" % (self.ip, self.port))
|
||||
self.log.info("Connecting to Tor Controller %s:%s" % (self.ip, self.port))
|
||||
try:
|
||||
with self.lock:
|
||||
conn.connect((self.ip, self.port))
|
||||
|
@ -203,19 +208,28 @@ class TorManager:
|
|||
self.log.error("Tor reset circuits error: %s" % res)
|
||||
|
||||
def addOnion(self):
|
||||
result = self.makeOnionAndKey()
|
||||
if result:
|
||||
onion_address, onion_privatekey = result
|
||||
self.privatekeys[onion_address] = onion_privatekey
|
||||
self.status = u"OK (%s onions running)" % len(self.privatekeys)
|
||||
SiteManager.peer_blacklist.append((onion_address + ".onion", self.fileserver_port))
|
||||
return onion_address
|
||||
else:
|
||||
return False
|
||||
|
||||
def makeOnionAndKey(self):
|
||||
res = self.request("ADD_ONION NEW:RSA1024 port=%s" % self.fileserver_port)
|
||||
match = re.search("ServiceID=([A-Za-z0-9]+).*PrivateKey=RSA1024:(.*?)[\r\n]", res, re.DOTALL)
|
||||
if match:
|
||||
onion_address, onion_privatekey = match.groups()
|
||||
self.privatekeys[onion_address] = onion_privatekey
|
||||
self.status = u"OK (%s onion running)" % len(self.privatekeys)
|
||||
SiteManager.peer_blacklist.append((onion_address + ".onion", self.fileserver_port))
|
||||
return onion_address
|
||||
return (onion_address, onion_privatekey)
|
||||
else:
|
||||
self.status = u"AddOnion error (%s)" % res
|
||||
self.log.error("Tor addOnion error: %s" % res)
|
||||
return False
|
||||
|
||||
|
||||
def delOnion(self, address):
|
||||
res = self.request("DEL_ONION %s" % address)
|
||||
if "250 OK" in res:
|
||||
|
@ -278,11 +292,13 @@ class TorManager:
|
|||
self.log.debug("Created new hidden service for %s: %s" % (site_address, onion))
|
||||
return onion
|
||||
|
||||
# Creates and returns a
|
||||
# socket that has connected to the Tor Network
|
||||
def createSocket(self, onion, port):
|
||||
if not self.enabled:
|
||||
return False
|
||||
self.log.debug("Creating new socket to %s:%s" % (onion, port))
|
||||
if config.tor == "always": # Every socket is proxied by default
|
||||
self.log.debug("Creating new Tor socket to %s:%s" % (onion, port))
|
||||
if config.tor == "always": # Every socket is proxied by default, in this mode
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect((onion, int(port)))
|
||||
else:
|
||||
|
|
Loading…
Reference in a new issue