Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
16bbe738a7 | |||
2792dc5e68 | |||
03f415499c | |||
005f9b060d | |||
8c6309eff9 | |||
fe28ab3246 | |||
156370a586 |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,4 +6,3 @@ venv
|
|||
/*.egg-info
|
||||
*.pyc
|
||||
__pycache__
|
||||
.idea
|
26
README.md
26
README.md
|
@ -13,21 +13,7 @@ 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
|
||||
|
||||
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
|
||||
## Build Debian Package
|
||||
|
||||
If you don't already have a GPG key, generate one:
|
||||
|
||||
|
@ -35,11 +21,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 `build-deb.sh` to build a Debian package and install it
|
||||
Using the e-mail address you provided during GPG key generation, run `make-pkg.sh` to build a Debian package and install it
|
||||
|
||||
```bash
|
||||
./build-deb.sh john@doe.com
|
||||
apt update && apt install build/torch-agent_0.0.6-1_all.deb
|
||||
./make-pkg.sh john@doe.com
|
||||
apt update && apt install build/torch-agent_0.0.1-1_all.deb
|
||||
```
|
||||
|
||||
This will:
|
||||
|
@ -59,3 +45,7 @@ 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
|
43
build-deb.sh
43
build-deb.sh
|
@ -1,34 +1,33 @@
|
|||
#!/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
|
||||
|
||||
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:?}"
|
||||
mkdir -p "$DEB_DIR/src/etc/torch"
|
||||
cp -r debian "$DEB_DIR/"
|
||||
cp torch.conf "$DEB_DIR/src/etc/torch/"
|
||||
rm -rf $BUILD_DIR/*
|
||||
|
||||
pip3 install -r requirements.txt
|
||||
python3 setup.py sdist
|
||||
|
||||
cd $BUILD_DIR || exit
|
||||
tar -xzmf "$PROJECT.tar.gz"
|
||||
mkdir -p $DEB_DIR/src/etc/torch
|
||||
cp -r debian $DEB_DIR/
|
||||
cp torch.conf $DEB_DIR/src/etc/torch/
|
||||
|
||||
cd "$PROJECT" || exit
|
||||
export USER
|
||||
USER=$(whoami)
|
||||
dh_make --createorig -e "$DEB_EMAIL" -s -y
|
||||
dpkg-buildpackage $DPKG_BUILD_OPTS
|
||||
cd $BUILD_DIR
|
||||
tar -xzmf $PROJECT.tar.gz
|
||||
|
||||
cd $PROJECT
|
||||
export USER=`whoami`
|
||||
dh_make --createorig -e $DEBEMAIL -s -y
|
||||
dpkg-buildpackage -k$DEBEMAIL
|
||||
|
|
6
debian/changelog
vendored
6
debian/changelog
vendored
|
@ -1,5 +1,5 @@
|
|||
torch-agent (0.0.6-1) stable; urgency=medium
|
||||
torch-agent (0.0.1-1) unstable; urgency=medium
|
||||
|
||||
* Update
|
||||
* Initial release
|
||||
|
||||
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 08 Oct 2020 19:46:22 +0200
|
||||
-- Benjamin Dweck <bjdweck@gmail.com> Tue, 06 Oct 2020 15:53:02 +0200
|
||||
|
|
2
debian/files
vendored
Normal file
2
debian/files
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
torch-agent_0.0.1-1_all.deb net optional
|
||||
torch-agent_0.0.1-1_amd64.buildinfo net optional
|
12
debian/postinst
vendored
12
debian/postinst
vendored
|
@ -42,9 +42,7 @@ configure_tor_controller() {
|
|||
fi
|
||||
|
||||
if [ $TORRC_CHANGED -eq 1 ]; then
|
||||
if [ -d "/run/systemd/system" ]; then
|
||||
systemctl reload tor
|
||||
fi
|
||||
systemctl reload tor
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -55,12 +53,10 @@ case "$1" in
|
|||
useradd -r -g $GROUP $USER
|
||||
fi
|
||||
|
||||
sudo -H pip3 install 'paho-mqtt>=1.5.1'
|
||||
chown $USER /etc/torch
|
||||
chown $USER /etc/torch/torch.conf
|
||||
|
||||
chown $USER /etc/torch
|
||||
chown $USER /etc/torch/torch.conf
|
||||
|
||||
configure_tor_controller
|
||||
configure_tor_controller
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
|
|
1
debian/pydist-overrides
vendored
1
debian/pydist-overrides
vendored
|
@ -1 +0,0 @@
|
|||
OthermoduleName python-othermodule; PEP386
|
|
@ -1,13 +0,0 @@
|
|||
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" ]
|
|
@ -1,29 +0,0 @@
|
|||
# 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
|
||||
```
|
|
@ -1,21 +0,0 @@
|
|||
-----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-----
|
|
@ -1,27 +0,0 @@
|
|||
-----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-----
|
|
@ -1,23 +0,0 @@
|
|||
-----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-----
|
|
@ -1,16 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#!/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
|
|
@ -35,10 +35,19 @@ 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
16
example/Vagrantfile
vendored
|
@ -64,19 +64,17 @@ 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
|
||||
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 apt install -y ./torch-agent_0.0.1-1_all.deb
|
||||
|
||||
sudo cp -f torch-conf/* /etc/torch/
|
||||
sudo chown -R torch /etc/torch
|
||||
|
||||
sudo systemctl enable torch-agent
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
websockets_log_level 9
|
||||
listener 8883
|
||||
connection_messages true
|
||||
log_type all
|
||||
|
||||
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
|
||||
websockets_log_level 9
|
||||
cafile /mosquitto/config/ca.crt
|
||||
keyfile /mosquitto/config/mqtt.example.com.key
|
||||
certfile /mosquitto/config/mqtt.example.com.crt
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
docker run -it --rm --user $(echo $UID) --name mosquitto -p 8883:8883 -p 1883:1883 -v $(pwd)/broker-config:/mosquitto/config eclipse-mosquitto
|
||||
docker run -it --rm --user $(echo $UID) --name mosquitto -p 8883:8883 -v $(pwd)/broker-config:/mosquitto/config eclipse-mosquitto
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
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
|
||||
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
|
||||
|
|
BIN
example/torch-agent_0.0.1-1_all.deb
Normal file
BIN
example/torch-agent_0.0.1-1_all.deb
Normal file
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
#!/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/"
|
|
@ -1,3 +0,0 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
|
@ -1,6 +1,5 @@
|
|||
pip~=20.2.4
|
||||
setuptools~=50.3.2
|
||||
stdeb3~=0.9.0.post2
|
||||
paho-mqtt~=1.5.1
|
||||
wheel>=0.35.1
|
||||
setuptools>=44.0.0
|
||||
stem>=1.8.0
|
||||
PySocks
|
||||
paho-mqtt>=1.5.1
|
||||
PySocks>=1.7.1
|
||||
|
|
25
setup.cfg
25
setup.cfg
|
@ -1,25 +0,0 @@
|
|||
[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
|
29
setup.py
29
setup.py
|
@ -1,4 +1,31 @@
|
|||
#!/usr/bin/env python3
|
||||
import setuptools
|
||||
|
||||
setuptools.setup()
|
||||
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',
|
||||
)
|
||||
|
||||
|
|
34
torch.conf
34
torch.conf
|
@ -1,47 +1,19 @@
|
|||
#################
|
||||
# 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]
|
||||
|
||||
# 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
|
||||
BrokerHost = mqtt.example.com # OR 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
|
||||
|
||||
# Optional: Topic to be used when publishing connection info (defaults to 'torch/[hostname]/onion_url')
|
||||
#Topic = example/topic
|
||||
### Options for Using TLS
|
||||
|
||||
### 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
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "0.0.6"
|
||||
__version__ = "0.0.1"
|
||||
|
|
|
@ -1,127 +1,97 @@
|
|||
import argparse
|
||||
import configparser
|
||||
import json
|
||||
import socket
|
||||
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
|
||||
|
||||
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 = 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)')
|
||||
parser.add_argument('--config-dir', nargs='?', dest='configPath', default='/etc/torch',
|
||||
help='configuration directory (default: /etc/torch)')
|
||||
|
||||
args = parser.parse_args()
|
||||
args = parser.parse_args()
|
||||
|
||||
config_path = args.configPath
|
||||
configPath = args.configPath
|
||||
|
||||
if "TORCH_CONFIG_DIR" in environ:
|
||||
config_path = environ.get("TORCH_CONFIG_DIR")
|
||||
if "TORCH_CONFIG_DIR" in environ:
|
||||
configPath = environ.get("TORCH_CONFIG_DIR")
|
||||
|
||||
if not config_path.endswith("/"):
|
||||
config_path = config_path + "/"
|
||||
if not configPath.endswith("/"):
|
||||
configPath = configPath + "/"
|
||||
|
||||
print("Using torch configuration path: " + config_path)
|
||||
print("Using torch configuration path: " + configPath)
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config = configparser.ConfigParser()
|
||||
config.read(configPath + "torch.conf")
|
||||
|
||||
configuration_file_path = config_path + "torch.conf"
|
||||
print("Reading configuration file at '%s'" % configuration_file_path)
|
||||
config.read(configuration_file_path)
|
||||
torProxyPort = config['tor'].getint('ProxyPort', fallback = 9050)
|
||||
torControllerPort = config['tor'].getint('ControllerPort', fallback = 9051)
|
||||
|
||||
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)
|
||||
sshPort = config['ssh'].getint('Port', fallback = 22)
|
||||
|
||||
ssh_port = 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))
|
||||
|
||||
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)
|
||||
mqttRequireCertificate = mqttConfig.getboolean(
|
||||
'RequireCertificate',
|
||||
fallback = False)
|
||||
|
||||
mqtt_require_certificate = mqtt_config.getboolean(
|
||||
'RequireCertificate',
|
||||
fallback=False)
|
||||
mqttCaFile = configPath + mqttConfig.get('CaFile')
|
||||
mqttCertFile = configPath + mqttConfig.get('CertFile')
|
||||
mqttKeyFile = configPath + mqttConfig.get('KeyFile')
|
||||
|
||||
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
|
||||
with Controller.from_port(port = torControllerPort) as controller:
|
||||
|
||||
protocolInfo = stem.connection.get_protocolinfo(controller)
|
||||
|
||||
mqtt_use_tls = \
|
||||
mqtt_ca_file is not None and \
|
||||
mqtt_cert_file is not None and \
|
||||
mqtt_key_file is not None
|
||||
stem.connection.authenticate_safecookie(
|
||||
controller,
|
||||
protocolInfo.cookie_path)
|
||||
|
||||
print("Connected to Tor on port %s" % (torControllerPort))
|
||||
|
||||
print("Connecting to local TOR controller on port %s" % tor_controller_port)
|
||||
service = controller.create_ephemeral_hidden_service(sshPort, detached = True)
|
||||
|
||||
with Controller.from_port(port=tor_controller_port) as controller:
|
||||
onionAddress = "%s.onion" % (service.service_id)
|
||||
|
||||
protocol_info = stem.connection.get_protocolinfo(controller)
|
||||
print("Created Tor Hidden Service for local port %s at %s" % (sshPort, onionAddress))
|
||||
|
||||
stem.connection.authenticate_safecookie(controller, protocol_info.cookie_path)
|
||||
payload = {
|
||||
'clientId': clientID,
|
||||
'timestamp': datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"),
|
||||
'onionAddress': onionAddress,
|
||||
'sshPort': sshPort
|
||||
}
|
||||
|
||||
print("Creating TOR Hidden Service...")
|
||||
client = mqtt.Client()
|
||||
protocol = "mqtt"
|
||||
|
||||
service = controller.create_ephemeral_hidden_service(ssh_port, detached=True)
|
||||
if mqttRequireCertificate:
|
||||
client.tls_set(
|
||||
ca_certs = mqttCaFile,
|
||||
certfile = mqttCertFile,
|
||||
keyfile = mqttKeyFile,
|
||||
cert_reqs=ssl.CERT_REQUIRED)
|
||||
protocol = "mqtts"
|
||||
|
||||
onion_address = "%s.onion" % service.service_id
|
||||
if mqttBrokerHost.endswith(".onion"):
|
||||
client.proxy_set(proxy_type=socks.SOCKS5, proxy_addr="localhost", proxy_port=torProxyPort)
|
||||
client.tls_insecure_set(True)
|
||||
|
||||
print("Created Tor Hidden Service for local service on port %s at %s" % (ssh_port, onion_address))
|
||||
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))
|
||||
|
||||
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)
|
||||
client.disconnect()
|
||||
print("Disconnected from MQTT Broker")
|
||||
|
|
Loading…
Reference in New Issue
Block a user