Compare commits
22
Commits
a8b1029ad2
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46ab5fea97 | ||
|
|
7197e9aa92 | ||
|
|
2c6071ea79 | ||
|
|
4ac90e7e77 | ||
|
|
76e0c6e7a7 | ||
|
|
d3af567287 | ||
|
|
0484e3b484 | ||
|
|
be4ce4a288 | ||
|
|
7d764cb043 | ||
|
|
cd51f18eab | ||
|
|
97f8bdd3ac | ||
|
|
64b67b08cb | ||
|
|
626c13cde2 | ||
|
|
09ff9f6e86 | ||
|
|
8bc211d413 | ||
|
|
67758f6eb3 | ||
|
|
43bece3c57 | ||
|
|
16085fd594 | ||
|
|
5a2ac0c3dc | ||
|
|
26d4444137 | ||
|
|
59ddc37cfd | ||
|
|
fe94fcc204 |
@@ -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
|
* MQTT broker - Any MQTT broker, reachable via IPv4 or Tor, through TLS or insecure communications
|
||||||
* `torch-subscriber` - Listens for and handles onion hostname publications
|
* `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:
|
If you don't already have a GPG key, generate one:
|
||||||
|
|
||||||
@@ -25,7 +39,7 @@ Using the e-mail address you provided during GPG key generation, run `build-deb.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build-deb.sh [email protected]
|
./build-deb.sh [email protected]
|
||||||
apt update && apt install build/torch-agent_0.0.4-1_all.deb
|
apt update && apt install build/torch-agent_0.0.6-1_all.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
This will:
|
This will:
|
||||||
@@ -44,4 +58,4 @@ The configuation directory can be specified by
|
|||||||
|
|
||||||
A fully configured example can be found [here](example)
|
A fully configured example can be found [here](example)
|
||||||
|
|
||||||
See the sample [`torch.conf`](torch.conf) file for additional configuration options and details
|
See the sample [`torch.conf`](torch.conf) file for additional configuration options and details
|
||||||
|
|||||||
+4
-4
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
if [[ -z "${DEB_EMAIL}" ]]; then
|
if [[ -z "${DEB_EMAIL}" ]]; then
|
||||||
DEB_EMAIL="$1"
|
DEB_EMAIL="$1"
|
||||||
|
DPKG_BUILD_OPTS=-k"$DEB_EMAIL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "${DEB_EMAIL}" ]]; then
|
if [[ -z "${DEB_EMAIL}" ]]; then
|
||||||
echo "E-mail address required for packaging signing with gpg key!"
|
DEB_EMAIL="[email protected]"
|
||||||
echo "Usage: ./build-deb.sh EMAIL"
|
DPKG_BUILD_OPTS="-us -uc"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TORCH_VERSION=$(git describe --tags --abbrev=0)
|
TORCH_VERSION=$(git describe --tags --abbrev=0)
|
||||||
@@ -31,4 +31,4 @@ cd "$PROJECT" || exit
|
|||||||
export USER
|
export USER
|
||||||
USER=$(whoami)
|
USER=$(whoami)
|
||||||
dh_make --createorig -e "$DEB_EMAIL" -s -y
|
dh_make --createorig -e "$DEB_EMAIL" -s -y
|
||||||
dpkg-buildpackage -k"$DEB_EMAIL"
|
dpkg-buildpackage $DPKG_BUILD_OPTS
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
torch-agent (0.0.4-1) stable; urgency=medium
|
torch-agent (0.0.6-1) stable; urgency=medium
|
||||||
|
|
||||||
* Update
|
* Update
|
||||||
|
|
||||||
|
|||||||
Vendored
+3
-1
@@ -42,7 +42,9 @@ configure_tor_controller() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $TORRC_CHANGED -eq 1 ]; then
|
if [ $TORRC_CHANGED -eq 1 ]; then
|
||||||
systemctl reload tor
|
if [ -d "/run/systemd/system" ]; then
|
||||||
|
systemctl reload tor
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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" ]
|
||||||
@@ -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
|
||||||
|
```
|
||||||
@@ -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-----
|
||||||
@@ -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-----
|
||||||
@@ -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-----
|
||||||
@@ -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
|
||||||
|
|
||||||
Executable
+10
@@ -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
|
||||||
+1
-10
@@ -35,19 +35,10 @@ In a separate terminal window, run the subscriber:
|
|||||||
|
|
||||||
#### Run TORch Agent in Vagrant
|
#### Run TORch Agent in Vagrant
|
||||||
|
|
||||||
[Build](..) the latest source into a Debian package and copy it to `example/`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ..
|
|
||||||
./make-pkg.sh [email protected]
|
|
||||||
cp -f build/torch-agent_0.0.4-1_all.deb example/
|
|
||||||
cd example
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the Vagrant box in a third terminal window:
|
Run the Vagrant box in a third terminal window:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
vagrant up
|
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.
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
listener 8883
|
websockets_log_level 9
|
||||||
connection_messages true
|
connection_messages true
|
||||||
log_type all
|
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
|
cafile /mosquitto/config/ca.crt
|
||||||
keyfile /mosquitto/config/mqtt.example.com.key
|
keyfile /mosquitto/config/mqtt.example.com.key
|
||||||
certfile /mosquitto/config/mqtt.example.com.crt
|
certfile /mosquitto/config/mqtt.example.com.crt
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/bash
|
#!/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
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/bash
|
#!/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
|
||||||
|
|||||||
Executable
+7
@@ -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,3 +3,4 @@ setuptools~=50.3.2
|
|||||||
stdeb3~=0.9.0.post2
|
stdeb3~=0.9.0.post2
|
||||||
paho-mqtt~=1.5.1
|
paho-mqtt~=1.5.1
|
||||||
stem>=1.8.0
|
stem>=1.8.0
|
||||||
|
PySocks
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ install_requires =
|
|||||||
setuptools~=50.3.1
|
setuptools~=50.3.1
|
||||||
pip~=20.2.3
|
pip~=20.2.3
|
||||||
stem
|
stem
|
||||||
|
PySocks
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
console_scripts = torch-agent=torch_agent.torch_agent:main
|
console_scripts = torch-agent=torch_agent.torch_agent:main
|
||||||
|
|||||||
+28
-3
@@ -1,22 +1,47 @@
|
|||||||
|
#################
|
||||||
|
# The `tor` section heading is required
|
||||||
[tor]
|
[tor]
|
||||||
|
|
||||||
|
# Optional: The Tor onion proxy host and port (default: 127.0.0.1:9050)
|
||||||
|
#ProxyHost 127.0.0.1
|
||||||
ProxyPort = 9050
|
ProxyPort = 9050
|
||||||
|
|
||||||
|
# Optional: The Tor controller port (default: 9051) for creating new hidden services
|
||||||
ControllerPort = 9051
|
ControllerPort = 9051
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# The `ssh` section heading is required
|
||||||
[ssh]
|
[ssh]
|
||||||
|
|
||||||
|
# Optional: Local SSH sevice port (default: 22)
|
||||||
Port = 22
|
Port = 22
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# The `mqtt` section heading is required
|
||||||
[mqtt]
|
[mqtt]
|
||||||
|
|
||||||
|
# Optional: The MQTT broker host and port (default: localhost:1883)
|
||||||
|
# Can be either IPv4 or Tor onion hostname
|
||||||
BrokerHost = mqtt.example.com
|
BrokerHost = mqtt.example.com
|
||||||
#BrokerHost = example1i3uyrbfoi3fi.onion
|
#BrokerHost = example1i3uyrbfoi3fi.onion
|
||||||
|
|
||||||
BrokerPort = 1883
|
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
|
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
|
#RequireCertificate = true
|
||||||
|
|
||||||
#CaFile = ca.crt
|
#CaFile = ca.crt
|
||||||
#CertFile = client.crt
|
#CertFile = client.crt
|
||||||
#KeyFile = client.key
|
#KeyFile = client.key
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.0.4"
|
__version__ = "0.0.6"
|
||||||
|
|||||||
+73
-44
@@ -1,15 +1,16 @@
|
|||||||
from stem.control import Controller
|
|
||||||
import stem.connection
|
|
||||||
import paho.mqtt.client as mqtt
|
|
||||||
from paho.mqtt.client import socks
|
|
||||||
import ssl
|
|
||||||
import socket
|
|
||||||
import json
|
|
||||||
import configparser
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import configparser
|
||||||
|
import json
|
||||||
|
import socket
|
||||||
|
import ssl
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
|
import paho.mqtt.publish as publish
|
||||||
|
import socks
|
||||||
|
import stem.connection
|
||||||
|
from stem.control import Controller
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='Broadcast SSH hidden service hostname via MQTT')
|
parser = argparse.ArgumentParser(description='Broadcast SSH hidden service hostname via MQTT')
|
||||||
@@ -30,8 +31,12 @@ def main():
|
|||||||
print("Using torch configuration path: " + config_path)
|
print("Using torch configuration path: " + config_path)
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(config_path + "torch.conf")
|
|
||||||
|
|
||||||
|
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_proxy_port = config['tor'].getint('ProxyPort', fallback=9050)
|
||||||
tor_controller_port = config['tor'].getint('ControllerPort', fallback=9051)
|
tor_controller_port = config['tor'].getint('ControllerPort', fallback=9051)
|
||||||
|
|
||||||
@@ -40,59 +45,83 @@ def main():
|
|||||||
mqtt_config = config['mqtt']
|
mqtt_config = config['mqtt']
|
||||||
mqtt_broker_host = mqtt_config.get('BrokerHost', fallback="localhost")
|
mqtt_broker_host = mqtt_config.get('BrokerHost', fallback="localhost")
|
||||||
mqtt_broker_port = mqtt_config.getint('BrokerPort', fallback=1883)
|
mqtt_broker_port = mqtt_config.getint('BrokerPort', fallback=1883)
|
||||||
client_id = mqtt_config.get('ClientID', fallback=socket.gethostname())
|
mqtt_broker_using_tor = mqtt_broker_host.endswith(".onion")
|
||||||
mqtt_topic = mqtt_config.get('Topic', fallback="torch/%s/onion_url" % client_id)
|
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(
|
mqtt_require_certificate = mqtt_config.getboolean(
|
||||||
'RequireCertificate',
|
'RequireCertificate',
|
||||||
fallback=False)
|
fallback=False)
|
||||||
|
|
||||||
mqtt_ca_file = config_path + mqtt_config.get('CaFile')
|
mqtt_ca_file = mqtt_config.get('CaFile', fallback=None)
|
||||||
mqtt_cert_file = config_path + mqtt_config.get('CertFile')
|
mqtt_ca_file = config_path + mqtt_ca_file
|
||||||
mqtt_key_file = config_path + mqtt_config.get('KeyFile')
|
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:
|
with Controller.from_port(port=tor_controller_port) as controller:
|
||||||
|
|
||||||
protocol_info = stem.connection.get_protocolinfo(controller)
|
protocol_info = stem.connection.get_protocolinfo(controller)
|
||||||
|
|
||||||
stem.connection.authenticate_safecookie(
|
stem.connection.authenticate_safecookie(controller, protocol_info.cookie_path)
|
||||||
controller,
|
|
||||||
protocol_info.cookie_path)
|
|
||||||
|
|
||||||
print("Connected to Tor on port %s" % tor_controller_port)
|
print("Creating TOR Hidden Service...")
|
||||||
|
|
||||||
service = controller.create_ephemeral_hidden_service(ssh_port, detached=True)
|
service = controller.create_ephemeral_hidden_service(ssh_port, detached=True)
|
||||||
|
|
||||||
onion_address = "%s.onion" % service.service_id
|
onion_address = "%s.onion" % service.service_id
|
||||||
|
|
||||||
print("Created Tor Hidden Service for local port %s at %s" % (ssh_port, onion_address))
|
print("Created Tor Hidden Service for local service on port %s at %s" % (ssh_port, onion_address))
|
||||||
|
|
||||||
payload = {
|
protocol = "mqtt"
|
||||||
'clientId': client_id,
|
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)"),
|
'timestamp': datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)"),
|
||||||
'onionAddress': onion_address,
|
'onionAddress': onion_address,
|
||||||
'sshPort': ssh_port
|
'sshPort': ssh_port
|
||||||
}
|
})
|
||||||
|
|
||||||
client = mqtt.Client()
|
publish.single(mqtt_topic,
|
||||||
protocol = "mqtt"
|
payload,
|
||||||
|
qos=1,
|
||||||
if mqtt_require_certificate:
|
hostname=mqtt_broker_host,
|
||||||
client.tls_set(
|
port=mqtt_broker_port,
|
||||||
ca_certs=mqtt_ca_file,
|
client_id=mqtt_client_id,
|
||||||
certfile=mqtt_cert_file,
|
tls=tls_args,
|
||||||
keyfile=mqtt_key_file,
|
proxy_args=proxy_args)
|
||||||
cert_reqs=ssl.CERT_REQUIRED)
|
|
||||||
protocol = "mqtts"
|
|
||||||
|
|
||||||
if mqtt_broker_host.endswith(".onion"):
|
|
||||||
client.proxy_set(proxy_type=socks.SOCKS5, proxy_addr="localhost", proxy_port=tor_proxy_port)
|
|
||||||
client.tls_insecure_set(True)
|
|
||||||
|
|
||||||
client.connect(mqtt_broker_host, mqtt_broker_port, 60)
|
|
||||||
client.publish(mqtt_topic, json.dumps(payload))
|
|
||||||
print("Connected to MQTT Broker at %s://%s:%s/%s" % (protocol, mqtt_broker_host, mqtt_broker_port, mqtt_topic))
|
|
||||||
print("Published payload: " + json.dumps(payload))
|
|
||||||
|
|
||||||
client.disconnect()
|
|
||||||
print("Disconnected from MQTT Broker")
|
|
||||||
|
|||||||
Reference in New Issue
Block a user