diff --git a/.gitignore b/.gitignore index d19b44c..82dc975 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ .vagrant -build \ No newline at end of file +build +build_deb +venv +/dist/ +/*.egg-info +*.pyc +__pycache__ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..863e987 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Benjamin Dweck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/build-deb.sh b/build-deb.sh new file mode 100755 index 0000000..c67d099 --- /dev/null +++ b/build-deb.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +TORCH_VERSION=$(git describe --tags --abbrev=0) +PROJECT=torch-agent-$TORCH_VERSION + +if [[ -z "${DEBEMAIL}" ]]; then + DEBEMAIL="$1" +fi + +if [[ -z "${DEBEMAIL}" ]]; then + echo "E-mail address required for packaging signing with gpg key!" + echo "Usage: ./build-deb.sh EMAIL" + exit 1 +fi + +BUILD_DIR=dist +DEB_DIR=$BUILD_DIR/$PROJECT + +rm -rf $BUILD_DIR/* + +python3 setup.py sdist + +mkdir -p $DEB_DIR/src/etc/torch +cp -r debian $DEB_DIR/ +cp torch.conf $DEB_DIR/src/etc/torch/ + +cd $BUILD_DIR +tar -xzmf $PROJECT.tar.gz + +cd $PROJECT +export USER=`whoami` +dh_make --createorig -e $DEBEMAIL -s -y +dpkg-buildpackage -k$DEBEMAIL diff --git a/debian/README.Debian b/debian/README.Debian deleted file mode 100644 index 699fb17..0000000 --- a/debian/README.Debian +++ /dev/null @@ -1,6 +0,0 @@ -torch-agent for Debian ---------------------- - - - - -- Benjamin Dweck Tue, 06 Oct 2020 15:53:02 +0200 diff --git a/debian/README.source b/debian/README.source deleted file mode 100644 index 88e9ee1..0000000 --- a/debian/README.source +++ /dev/null @@ -1,10 +0,0 @@ -torch-agent for Debian ---------------------- - - - - - - -- Benjamin Dweck Tue, 06 Oct 2020 15:53:02 +0200 - diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..9f1d48e --- /dev/null +++ b/debian/compat @@ -0,0 +1,2 @@ +11 + diff --git a/debian/control b/debian/control index 4052515..441a78c 100644 --- a/debian/control +++ b/debian/control @@ -2,15 +2,17 @@ Source: torch-agent Section: net Priority: optional Maintainer: Benjamin Dweck -Build-Depends: debhelper-compat (= 12) +Build-Depends: debhelper (>=11~), dh-python, python3-all Standards-Version: 4.4.1 -Homepage: https://rudefox.io +Homepage: https://git.rudefox.io/bj/torch-agent +X-Python3-Version: >= 3.2 #Vcs-Browser: https://salsa.debian.org/debian/torch-agent -#Vcs-Git: https://salsa.debian.org/debian/torch-agent.git +Vcs-Git: https://git.rudefox.io/bj/torch-agent.git Package: torch-agent Architecture: all -Depends: ssh, tor, python3-pip, ${misc:Depends} +Multi-Arch: foreign +Depends: ssh, tor, python3-pip, ${misc:Depends}, ${python3:Depends} Description: TORch is a solution for creating an SSH-via-Tor backdoor on a remote device as a means of fallback remote - management and initial headless device configuration. \ No newline at end of file + management and initial headless device configuration. diff --git a/debian/copyright b/debian/copyright index b1e631f..1a04b25 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,7 +1,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: torch-agent Upstream-Contact: bjdweck@gmail.com -Source: https://rudefox.io +Source: https://git.rudefox.io/bj/torch-agent Files: debian/* Copyright: 2020 Benjamin Dweck @@ -20,4 +20,4 @@ License: GPL-2+ along with this program. If not, see . On Debian systems, the complete text of the GNU General - Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". \ No newline at end of file + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". diff --git a/debian/manpage.1.ex b/debian/manpage.1.ex deleted file mode 100644 index d43cc54..0000000 --- a/debian/manpage.1.ex +++ /dev/null @@ -1,56 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" (C) Copyright 2020 Benjamin Dweck , -.\" -.\" First parameter, NAME, should be all caps -.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection -.\" other parameters are allowed: see man(7), man(1) -.TH Torch-agent SECTION "October 6 2020" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -torch-agent \- program to do something -.SH SYNOPSIS -.B torch-agent -.RI [ options ] " files" ... -.br -.B bar -.RI [ options ] " files" ... -.SH DESCRIPTION -This manual page documents briefly the -.B torch-agent -and -.B bar -commands. -.PP -.\" TeX users may be more comfortable with the \fB\fP and -.\" \fI\fP escape sequences to invode bold face and italics, -.\" respectively. -\fBtorch-agent\fP is a program that... -.SH OPTIONS -These programs follow the usual GNU command line syntax, with long -options starting with two dashes (`-'). -A summary of options is included below. -For a complete description, see the Info files. -.TP -.B \-h, \-\-help -Show summary of options. -.TP -.B \-v, \-\-version -Show version of program. -.SH SEE ALSO -.BR bar (1), -.BR baz (1). -.br -The programs are documented fully by -.IR "The Rise and Fall of a Fooish Bar" , -available via the Info system. diff --git a/debian/manpage.sgml.ex b/debian/manpage.sgml.ex deleted file mode 100644 index ceaeb33..0000000 --- a/debian/manpage.sgml.ex +++ /dev/null @@ -1,154 +0,0 @@ - manpage.1'. You may view - the manual page with: `docbook-to-man manpage.sgml | nroff -man | - less'. A typical entry in a Makefile or Makefile.am is: - -manpage.1: manpage.sgml - docbook-to-man $< > $@ - - - The docbook-to-man binary is found in the docbook-to-man package. - Please remember that if you create the nroff version in one of the - debian/rules file targets (such as build), you will need to include - docbook-to-man in your Build-Depends control field. - - --> - - - FIRSTNAME"> - SURNAME"> - - October 6 2020"> - - SECTION"> - bjdweck@gmail.com"> - - Torch-agent"> - - - Debian"> - GNU"> - GPL"> -]> - - - -
- &dhemail; -
- - &dhfirstname; - &dhsurname; - - - 2003 - &dhusername; - - &dhdate; -
- - &dhucpackage; - - &dhsection; - - - &dhpackage; - - program to do something - - - - &dhpackage; - - - - - - - - DESCRIPTION - - This manual page documents briefly the - &dhpackage; and bar - commands. - - This manual page was written for the &debian; distribution - because the original program does not have a manual page. - Instead, it has documentation in the &gnu; - Info format; see below. - - &dhpackage; is a program that... - - - - OPTIONS - - These programs follow the usual &gnu; command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - Info files. - - - - - - - - Show summary of options. - - - - - - - - Show version of program. - - - - - - SEE ALSO - - bar (1), baz (1). - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - Info system. - - - AUTHOR - - This manual page was written by &dhusername; &dhemail; for - the &debian; system (and may be used by others). Permission is - granted to copy, distribute and/or modify this document under - the terms of the &gnu; General Public License, Version 2 any - later version published by the Free Software Foundation. - - - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. - - - -
- - diff --git a/debian/manpage.xml.ex b/debian/manpage.xml.ex deleted file mode 100644 index 13a18ba..0000000 --- a/debian/manpage.xml.ex +++ /dev/null @@ -1,291 +0,0 @@ - -.
will be generated. You may view the -manual page with: nroff -man .
| less'. A typical entry -in a Makefile or Makefile.am is: - -DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl -XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" - -manpage.1: manpage.xml - $(XP) $(DB2MAN) $< - -The xsltproc binary is found in the xsltproc package. The XSL files are in -docbook-xsl. A description of the parameters you can use can be found in the -docbook-xsl-doc-* packages. Please remember that if you create the nroff -version in one of the debian/rules file targets (such as build), you will need -to include xsltproc and docbook-xsl in your Build-Depends control field. -Alternatively use the xmlto command/package. That will also automatically -pull in xsltproc and docbook-xsl. - -Notes for using docbook2x: docbook2x-man does not automatically create the -AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as - ... . - -To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections -read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be -found in the docbook-xsl-doc-html package. - -Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` - -General documentation about man-pages and man-page-formatting: -man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ - ---> - - - - - - - - - - - - - -]> - - - - &dhtitle; - &dhpackage; - - - &dhfirstname; - &dhsurname; - Wrote this manpage for the Debian system. -
- &dhemail; -
-
-
- - 2007 - &dhusername; - - - This manual page was written for the Debian system - (and may be used by others). - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU General Public License, - Version 2 or (at your option) any later version published by - the Free Software Foundation. - On Debian systems, the complete text of the GNU General Public - License can be found in - /usr/share/common-licenses/GPL. - -
- - &dhucpackage; - &dhsection; - - - &dhpackage; - program to do something - - - - &dhpackage; - - - - - - - - - this - - - - - - - - this - that - - - - - &dhpackage; - - - - - - - - - - - - - - - - - - - DESCRIPTION - This manual page documents briefly the - &dhpackage; and bar - commands. - This manual page was written for the Debian distribution - because the original program does not have a manual page. - Instead, it has documentation in the GNU - info - 1 - format; see below. - &dhpackage; is a program that... - - - OPTIONS - The program follows the usual GNU command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - - info - 1 - files. - - - - - - - Does this and that. - - - - - - - Show summary of options. - - - - - - - Show version of program. - - - - - - FILES - - - /etc/foo.conf - - The system-wide configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - ${HOME}/.foo.conf - - The per-user configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - - - ENVIRONMENT - - - FOO_CONF - - If used, the defined file is used as configuration - file (see also ). - - - - - - DIAGNOSTICS - The following diagnostics may be issued - on stderr: - - - Bad configuration file. Exiting. - - The configuration file seems to contain a broken configuration - line. Use the option, to get more info. - - - - - &dhpackage; provides some return codes, that can - be used in scripts: - - Code - Diagnostic - - 0 - Program exited successfully. - - - 1 - The configuration file seems to be broken. - - - - - - BUGS - The program is currently limited to only work - with the foobar library. - The upstreams BTS can be found - at . - - - SEE ALSO - - - bar - 1 - , - baz - 1 - , - foo.conf - 5 - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - info - 1 - system. - -
- diff --git a/debian/postinst b/debian/postinst index ed588b4..9647a8f 100644 --- a/debian/postinst +++ b/debian/postinst @@ -49,15 +49,14 @@ configure_tor_controller() { case "$1" in configure) - if ! getent passwd $USER >/dev/null ; then - useradd -r -g $GROUP $USER - fi + if ! getent passwd $USER >/dev/null ; then + useradd -r -g $GROUP $USER + fi - chown $USER /etc/torch - chown $USER /etc/torch/torch.conf - chown $USER /usr/share/torch-agent/torch-agent.py + chown $USER /etc/torch + chown $USER /etc/torch/torch.conf - configure_tor_controller + configure_tor_controller ;; abort-upgrade|abort-remove|abort-deconfigure) diff --git a/debian/postrm b/debian/postrm index b95016c..7f60f00 100644 --- a/debian/postrm +++ b/debian/postrm @@ -23,7 +23,7 @@ USER="torch" case "$1" in purge|abort-install) rm -rf /etc/torch - rm -f /usr/share/torch-agent/torch-agent.py + if [ -x "$(command -v deluser)" ]; then deluser --quiet --system $USER > /dev/null || true else diff --git a/debian/preinst b/debian/preinst index 3e46feb..6ae9a66 100755 --- a/debian/preinst +++ b/debian/preinst @@ -16,10 +16,7 @@ set -e case "$1" in install|upgrade) - sudo -H pip3 install stem paho-mqtt PySocks - mkdir -p /etc/torch - mkdir -p /usr/share/torch-agent ;; abort-upgrade) diff --git a/debian/prerm.ex b/debian/prerm.ex deleted file mode 100644 index 55eee78..0000000 --- a/debian/prerm.ex +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -# prerm script for torch-agent -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - remove|upgrade|deconfigure) - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/rules b/debian/rules index 1f72afe..03090c8 100755 --- a/debian/rules +++ b/debian/rules @@ -13,9 +13,11 @@ # package maintainers to append LDFLAGS #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed +export PYBUILD_NAME=torch-agent +export PYBUILD_SYSTEM=distutils %: - dh $@ + dh $@ --with python3 --buildsystem=pybuild override_dh_installsystemd: dh_installsystemd --no-start --no-enable diff --git a/debian/salsa-ci.yml.ex b/debian/salsa-ci.yml.ex deleted file mode 100644 index 260ebbe..0000000 --- a/debian/salsa-ci.yml.ex +++ /dev/null @@ -1,11 +0,0 @@ -# For more information on what jobs are run see: -# https://salsa.debian.org/salsa-ci-team/pipeline -# -# To enable the jobs, go to your repository (at salsa.debian.org) -# and click over Settings > CI/CD > Expand (in General pipelines). -# In "Custom CI config path" write debian/salsa-ci.yml and click -# in "Save Changes". The CI tests will run after the next commit. ---- -include: - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml diff --git a/debian/source/include-binaries b/debian/source/include-binaries deleted file mode 100755 index 65663a9..0000000 --- a/debian/source/include-binaries +++ /dev/null @@ -1,2 +0,0 @@ -src/usr/share/torch-agent/torch-agent.py -src/etc/torch/torch.conf \ No newline at end of file diff --git a/debian/src/etc/torch/torch.conf b/debian/src/etc/torch/torch.conf deleted file mode 100755 index d9d0afd..0000000 --- a/debian/src/etc/torch/torch.conf +++ /dev/null @@ -1,19 +0,0 @@ -[tor] -ProxyPort = 9050 -ControllerPort = 9051 - -[ssh] -Port = 22 - -[mqtt] -BrokerHost = mqtt.example.com # OR example1i3uyrbfoi3fi.onion -BrokerPort = 1883 -ClientID = my-client -Topic = example/topic - -### Options for Using TLS - -#RequireCertificate = true -#CaFile = ca.crt -#CertFile = client.crt -#KeyFile = client.key \ No newline at end of file diff --git a/debian/src/usr/share/torch-agent/torch-agent.py b/debian/src/usr/share/torch-agent/torch-agent.py deleted file mode 100755 index 98fd542..0000000 --- a/debian/src/usr/share/torch-agent/torch-agent.py +++ /dev/null @@ -1,98 +0,0 @@ -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 - -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") diff --git a/debian/torch-agent-docs.docs b/debian/torch-agent-docs.docs index efea0a6..e69de29 100644 --- a/debian/torch-agent-docs.docs +++ b/debian/torch-agent-docs.docs @@ -1,2 +0,0 @@ -README.Debian -README.source diff --git a/debian/torch-agent.cron.d.ex b/debian/torch-agent.cron.d.ex deleted file mode 100644 index 0910f88..0000000 --- a/debian/torch-agent.cron.d.ex +++ /dev/null @@ -1,4 +0,0 @@ -# -# Regular cron jobs for the torch-agent package -# -0 4 * * * root [ -x /usr/bin/torch-agent_maintenance ] && /usr/bin/torch-agent_maintenance diff --git a/debian/torch-agent.debhelper.log b/debian/torch-agent.debhelper.log deleted file mode 100644 index e15a197..0000000 --- a/debian/torch-agent.debhelper.log +++ /dev/null @@ -1 +0,0 @@ -dh_installsystemd diff --git a/debian/torch-agent.doc-base.EX b/debian/torch-agent.doc-base.EX deleted file mode 100644 index 25a60ee..0000000 --- a/debian/torch-agent.doc-base.EX +++ /dev/null @@ -1,20 +0,0 @@ -Document: torch-agent -Title: Debian torch-agent Manual -Author: -Abstract: This manual describes what torch-agent is - and how it can be used to - manage online manuals on Debian systems. -Section: unknown - -Format: debiandoc-sgml -Files: /usr/share/doc/torch-agent/torch-agent.sgml.gz - -Format: postscript -Files: /usr/share/doc/torch-agent/torch-agent.ps.gz - -Format: text -Files: /usr/share/doc/torch-agent/torch-agent.text.gz - -Format: HTML -Index: /usr/share/doc/torch-agent/html/index.html -Files: /usr/share/doc/torch-agent/html/*.html diff --git a/debian/torch-agent.install b/debian/torch-agent.install index 4db3ce4..44d2d6f 100644 --- a/debian/torch-agent.install +++ b/debian/torch-agent.install @@ -1,2 +1 @@ -src/usr/share/torch-agent /usr/share/ -src/etc/torch /etc/ \ No newline at end of file +src/etc/torch /etc/ diff --git a/debian/torch-agent.postrm.debhelper b/debian/torch-agent.postrm.debhelper deleted file mode 100644 index bc043aa..0000000 --- a/debian/torch-agent.postrm.debhelper +++ /dev/null @@ -1,19 +0,0 @@ -# Automatically added by dh_installsystemd/12.10ubuntu1 -if [ -d /run/systemd/system ]; then - systemctl --system daemon-reload >/dev/null || true -fi -# End automatically added section -# Automatically added by dh_installsystemd/12.10ubuntu1 -if [ "$1" = "remove" ]; then - if [ -x "/usr/bin/deb-systemd-helper" ]; then - deb-systemd-helper mask 'torch-agent.service' >/dev/null || true - fi -fi - -if [ "$1" = "purge" ]; then - if [ -x "/usr/bin/deb-systemd-helper" ]; then - deb-systemd-helper purge 'torch-agent.service' >/dev/null || true - deb-systemd-helper unmask 'torch-agent.service' >/dev/null || true - fi -fi -# End automatically added section diff --git a/torch-agent.service b/debian/torch-agent.service similarity index 65% rename from torch-agent.service rename to debian/torch-agent.service index 6816b64..9b8df28 100755 --- a/torch-agent.service +++ b/debian/torch-agent.service @@ -5,9 +5,9 @@ Requires=tor.service ssh.service [Service] Environment=PYTHONUNBUFFERED=1 -ExecStart=/usr/bin/python3 /usr/share/torch-agent/torch-agent.py +ExecStart=/usr/bin/torch-agent User=torch Group=debian-tor [Install] -WantedBy=multi-user.target ssh.service tor.service \ No newline at end of file +WantedBy=multi-user.target ssh.service tor.service diff --git a/debian/watch.ex b/debian/watch.ex deleted file mode 100644 index 888e752..0000000 --- a/debian/watch.ex +++ /dev/null @@ -1,38 +0,0 @@ -# Example watch control file for uscan -# Rename this file to "watch" and then you can run the "uscan" command -# to check for upstream updates and more. -# See uscan(1) for format - -# Compulsory line, this is a version 4 file -version=4 - -# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig -#opts="pgpsigurlmangle=s%$%.sig%" - -# HTTP site (basic) -#http://example.com/downloads.html \ -# files/torch-agent-([\d\.]+)\.tar\.gz debian uupdate - -# Uncomment to examine an FTP server -#ftp://ftp.example.com/pub/torch-agent-(.*)\.tar\.gz debian uupdate - -# SourceForge hosted projects -# http://sf.net/torch-agent/ torch-agent-(.*)\.tar\.gz debian uupdate - -# GitHub hosted projects -#opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%-$1.tar.gz%" \ -# https://github.com//torch-agent/tags \ -# (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate - -# PyPI -# https://pypi.debian.net/torch-agent/torch-agent-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) - -# Direct Git -# opts="mode=git" http://git.example.com/torch-agent.git \ -# refs/tags/v([\d\.]+) debian uupdate - - - - -# Uncomment to find new files on GooglePages -# http://example.googlepages.com/foo.html torch-agent-(.*)\.tar\.gz diff --git a/example/torch-agent_0.0.1-1_all.deb b/example/torch-agent_0.0.1-1_all.deb index ca57b2d..1534fff 100644 Binary files a/example/torch-agent_0.0.1-1_all.deb and b/example/torch-agent_0.0.1-1_all.deb differ diff --git a/make-pkg.sh b/make-pkg.sh deleted file mode 100755 index 6026f7a..0000000 --- a/make-pkg.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -if [[ -z "${DEBEMAIL}" ]]; then - DEBEMAIL="$1" -fi - -if [[ -z "${DEBEMAIL}" ]]; then - echo "E-mail address required for packaging signing with gpg key!" - echo "Usage: ./make-pkg.sh EMAIL" - exit 1 -fi - -TORCH_VERSION=$(git describe --tags) -DEBIAN_PKG=torch-agent-$TORCH_VERSION -PKG_ROOT=build/$DEBIAN_PKG - -rf -rf $PKG_ROOT - -mkdir -p $PKG_ROOT -cp -r debian $PKG_ROOT - -mkdir -p $PKG_ROOT/src/etc/torch -cp torch.conf $PKG_ROOT/src/etc/torch/ - -mkdir -p $PKG_ROOT/src/usr/share/torch-agent -cp torch-agent.py $PKG_ROOT/src/usr/share/torch-agent/ - -cp torch-agent.service $PKG_ROOT/debian/ - -cd $PKG_ROOT - -export USER=`whoami` -dh_make --createorig -e $DEBEMAIL -s -y -dpkg-buildpackage -k$DEBEMAIL \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..37a8e83 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +wheel>=0.35.1 +setuptools>=44.0.0 +stem>=1.8.0 +paho-mqtt>=1.5.1 +PySocks>=1.7.1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..33cae5a --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="torch-agent", + version="0.0.1", + author="B.J. Dweck", + author_email="bjdweck@gmail.com", + description="TORch: Iluminate the Way to your Node", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://git.rudefox.io/bj/torch-agent", + packages=setuptools.find_packages(), + install_requires=[ + 'stem', + 'paho-mqtt', + 'PySocks', + ], + entry_points = { + 'console_scripts': ['torch-agent=torch_agent.torch_agent:main'], + }, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + ], + python_requires='>=3.6', +) + diff --git a/torch-agent.py b/torch-agent.py deleted file mode 100644 index 98fd542..0000000 --- a/torch-agent.py +++ /dev/null @@ -1,98 +0,0 @@ -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 - -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") diff --git a/torch.conf b/torch.conf index d9d0afd..a6dd07d 100644 --- a/torch.conf +++ b/torch.conf @@ -16,4 +16,5 @@ Topic = example/topic #RequireCertificate = true #CaFile = ca.crt #CertFile = client.crt -#KeyFile = client.key \ No newline at end of file +#KeyFile = client.key + diff --git a/torch_agent/__init__.py b/torch_agent/__init__.py new file mode 100644 index 0000000..f102a9c --- /dev/null +++ b/torch_agent/__init__.py @@ -0,0 +1 @@ +__version__ = "0.0.1" diff --git a/torch_agent/__main__.py b/torch_agent/__main__.py new file mode 100644 index 0000000..b395440 --- /dev/null +++ b/torch_agent/__main__.py @@ -0,0 +1,5 @@ +import sys +from torch_agent import main + +if __name__ == '__main__': + sys.exit(main()) diff --git a/torch_agent/torch_agent.py b/torch_agent/torch_agent.py new file mode 100755 index 0000000..94e2bf6 --- /dev/null +++ b/torch_agent/torch_agent.py @@ -0,0 +1,97 @@ +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")