torch-agent/torch_agent/torch_agent.py

117 lines
3.9 KiB
Python
Executable File

from stem.control import Controller
import stem.connection
import paho.mqtt.client as mqtt
import socks
import ssl
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()
config_path = args.configPath
if "TORCH_CONFIG_DIR" in environ:
config_path = environ.get("TORCH_CONFIG_DIR")
if not config_path.endswith("/"):
config_path = config_path + "/"
print("Using torch configuration path: " + config_path)
config = configparser.ConfigParser()
configuration_file_path = config_path + "torch.conf"
print("Reading configuration file at '%s'" % configuration_file_path)
config.read(configuration_file_path)
tor_proxy_host = config['tor'].get('ProxyHost', fallback="127.0.0.1")
tor_proxy_port = config['tor'].getint('ProxyPort', fallback=9050)
tor_controller_port = config['tor'].getint('ControllerPort', fallback=9051)
ssh_port = config['ssh'].getint('Port', fallback=22)
mqtt_config = config['mqtt']
mqtt_broker_host = mqtt_config.get('BrokerHost', fallback="localhost")
mqtt_broker_port = mqtt_config.getint('BrokerPort', fallback=1883)
mqtt_broker_using_tor = mqtt_broker_host.endswith(".onion")
client_id = mqtt_config.get('ClientID', fallback=socket.gethostname())
mqtt_topic = mqtt_config.get('Topic', fallback="torch/%s/onion_url" % client_id)
mqtt_require_certificate = mqtt_config.getboolean(
'RequireCertificate',
fallback=False)
mqtt_ca_file = config_path + mqtt_config.get('CaFile')
mqtt_cert_file = config_path + mqtt_config.get('CertFile')
mqtt_key_file = config_path + mqtt_config.get('KeyFile')
print("Connecting to local TOR controller on port %s" % tor_controller_port)
with Controller.from_port(port=tor_controller_port) as controller:
protocol_info = stem.connection.get_protocolinfo(controller)
stem.connection.authenticate_safecookie(controller, protocol_info.cookie_path)
print("Creating TOR Hidden Service...")
service = controller.create_ephemeral_hidden_service(ssh_port, detached=True)
onion_address = "%s.onion" % service.service_id
print("Created Tor Hidden Service for local service on port %s at %s" % (ssh_port, onion_address))
def on_publish(pub_client):
print("Published payload!")
pub_client.disconnect()
def on_disconnect(pub_client):
print("Disconnected!")
pub_client.loop_stop()
client = mqtt.Client()
client.on_publish = on_publish
client.on_disconnect = on_disconnect
client.loop_start()
protocol = "mqtt"
if mqtt_broker_using_tor:
client.proxy_set(proxy_type=socks.SOCKS5, proxy_addr=tor_proxy_host, proxy_port=tor_proxy_port)
else:
if mqtt_require_certificate:
protocol = "mqtts"
client.tls_set(
ca_certs=mqtt_ca_file,
certfile=mqtt_cert_file,
keyfile=mqtt_key_file,
cert_reqs=ssl.CERT_REQUIRED)
print("Connecting to MQTT broker: %s://%s:%s/%s" % (protocol, mqtt_broker_host, mqtt_broker_port, mqtt_topic))
if mqtt_broker_using_tor:
print("--> Using TOR proxy: %s:%s" % (tor_proxy_host, tor_proxy_port))
client.connect(mqtt_broker_host, mqtt_broker_port, 60)
print("Connected to MQTT Broker")
payload = json.dumps({
'clientId': client_id,
'timestamp': datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"),
'onionAddress': onion_address,
'sshPort': ssh_port
})
print("Publishing payload: " + payload)
client.publish(mqtt_topic, payload, qos=1)