Compare commits

...

46 Commits

Author SHA1 Message Date
B.J. Dweck 46ab5fea97 Merger with rudefox master
Merge branch 'master' of https://git.rudefox.io/bj/torch-agent
2020-10-23 12:41:03 +02:00
B.J. Dweck 7197e9aa92 Updated example and sample config to run mosquitto on 2 ports: 1883 and 8883 2020-10-23 12:37:06 +02:00
B.J. Dweck 2c6071ea79 Added script to publish package to the Rudefox Debian repo 2020-10-23 12:33:24 +02:00
B.J. Dweck 4ac90e7e77 Updated documentation in torch.conf 2020-10-23 12:32:33 +02:00
B.J. Dweck 76e0c6e7a7 Tweaked README.md 2020-10-23 12:32:15 +02:00
B.J. Dweck d3af567287 Trying to make server certificate hostname verification optional 2020-10-22 13:52:02 +02:00
B.J. Dweck 0484e3b484 Version 0.0.6 increment 2020-10-22 11:37:34 +02:00
B.J. Dweck be4ce4a288 Reduced delays; they weren't the source of the problem 2020-10-22 11:32:13 +02:00
B.J. Dweck 7d764cb043 Moved over to using mqtt.publish.single() instead of manual connection 2020-10-22 11:07:26 +02:00
B.J. Dweck cd51f18eab Trying to fix disconnection issue using the paho-mqtt loop... 2020-10-22 10:50:24 +02:00
B.J. Dweck 97f8bdd3ac Try to disconnect only after publishing 2020-10-22 10:32:23 +02:00
B.J. Dweck 64b67b08cb Added Dcoker Tor test harness 2020-10-22 10:13:31 +02:00
B.J. Dweck 626c13cde2 Raised torch MQTT publish QoS to 1 (make sure broker received at least 1) 2020-10-22 10:06:06 +02:00
B.J. Dweck 09ff9f6e86 Modified build script to make signing optional 2020-10-22 09:24:45 +02:00
B.J. Dweck 8bc211d413 Changed default local Tor proxy host from 'localhost' to '127.0.0.1' 2020-10-22 08:51:01 +02:00
B.J. Dweck 67758f6eb3 Debian package should only reload Systemd if it is running on the current system 2020-10-22 08:50:00 +02:00
B.J. Dweck 43bece3c57 Added log messaging 2020-10-21 12:31:45 +02:00
B.J. Dweck 16085fd594 MQTT Client initialized incorrectly with paho-mqtt tls_insecure_set(True) 2020-10-20 20:05:30 +02:00
B.J. Dweck 5a2ac0c3dc Attempt to fix broken PySocks Debian package dependency 2020-10-20 13:27:09 +02:00
B.J. Dweck 26d4444137 Revised README.md files to take Rudefox repo into account 2020-10-20 12:26:26 +02:00
B.J. Dweck 59ddc37cfd Incremented version number to 0.0.5 2020-10-20 12:25:35 +02:00
B.J. Dweck fe94fcc204 BUGFIX: onion urls were broken 2020-10-20 12:16:19 +02:00
B.J. Dweck a8b1029ad2 Can provision from the online Rudefox Debian repo 2020-10-20 10:49:38 +02:00
B.J. Dweck 32ee0ffe55 fixed up build-deb.sh 2020-10-20 10:25:31 +02:00
B.J. Dweck f31e9e62d7 fixed build by correcting typo in setup.cfg 2020-10-20 00:42:05 +02:00
B.J. Dweck 05c9ae8d6e Upgraded build system to setup.cfg 2020-10-20 00:27:38 +02:00
B.J. Dweck 64b9698010 Fixed PySocks (lack of) dependency and formatting 2020-10-20 00:20:33 +02:00
B.J. Dweck d9e68d50fe Upgraded setuptools version 2020-10-20 00:08:33 +02:00
B.J. Dweck 1c6da7a091 Added .gitignore for .idea 2020-10-20 00:08:17 +02:00
B.J. Dweck 609ccfbf27 Fixed bash script warnings 2020-10-20 00:07:57 +02:00
B.J. Dweck a78cddfdb1 Fixed broken comment 2020-10-20 00:07:36 +02:00
B.J. Dweck a38b6ee751 Fixed typo 2020-10-20 00:07:24 +02:00
B.J. Dweck f3677ad45e Incremented version to 0.0.4 2020-10-09 12:11:59 +02:00
B.J. Dweck ceb80569cb Debian dependency fixed (albeit in a hacky way for now...) Finally works through tor on RPi image 2020-10-09 11:59:31 +02:00
B.J. Dweck 72c6af328e Attempt 3 at solving dependency issue on pi 2020-10-09 01:42:36 +02:00
B.J. Dweck 54b1fe79a9 2nd attempt at fixing Debian packaging issue with paho-mqtt version for RPi 2020-10-09 01:16:14 +02:00
B.J. Dweck 19df7d2d35 Updated example Debian package 2020-10-09 00:17:54 +02:00
B.J. Dweck 1a4fceb89e Increment version to 0.0.3 2020-10-09 00:01:59 +02:00
B.J. Dweck fa3ad27146 BUGFIX: Require Python paho-mqtt package version >= 1.5.1 2020-10-09 00:01:38 +02:00
B.J. Dweck 21d8dbe1d1 Added updated example .deb package 2020-10-08 19:58:45 +02:00
B.J. Dweck 4a54459eab BUGFIX: Changelog changed to build package 2020-10-08 19:55:00 +02:00
B.J. Dweck 21665f976c Updated version to 0.0.2 2020-10-08 19:48:16 +02:00
B.J. Dweck a891f9bf51 Revomed redundant version number constant 2020-10-08 19:45:01 +02:00
B.J. Dweck fa24e56662 Deleted unnecessary file 2020-10-08 19:41:39 +02:00
B.J. Dweck c94962e2f1 Updated README.md 2020-10-08 15:25:08 +02:00
B.J. Dweck a9aca4da54 Moved build over to Python setuptools and Debian dh_python 2020-10-08 15:20:42 +02:00
56 changed files with 486 additions and 964 deletions

