98 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| from stem.control import Controller
 | |
| import stem.connection
 | |
| import paho.mqtt.client as mqtt
 | |
| import ssl
 | |
| import socks
 | |
| import socket
 | |
| import json
 | |
| import configparser
 | |
| import argparse
 | |
| from datetime import datetime
 | |
| from os import environ
 | |
| 
 | |
| def main():
 | |
|   parser = argparse.ArgumentParser(description='Broadcast SSH hidden service hostname via MQTT')
 | |
| 
 | |
|   parser.add_argument('--config-dir', nargs='?', dest='configPath', default='/etc/torch',
 | |
|                      help='configuration directory (default: /etc/torch)')
 | |
| 
 | |
|   args = parser.parse_args()
 | |
| 
 | |
|   configPath = args.configPath
 | |
| 
 | |
|   if "TORCH_CONFIG_DIR" in environ:
 | |
|     configPath = environ.get("TORCH_CONFIG_DIR")
 | |
| 
 | |
|   if not configPath.endswith("/"):
 | |
|     configPath = configPath + "/"
 | |
| 
 | |
|   print("Using torch configuration path: " + configPath)
 | |
| 
 | |
|   config = configparser.ConfigParser()
 | |
|   config.read(configPath + "torch.conf")
 | |
| 
 | |
|   torProxyPort = config['tor'].getint('ProxyPort', fallback = 9050)
 | |
|   torControllerPort = config['tor'].getint('ControllerPort', fallback = 9051)
 | |
| 
 | |
|   sshPort = config['ssh'].getint('Port', fallback = 22)
 | |
| 
 | |
|   mqttConfig = config['mqtt']
 | |
|   mqttBrokerHost = mqttConfig.get('BrokerHost', fallback = "localhost")
 | |
|   mqttBrokerPort = mqttConfig.getint('BrokerPort', fallback = 1883)
 | |
|   clientID = mqttConfig.get('ClientID', fallback = socket.gethostname())
 | |
|   mqttTopic = mqttConfig.get('Topic', fallback = "torch/%s/onion_url" % (clientID))
 | |
| 
 | |
|   mqttRequireCertificate = mqttConfig.getboolean(
 | |
|                                          'RequireCertificate', 
 | |
|                                          fallback = False)
 | |
| 
 | |
|   mqttCaFile = configPath + mqttConfig.get('CaFile')
 | |
|   mqttCertFile = configPath + mqttConfig.get('CertFile')
 | |
|   mqttKeyFile = configPath + mqttConfig.get('KeyFile')
 | |
| 
 | |
|   with Controller.from_port(port = torControllerPort) as controller:
 | |
|     
 | |
|     protocolInfo = stem.connection.get_protocolinfo(controller)
 | |
| 
 | |
|     stem.connection.authenticate_safecookie(
 | |
|                          controller, 
 | |
|                          protocolInfo.cookie_path)
 | |
|     
 | |
|     print("Connected to Tor on port %s" % (torControllerPort))
 | |
| 
 | |
|     service = controller.create_ephemeral_hidden_service(sshPort, detached = True)
 | |
| 
 | |
|     onionAddress = "%s.onion" % (service.service_id)
 | |
| 
 | |
|     print("Created Tor Hidden Service for local port %s at %s" % (sshPort, onionAddress))
 | |
| 
 | |
|   payload = { 
 | |
|     'clientId': clientID, 
 | |
|     'timestamp': datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"), 
 | |
|     'onionAddress': onionAddress, 
 | |
|     'sshPort': sshPort 
 | |
|     }
 | |
| 
 | |
|   client = mqtt.Client()
 | |
|   protocol = "mqtt"
 | |
| 
 | |
|   if mqttRequireCertificate:
 | |
|     client.tls_set(
 | |
|             ca_certs = mqttCaFile, 
 | |
|             certfile = mqttCertFile, 
 | |
|             keyfile = mqttKeyFile, 
 | |
|             cert_reqs=ssl.CERT_REQUIRED)
 | |
|     protocol = "mqtts"
 | |
| 
 | |
|   if mqttBrokerHost.endswith(".onion"):
 | |
|     client.proxy_set(proxy_type=socks.SOCKS5, proxy_addr="localhost", proxy_port=torProxyPort)
 | |
|     client.tls_insecure_set(True)
 | |
| 
 | |
|   client.connect(mqttBrokerHost, mqttBrokerPort, 60)
 | |
|   client.publish(mqttTopic, json.dumps(payload))
 | |
|   print("Connected to MQTT Broker at %s://%s:%s/%s" % (protocol, mqttBrokerHost, mqttBrokerPort, mqttTopic))
 | |
|   print("Published payload: " + json.dumps(payload))
 | |
| 
 | |
|   client.disconnect()
 | |
|   print("Disconnected from MQTT Broker")
 |