9
.gitignore vendored
View File

@ -1,2 +1,9 @@
.vagrant
build
build
build_deb
venv
/dist/
/*.egg-info
*.pyc
__pycache__
.idea

21
LICENSE.md Normal file
View File

@ -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.

View File

@ -13,7 +13,21 @@ A TORch solution consists of 3 processes:
* MQTT broker - Any MQTT broker, reachable via IPv4 or Tor, through TLS or insecure communications
* `torch-subscriber` - Listens for and handles onion hostname publications
## Build Debian Package
Easily launch a TORch Node monitor service using the [`torch-subscriber-docker`](https://git.rudefox.io/bj/torch-subscriber-docker) project
## Installation
### Install Package from Rudefox Debian Repo
1. [Add the Rudefox Repo](https://rudefox.io/repo/) as an `apt` source
2. Install the `torch-agent` package
```bash
sudo apt install torch-agent
```
### Build Debian Package from Source
If you don't already have a GPG key, generate one:
@ -21,11 +35,11 @@ If you don't already have a GPG key, generate one:
gpg --full-generate-key
```
Using the e-mail address you provided during GPG key generation, run `make-pkg.sh` to build a Debian package and install it
Using the e-mail address you provided during GPG key generation, run `build-deb.sh` to build a Debian package and install it
```bash
./make-pkg.sh john@doe.com
apt update && apt install build/torch-agent_0.0.1-1_all.deb
./build-deb.sh john@doe.com
apt update && apt install build/torch-agent_0.0.6-1_all.deb
```
This will:
@ -45,7 +59,3 @@ The configuation directory can be specified by
A fully configured example can be found [here](example)
See the sample [`torch.conf`](torch.conf) file for additional configuration options and details
## Roadmap
[ ] Utilize [dh_python3](https://www.debian.org/doc/manuals/debmake-doc/ch08.en.html#setup-py) in Debian package build

34
build-deb.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/bash
if [[ -z "${DEB_EMAIL}" ]]; then
DEB_EMAIL="$1"
DPKG_BUILD_OPTS=-k"$DEB_EMAIL"
fi
if [[ -z "${DEB_EMAIL}" ]]; then
DEB_EMAIL="none@none.com"
DPKG_BUILD_OPTS="-us -uc"
fi
TORCH_VERSION=$(git describe --tags --abbrev=0)
PROJECT=torch-agent-$TORCH_VERSION
BUILD_DIR=dist
DEB_DIR=$BUILD_DIR/$PROJECT
rm -rf "${BUILD_DIR:?}"
mkdir -p "$DEB_DIR/src/etc/torch"
cp -r debian "$DEB_DIR/"
cp torch.conf "$DEB_DIR/src/etc/torch/"
pip3 install -r requirements.txt
python3 setup.py sdist
cd $BUILD_DIR || exit
tar -xzmf "$PROJECT.tar.gz"
cd "$PROJECT" || exit
export USER
USER=$(whoami)
dh_make --createorig -e "$DEB_EMAIL" -s -y
dpkg-buildpackage $DPKG_BUILD_OPTS

View File

@ -1,6 +0,0 @@
torch-agent for Debian
---------------------
<possible notes regarding this package - if none, delete this file>
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 06 Oct 2020 15:53:02 +0200

10
debian/README.source vendored
View File

@ -1,10 +0,0 @@
torch-agent for Debian
---------------------
<this file describes information about the source package, see Debian policy
manual section 4.14. You WILL either need to modify or delete this file>
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 06 Oct 2020 15:53:02 +0200

6
debian/changelog vendored
View File

@ -1,5 +1,5 @@
torch-agent (0.0.1-1) unstable; urgency=medium
torch-agent (0.0.6-1) stable; urgency=medium
* Initial release
* Update
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 06 Oct 2020 15:53:02 +0200
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 08 Oct 2020 19:46:22 +0200

2
debian/compat vendored Normal file
View File

@ -0,0 +1,2 @@
11

12
debian/control vendored
View File

@ -2,15 +2,17 @@ Source: torch-agent
Section: net
Priority: optional
Maintainer: Benjamin Dweck <bjdweck@gmail.com>
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.
management and initial headless device configuration.

4
debian/copyright vendored
View File

@ -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 <bjdweck@gmail.com>
@ -20,4 +20,4 @@ License: GPL-2+
along with this program. If not, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".

2
debian/files vendored
View File

@ -1,2 +0,0 @@
torch-agent_0.0.1-1_all.deb net optional
torch-agent_0.0.1-1_amd64.buildinfo net optional

56
debian/manpage.1.ex vendored
View File

@ -1,56 +0,0 @@
.\" Hey, EMACS: -*- nroff -*-
.\" (C) Copyright 2020 Benjamin Dweck <bjdweck@gmail.com>,
.\"
.\" 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 <n> 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<whatever>\fP and
.\" \fI<whatever>\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.

154
debian/manpage.sgml.ex vendored
View File

@ -1,154 +0,0 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!-- Process this file with docbook-to-man to generate an nroff manual
page: `docbook-to-man manpage.sgml > 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.
-->
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
<!ENTITY dhsurname "<surname>SURNAME</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
<!ENTITY dhdate "<date>October 6 2020</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
<!ENTITY dhemail "<email>bjdweck@gmail.com</email>">
<!ENTITY dhusername "Benjamin Dweck">
<!ENTITY dhucpackage "<refentrytitle>Torch-agent</refentrytitle>">
<!ENTITY dhpackage "torch-agent">
<!ENTITY debian "<productname>Debian</productname>">
<!ENTITY gnu "<acronym>GNU</acronym>">
<!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
]>
<refentry>
<refentryinfo>
<address>
&dhemail;
</address>
<author>
&dhfirstname;
&dhsurname;
</author>
<copyright>
<year>2003</year>
<holder>&dhusername;</holder>
</copyright>
&dhdate;
</refentryinfo>
<refmeta>
&dhucpackage;
&dhsection;
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>program to do something</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
<arg><option>-e <replaceable>this</replaceable></option></arg>
<arg><option>--example <replaceable>that</replaceable></option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>This manual page documents briefly the
<command>&dhpackage;</command> and <command>bar</command>
commands.</para>
<para>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;
<application>Info</application> format; see below.</para>
<para><command>&dhpackage;</command> is a program that...</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<para>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
<application>Info</application> files.</para>
<variablelist>
<varlistentry>
<term><option>-h</option>
<option>--help</option>
</term>
<listitem>
<para>Show summary of options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>
<option>--version</option>
</term>
<listitem>
<para>Show version of program.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>bar (1), baz (1).</para>
<para>The programs are documented fully by <citetitle>The Rise and
Fall of a Fooish Bar</citetitle> available via the
<application>Info</application> system.</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>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.
</para>
<para>
On Debian systems, the complete text of the GNU General Public
License can be found in /usr/share/common-licenses/GPL.
</para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

291
debian/manpage.xml.ex vendored
View File

@ -1,291 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!--
`xsltproc -''-nonet \
-''-param man.charmap.use.subset "0" \
-''-param make.year.ranges "1" \
-''-param make.single.year.ranges "1" \
/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \
manpage.xml'
A manual page <package>.<section> will be generated. You may view the
manual page with: nroff -man <package>.<section> | 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
<refsect1> ... </refsect1>.
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/
-->
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!ENTITY dhfirstname "FIRSTNAME">
<!ENTITY dhsurname "SURNAME">
<!-- dhusername could also be set to "&dhfirstname; &dhsurname;". -->
<!ENTITY dhusername "Benjamin Dweck">
<!ENTITY dhemail "bjdweck@gmail.com">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1) and
http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
<!ENTITY dhsection "SECTION">
<!-- TITLE should be something like "User commands" or similar (see
http://www.tldp.org/HOWTO/Man-Page/q2.html). -->
<!ENTITY dhtitle "torch-agent User Manual">
<!ENTITY dhucpackage "Torch-agent">
<!ENTITY dhpackage "torch-agent">
]>
<refentry>
<refentryinfo>
<title>&dhtitle;</title>
<productname>&dhpackage;</productname>
<authorgroup>
<author>
<firstname>&dhfirstname;</firstname>
<surname>&dhsurname;</surname>
<contrib>Wrote this manpage for the Debian system.</contrib>
<address>
<email>&dhemail;</email>
</address>
</author>
</authorgroup>
<copyright>
<year>2007</year>
<holder>&dhusername;</holder>
</copyright>
<legalnotice>
<para>This manual page was written for the Debian system
(and may be used by others).</para>
<para>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.</para>
<para>On Debian systems, the complete text of the GNU General Public
License can be found in
<filename>/usr/share/common-licenses/GPL</filename>.</para>
</legalnotice>
</refentryinfo>
<refmeta>
<refentrytitle>&dhucpackage;</refentrytitle>
<manvolnum>&dhsection;</manvolnum>
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>program to do something</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
<!-- These are several examples, how syntaxes could look -->
<arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg>
<arg choice="opt"><option>--example=<parameter>that</parameter></option></arg>
<arg choice="opt">
<group choice="req">
<arg choice="plain"><option>-e</option></arg>
<arg choice="plain"><option>--example</option></arg>
</group>
<replaceable class="option">this</replaceable>
</arg>
<arg choice="opt">
<group choice="req">
<arg choice="plain"><option>-e</option></arg>
<arg choice="plain"><option>--example</option></arg>
</group>
<group choice="req">
<arg choice="plain"><replaceable>this</replaceable></arg>
<arg choice="plain"><replaceable>that</replaceable></arg>
</group>
</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>&dhpackage;</command>
<!-- Normally the help and version options make the programs stop
right after outputting the requested information. -->
<group choice="opt">
<arg choice="plain">
<group choice="req">
<arg choice="plain"><option>-h</option></arg>
<arg choice="plain"><option>--help</option></arg>
</group>
</arg>
<arg choice="plain">
<group choice="req">
<arg choice="plain"><option>-v</option></arg>
<arg choice="plain"><option>--version</option></arg>
</group>
</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1 id="description">
<title>DESCRIPTION</title>
<para>This manual page documents briefly the
<command>&dhpackage;</command> and <command>bar</command>
commands.</para>
<para>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 <citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> format; see below.</para>
<para><command>&dhpackage;</command> is a program that...</para>
</refsect1>
<refsect1 id="options">
<title>OPTIONS</title>
<para>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
<citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> files.</para>
<variablelist>
<!-- Use the variablelist.term.separator and the
variablelist.term.break.after parameters to
control the term elements. -->
<varlistentry>
<term><option>-e <replaceable>this</replaceable></option></term>
<term><option>--example=<replaceable>that</replaceable></option></term>
<listitem>
<para>Does this and that.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option></term>
<term><option>--help</option></term>
<listitem>
<para>Show summary of options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<term><option>--version</option></term>
<listitem>
<para>Show version of program.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="files">
<title>FILES</title>
<variablelist>
<varlistentry>
<term><filename>/etc/foo.conf</filename></term>
<listitem>
<para>The system-wide configuration file to control the
behaviour of <application>&dhpackage;</application>. See
<citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry> for further details.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>${HOME}/.foo.conf</filename></term>
<listitem>
<para>The per-user configuration file to control the
behaviour of <application>&dhpackage;</application>. See
<citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry> for further details.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="environment">
<title>ENVIRONMENT</title>
<variablelist>
<varlistentry>
<term><envar>FOO_CONF</envar></term>
<listitem>
<para>If used, the defined file is used as configuration
file (see also <xref linkend="files"/>).</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="diagnostics">
<title>DIAGNOSTICS</title>
<para>The following diagnostics may be issued
on <filename class="devicefile">stderr</filename>:</para>
<variablelist>
<varlistentry>
<term><errortext>Bad configuration file. Exiting.</errortext></term>
<listitem>
<para>The configuration file seems to contain a broken configuration
line. Use the <option>--verbose</option> option, to get more info.
</para>
</listitem>
</varlistentry>
</variablelist>
<para><command>&dhpackage;</command> provides some return codes, that can
be used in scripts:</para>
<segmentedlist>
<segtitle>Code</segtitle>
<segtitle>Diagnostic</segtitle>
<seglistitem>
<seg><errorcode>0</errorcode></seg>
<seg>Program exited successfully.</seg>
</seglistitem>
<seglistitem>
<seg><errorcode>1</errorcode></seg>
<seg>The configuration file seems to be broken.</seg>
</seglistitem>
</segmentedlist>
</refsect1>
<refsect1 id="bugs">
<!-- Or use this section to tell about upstream BTS. -->
<title>BUGS</title>
<para>The program is currently limited to only work
with the <package>foobar</package> library.</para>
<para>The upstreams <acronym>BTS</acronym> can be found
at <ulink url="http://bugzilla.foo.tld"/>.</para>
</refsect1>
<refsect1 id="see_also">
<title>SEE ALSO</title>
<!-- In alpabetical order. -->
<para><citerefentry>
<refentrytitle>bar</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>, <citerefentry>
<refentrytitle>baz</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>, <citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry></para>
<para>The programs are documented fully by <citetitle>The Rise and
Fall of a Fooish Bar</citetitle> available via the <citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> system.</para>
</refsect1>
</refentry>

19
debian/postinst vendored
View File

@ -42,22 +42,25 @@ configure_tor_controller() {
fi
if [ $TORRC_CHANGED -eq 1 ]; then
systemctl reload tor
if [ -d "/run/systemd/system" ]; then
systemctl reload tor
fi
fi
}
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
sudo -H pip3 install 'paho-mqtt>=1.5.1'
configure_tor_controller
chown $USER /etc/torch
chown $USER /etc/torch/torch.conf
configure_tor_controller
;;
abort-upgrade|abort-remove|abort-deconfigure)

2
debian/postrm vendored
View File

@ -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

3
debian/preinst vendored
View File

@ -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)

38
debian/prerm.ex vendored
View File

@ -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:
# * <prerm> `remove'
# * <old-prerm> `upgrade' <new-version>
# * <new-prerm> `failed-upgrade' <old-version>
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
# * <deconfigured's-prerm> `deconfigure' `in-favour'
# <package-being-installed> <version> `removing'
# <conflicting-package> <version>
# 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

1
debian/pydist-overrides vendored Normal file
View File

@ -0,0 +1 @@
OthermoduleName python-othermodule; PEP386

4
debian/rules vendored
View File

@ -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

View File

@ -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

View File

@ -1,2 +0,0 @@
src/usr/share/torch-agent/torch-agent.py
src/etc/torch/torch.conf

View File

@ -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

View File

@ -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")

View File

@ -1,2 +0,0 @@
README.Debian
README.source

View File

@ -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

View File

@ -1 +0,0 @@
dh_installsystemd

View File

@ -1,20 +0,0 @@
Document: torch-agent
Title: Debian torch-agent Manual
Author: <insert document author here>
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

View File

@ -1,2 +1 @@
src/usr/share/torch-agent /usr/share/
src/etc/torch /etc/
src/etc/torch /etc/

View File

@ -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

View File

@ -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
WantedBy=multi-user.target ssh.service tor.service

38
debian/watch.ex vendored
View File

@ -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%<project>-$1.tar.gz%" \
# https://github.com/<user>/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

13
docker-tor/Dockerfile Normal file
View File

@ -0,0 +1,13 @@
FROM ubuntu
RUN apt update && \
apt install -y sudo ssh tor curl python3-all
COPY dist/torch-agent_*_all.deb .
RUN apt install -y ./torch-agent_*_all.deb
COPY docker-tor/torch-agent.wrapper.sh /usr/bin/torch-agent.wrapper.sh
VOLUME [ "/etc/torch" ]
ENTRYPOINT [ "torch-agent.wrapper.sh" ]

29
docker-tor/README.md Normal file
View File

@ -0,0 +1,29 @@
# Tor Test Harness for TORch Agent
This is a Docker container for running the current development version of TORch Agent in an environment with a local Tor Proxy (without having to install and configure Tor on the development machine itself)
## Preparation
1. Build a Debian package from the current development version of TORch Agent
```bash
python -m venv venv && source venv/bin/activate
pip3 install -r requirements.txt
./build-deb.sh
```
2. Build the Docker image
```bash
docker build -f docker-tor/Dockerfile -t torch-agent .
```
3. Configure `torch-agent` by editing [`agent-conf/torch.conf`](./agent-conf/torch.conf)
* Be sure to update the onion hostname of the broker with the one you wish to test with
4. Launch the Docker container
```bash
docker run -it --rm -v "$(pwd)/docker-tor/agent-conf:/etc/torch" torch-agent
```

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDhDCCAmwCFFfe134gzLKm3ieNbeoxCvOhwsGxMA0GCSqGSIb3DQEBCwUAMIGE
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxETAPBgNVBAcMCE5ldyBZb3JrMRUw
EwYDVQQKDAxFeGFtcGxlIEluYy4xHDAaBgNVBAMME2NhLm1xdHQuZXhhbXBsZS5j
b20xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMB4XDTIwMTAwNjEx
MDQxMVoXDTMwMTAwNDExMDQxMVoweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5Z
MREwDwYDVQQHDAhOZXcgWW9yazEVMBMGA1UECgwMRXhhbXBsZSBJbmMuMRAwDgYD
VQQDDAd2YWdyYW50MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALBR3WYBUoSM9taDBWn8MSU3
WW7z9EmutaWRKlNCf8rAVXrEGf3shtBb6MWdRjAKHcBDZaTtmW6o0XoXkKdGeWcm
6X0o4TwaROPE7HR8OtKsmPTxQ09gKfkwB+sb8+fIPrKq6VLWiSJqvc6RbZvoKXIa
WU/BV4q3HG9MvFB2AMNx9pmzLeeP/m323pAEU28oR/kGvuDJHSLO3cNd1U5ZKFFt
J1hHYugKM3uHlyQ44ozu6l2AexGgIYjA5/y1D/RuWaybdpppLS3RerhKDrvTkwWD
UALgTdxHnIT90NFCtGsZTzwmbqs/ibq1NtkHGiS0tGhJjftIiPJZfuNArVsoYF0C
AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAeOEgOA8dJZGo/bT+2vnKm7VnJYrNgAax
B/X2kG3vLiayFgPYarQq8AjlqQCr8Dm1EqbUtnAhzSbQTX+v3oQBd7sRdlwfTYKa
bFEjhMeXhBgp/bWobq9FcwAL02wsAZh/gcbHAVrIwWmb42sbHTmrWY2jgJbX65jg
ameIn9p1j2CSJnC4Ju3B+btaCmksHI6uhuJVef/+pL53hs1z5MfehNvJaBkUzsya
nYAiCvrEQIzKlxROdBApZeQs0WFv0ktu6itzA3YsCMct1p3TNGwDUZ+cQqkTPhkB
KNT0VcmDNdavD59WsEfrgZe5/DXY+Q1yHzGmaq70y0U6SgTfOsslmQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsFHdZgFShIz21oMFafwxJTdZbvP0Sa61pZEqU0J/ysBVesQZ
/eyG0FvoxZ1GMAodwENlpO2ZbqjReheQp0Z5ZybpfSjhPBpE48TsdHw60qyY9PFD
T2Ap+TAH6xvz58g+sqrpUtaJImq9zpFtm+gpchpZT8FXirccb0y8UHYAw3H2mbMt
54/+bfbekARTbyhH+Qa+4MkdIs7dw13VTlkoUW0nWEdi6Aoze4eXJDjijO7qXYB7
EaAhiMDn/LUP9G5ZrJt2mmktLdF6uEoOu9OTBYNQAuBN3EechP3Q0UK0axlPPCZu
qz+JurU22QcaJLS0aEmN+0iI8ll+40CtWyhgXQIDAQABAoIBAQCYYtiHbYMk3jQD
p49JT1YmRRT9aMhr2hxR8Ql0lheeYuY9yThxljfZ4mVmTYw4vrWB0n4JsfQWiL8q
1y0E9Uq9lQrdSjSH3mhFto9qCWhJZjR4FgBHnOQJ4rIlR65gV1eg0UgAeTxiS4Cq
BFSIF3mijRU9ces4DxP7OYXTwHjecLQXWzsENhlcowTCYOfxLM/8YvVRCv2cxPJh
/TL3qn1LD5/15lUb58+SqNAOREGACB+YG6rFShvUrxkq3ShtZdPUOzM5z+9xS8yO
Uh2aZDmxtMB6GnYbQNhfM274i71aVhf0++7s8VsiVo3C61+qKIYcX0LK8t2PnQ1H
cFn20hKhAoGBANfyLB5T+nZUGBysZSe76SoZUFWM0OsLixLq0+CqHvnTmIVMLQpv
k8RV2/g7rKCcaKghSENI2gwWy+EDfVGi/nGc+uJ+n4FX92F98MmmzFvuQXOp1AuY
Qvqr2XquFu5B6Jz5aOniOMHHSRl9JmZOLc+rs7COH7s/o5OPBT+1OpHJAoGBANEG
HBnAuxZ0XJtB7TvA9wW3GCRidCisRH8rG0cN4dE3UuCC+DQq1AV03NwM6pycwz15
ljpkb+WtbE6iKG3sfj3vWhwkakcEnJKXGCVbKmMXI0L2sMnQB4bJ4TtXGDRJlLKg
XuwBsEmN8pM8IqRmnSpTrVbpCo4vZ/29c8l9+YP1AoGAcgIBGOHtUZuEP18k6J1k
tD05FHGLuwwVGJ+xzOMEB5GW7IkTHndZ5EYQJDYdJY5uEpW/uQY1WDyQ1vMornkH
LKRcMEf5nif7CxWaklvleIOJOq9mq9hvRDiGUSaoJJHXZUioAxLUNDoqdbKFG24a
8ZENBSGDzzACBF11v/TGP0ECgYEAp+WCeOUo4jaBlGx2RIMRaNPTXpZ+u5T0SDm1
5XMvKkCIH7LT8ANe3ysppM/zO+1nnl+l3i2C/Dg7QUZbt0A5f0JdXTGa9IStx8n6
KTd7arDRMB67jr+86/YJJwMkfAuGl5zd4jDRC6Qrbzzkjq2mHLOuDpuOUPufSl/9
O6Im5GkCgYA4zFE3ztSV6nq5EH3A7VmAsLiyRXBJfOlLXIBApv46/t4ivS4C3Esu
8LR+Vvx2XLWkpkrm9kR1wIutNx6x1pRkSGDKyRXn5+cU4A2Lw9y2BbwDhj+WiHkM
zCuL+8l2px2f3K1YPE3oGWHZZJScDwa03yjVzrSPDr766XBtH7W4vg==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID6zCCAtOgAwIBAgIUQJye5MbZVMpOpu87TmmlN/KOBj0wDQYJKoZIhvcNAQEL
BQAwgYQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3IFlv
cmsxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEcMBoGA1UEAwwTY2EubXF0dC5leGFt
cGxlLmNvbTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5jb20wHhcNMjAx
MDA2MTA1OTE4WhcNMzAxMDA0MTA1OTE4WjCBhDELMAkGA1UEBhMCVVMxCzAJBgNV
BAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEVMBMGA1UECgwMRXhhbXBsZSBJbmMu
MRwwGgYDVQQDDBNjYS5tcXR0LmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFh
ZG1pbkBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ALVndltaj3SX1zuJB0F5woIMUZCHopkgiO027/qE10IgM6SN4lFhR7wR0B/9PXrf
zn1xTC63w9xd3GbnlJvcWhWbh/m1t2Qx2mIvOmoELY8wlY6/V6NzjSgju7mZi0u6
aitU+LXINNuGS+JhVpc54QQ8M9o0jKlnNGnEmPjv6uhbNXx3f8lw3eqSr1ZqmpGd
UQVYKsNYBVzSqsnh/sn/KnGYn/nmpsKRWeLhoslJ3zDjaM/Y4NYol11nWFIPYCk5
7rzzxES/WdWLLnZ2W59YCT54YOGFqXE7oYgReD+Og2YwnGVQQpDcvb2HyIZL/2pa
oC6avMo/eC8HbSxwUKCnj1cCAwEAAaNTMFEwHQYDVR0OBBYEFEC8a9l0rpIdUqCS
i4NJwXlqUoLeMB8GA1UdIwQYMBaAFEC8a9l0rpIdUqCSi4NJwXlqUoLeMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGzxJWZdVozskr5yie2uetpL
aAReCaHEdWudRN3wVW1Dpm2sE23x4VFiJ+Uow9k21GgtGUsAIFqRgb3/QO+ipODC
GRwZmVopkuOaHfCz+tO8xqjvGHCidhhhNFdR9uVkWHoPKsQsvap0SSk12KMtFBRo
3rmeQwPP4qEPFEwc2U0hCUMsIUvMSt3KrA/j+aMRzOXU7QIMFbcYEF1IaGJz1RMh
h1VCXaUlL2liVTWU4XgudB8rMOuETec7un9hzoBVOWHxXdRrGPaoN4+zWiLRCDXO
6wapOhkmTOXuZY/NcMMwTmdJKTEQBD6XIQamv91Ne2bT89LHpcp1LjbaCz+UAxg=
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
[tor]
ControllerPort = 9051
[ssh]
Port = 22
[mqtt]
BrokerHost = wmzin3o2dvd4h2iu4mrf4zqbvgscgi27kd5afzvhgchghjdpqk7cmaqd.onion
BrokerPort = 1883
ClientID = myagent
Topic = torch/myagent/wake
RequireCertificate = false
CaFile = ca.crt
CertFile = agent.crt
KeyFile = agent.key

View File

@ -0,0 +1,10 @@
#!/bin/bash
tor &
while ! curl -s --socks5 127.0.0.1:9050 'https://check.torproject.org/' | grep -qm1 Congratulations
do
sleep 0.5
done
torch-agent $1 $2 $3 $4

View File

@ -35,19 +35,10 @@ In a separate terminal window, run the subscriber:
#### Run TORch Agent in Vagrant
[Build](..) the latest source into a Debian package and copy it to `example/`
```bash
cd ..
./make-pkg.sh john@doe.com
cp -f build/torch-agent_0.0.1-1_all.deb example/
cd example
```
Run the Vagrant box in a third terminal window:
```bash
vagrant up
```
You should see that the broker received a connection from the Vagrant box at boot up and the subscriber received the onion hostname. You can use a local `tor` proxy to connect to the vagrant box using SSH and the onion hostname.
You should see that the broker received a connection from the Vagrant box at boot up and the subscriber received the onion hostname. You can use a local `tor` proxy to connect to the vagrant box using SSH and the onion hostname.

16
example/Vagrantfile vendored
View File

@ -64,17 +64,19 @@ Vagrant.configure("2") do |config|
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "file", source: "torch-agent_0.0.1-1_all.deb", destination: "~/"
config.vm.provision "file", source: "agent-config", destination: "~/torch-conf"
config.vm.provision "shell", inline: <<-SHELL
sudo -- sh -c "echo '10.0.2.2 mqtt.example.com' >> /etc/hosts"
sudo -- sh -c "echo '10.0.2.2 mqtt.example.com' >> /etc/hosts"
sudo apt update
sudo apt install -y ./torch-agent_0.0.1-1_all.deb
sudo cp -f torch-conf/* /etc/torch/
wget -qO - https://rudefox.io/repo/gpg | sudo apt-key add
sudo add-apt-repository "deb https://repo.rudefox.io/repository/apt-release focal main"
sudo apt update
sudo apt install -y torch-agent
sudo cp -f torch-conf/* /etc/torch/
sudo chown -R torch /etc/torch
sudo systemctl enable torch-agent

View File

@ -1,7 +1,15 @@
listener 8883
websockets_log_level 9
connection_messages true
log_type all
websockets_log_level 9
listener 1883
cafile /mosquitto/config/ca.crt
#keyfile /mosquitto/config/mqtt.example.com.key
#certfile /mosquitto/config/mqtt.example.com.crt
require_certificate true
use_identity_as_username true
listener 8883
cafile /mosquitto/config/ca.crt
keyfile /mosquitto/config/mqtt.example.com.key
certfile /mosquitto/config/mqtt.example.com.crt

View File

@ -1,3 +1,3 @@
#!/usr/bin/bash
docker run -it --rm --user $(echo $UID) --name mosquitto -p 8883:8883 -v $(pwd)/broker-config:/mosquitto/config eclipse-mosquitto
docker run -it --rm --user $(echo $UID) --name mosquitto -p 8883:8883 -p 1883:1883 -v $(pwd)/broker-config:/mosquitto/config eclipse-mosquitto

View File

@ -1,3 +1,3 @@
#!/usr/bin/bash
mosquitto_sub -L mqtts://mqtt.example.com/it/torch/\+/ssh_onion --cafile subscriber-config/ca.crt --key subscriber-config/subscriber.key --cert subscriber-config/subscriber.crt
mosquitto_sub -L mqtts://mqtt.example.com/torch/\+/onion_url --cafile subscriber-config/ca.crt --key subscriber-config/subscriber.key --cert subscriber-config/subscriber.crt

Binary file not shown.

View File

@ -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

7
publish-deb.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
USERNAME=$1
PASSWORD=$2
VERSION=$3
curl -u "$USERNAME:$PASSWORD" -H "Content-Type: multipart/form-data" --data-binary "@dist/torch-agent_${VERSION}-1_all.deb" "https://repo.rudefox.io/repository/apt-release/"

3
pyproject.toml Normal file
View File

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
pip~=20.2.4
setuptools~=50.3.2
stdeb3~=0.9.0.post2
paho-mqtt~=1.5.1
stem>=1.8.0
PySocks

25
setup.cfg Normal file
View File

@ -0,0 +1,25 @@
[metadata]
name = torch-agent
version = attr: torch_agent.__version__
author = Benjamin Dweck
author_email = bjdweck@gmail.com
description = TORch: Illuminate the Way to your Node
url = https://git.rudefox.io/bj/torch-agent
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
[options]
packages = find:
install_requires =
paho-mqtt~=1.5.1
setuptools~=50.3.1
pip~=20.2.3
stem
PySocks
[options.entry_points]
console_scripts = torch-agent=torch_agent.torch_agent:main
[options.packages.find]
exclude=test

4
setup.py Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env python3
import setuptools
setuptools.setup()

View File

@ -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")

View File

@ -1,19 +1,48 @@
#################
# The `tor` section heading is required
[tor]
# Optional: The Tor onion proxy host and port (default: 127.0.0.1:9050)
#ProxyHost 127.0.0.1
ProxyPort = 9050
# Optional: The Tor controller port (default: 9051) for creating new hidden services
ControllerPort = 9051
#################
# The `ssh` section heading is required
[ssh]
# Optional: Local SSH sevice port (default: 22)
Port = 22
#################
# The `mqtt` section heading is required
[mqtt]
BrokerHost = mqtt.example.com # OR example1i3uyrbfoi3fi.onion
# Optional: The MQTT broker host and port (default: localhost:1883)
# Can be either IPv4 or Tor onion hostname
BrokerHost = mqtt.example.com
#BrokerHost = example1i3uyrbfoi3fi.onion
BrokerPort = 1883
# Optional: ID that will be used as an MQTT client ID when connecting to the broker (defaults to the current host's hostname)
ClientID = my-client
Topic = example/topic
### Options for Using TLS
# Optional: Topic to be used when publishing connection info (defaults to 'torch/[hostname]/onion_url')
#Topic = example/topic
### Optional: TLS Options
#
# Note: when CaFile, CertFile and KeyFile are ALL defined, then TLS (MQTTS) is used to connect to the broker. Otherwise MQTT is used.
#
# Optional: Whether or not TORch Agent will verify the hostname of the broker and require it to match the name on the certificate the broker provides. This will be automatically DISABLED for connections to Tor onion hosts
#RequireCertificate = true
#CaFile = ca.crt
#CertFile = client.crt
#KeyFile = client.key
#KeyFile = client.key

1
torch_agent/__init__.py Normal file
View File

@ -0,0 +1 @@
__version__ = "0.0.6"

5
torch_agent/__main__.py Normal file
View File

@ -0,0 +1,5 @@
import sys
from torch_agent import main
if __name__ == '__main__':
sys.exit(main())

127
torch_agent/torch_agent.py Executable file
View File

@ -0,0 +1,127 @@
import argparse
import configparser
import json
import socket
import ssl
from datetime import datetime
from os import environ
import paho.mqtt.publish as publish
import socks
import stem.connection
from stem.control import Controller
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")
mqtt_client_id = mqtt_config.get('ClientID', fallback=socket.gethostname())
mqtt_topic = mqtt_config.get('Topic', fallback="torch/%s/onion_url" % mqtt_client_id)
mqtt_require_certificate = mqtt_config.getboolean(
'RequireCertificate',
fallback=False)
mqtt_ca_file = mqtt_config.get('CaFile', fallback=None)
mqtt_ca_file = config_path + mqtt_ca_file
mqtt_cert_file = mqtt_config.get('CertFile', fallback=None)
mqtt_cert_file = config_path + mqtt_cert_file
mqtt_key_file = mqtt_config.get('KeyFile', fallback=None)
mqtt_key_file = config_path + mqtt_key_file
mqtt_use_tls = \
mqtt_ca_file is not None and \
mqtt_cert_file is not None and \
mqtt_key_file is not None
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))
protocol = "mqtt"
tls_args = None
proxy_args = None
cert_required = ssl.CERT_OPTIONAL
if mqtt_require_certificate:
cert_required = ssl.CERT_REQUIRED
if mqtt_broker_using_tor:
cert_required = ssl.CERT_OPTIONAL
proxy_args = {
'proxy_type': socks.SOCKS5,
'proxy_addr': tor_proxy_host,
'proxy_port': tor_proxy_port
}
if mqtt_use_tls:
protocol = "mqtts"
tls_args = {
'ca_certs': mqtt_ca_file,
'certfile': mqtt_cert_file,
'keyfile': mqtt_key_file,
'cert_reqs': cert_required
}
print("Publishing 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))
payload = json.dumps({
'clientId': mqtt_client_id,
'timestamp': datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"),
'onionAddress': onion_address,
'sshPort': ssh_port
})
publish.single(mqtt_topic,
payload,
qos=1,
hostname=mqtt_broker_host,
port=mqtt_broker_port,
client_id=mqtt_client_id,
tls=tls_args,
proxy_args=proxy_args)