diff --git a/Dockerfile-torsocks b/Dockerfile-torsocks
new file mode 100644
index 0000000..a2238a9
--- /dev/null
+++ b/Dockerfile-torsocks
@@ -0,0 +1,15 @@
+FROM ubuntu:20.04
+
+RUN apt-get update && apt-get install tor -y
+
+RUN mkdir -p /run/tor \
+ && chown -R debian-tor:debian-tor /run/tor \
+ && chmod 700 -R /run/tor
+
+COPY conf/torrc /etc/tor/torrc
+
+USER debian-tor
+
+EXPOSE 9050
+
+ENTRYPOINT ["tor"]
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..56c17b4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+up:
+ docker-compose up -d
+
+logs:
+ docker-compose logs -f
diff --git a/conf/torrc b/conf/torrc
new file mode 100644
index 0000000..5e8f91b
--- /dev/null
+++ b/conf/torrc
@@ -0,0 +1,14 @@
+BridgeRelay 1
+ControlSocket /run/tor/control
+ControlSocketsGroupWritable 1
+CookieAuthentication 1
+CookieAuthFileGroupReadable 1
+CookieAuthFile /run/tor/control.authcookie
+DataDirectory /var/lib/tor
+ExitPolicy reject6 *:*, reject *:*
+ExitRelay 0
+IPv6Exit 0
+Log notice stdout
+ORPort 9001
+PublishServerDescriptor 0
+SOCKSPort 0.0.0.0:9050
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..101f0c9
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,10 @@
+version: '3'
+services:
+ tor:
+ container_name: tor
+ build:
+ context: .
+ dockerfile: Dockerfile-torsocks
+ restart: unless-stopped
+ ports:
+ - 127.0.0.1:9050:9050
diff --git a/xmrnodes/app.py b/xmrnodes/app.py
index 4337f46..c5cb924 100644
--- a/xmrnodes/app.py
+++ b/xmrnodes/app.py
@@ -9,7 +9,7 @@ from datetime import datetime
from flask import Flask, request, redirect
from flask import render_template, flash, url_for
from urllib.parse import urlparse
-from xmrnodes.helpers import determine_crypto
+from xmrnodes.helpers import determine_crypto, is_onion, make_request
from xmrnodes.forms import SubmitNode
from xmrnodes.models import Node
from xmrnodes import config
@@ -91,8 +91,7 @@ def check():
now = datetime.utcnow()
logging.info(f"Attempting to check {node.url}")
try:
- r = requests.get(node.url + "/get_info", timeout=5)
- r.raise_for_status()
+ r = make_request(node.url)
assert "status" in r.json()
assert "offline" in r.json()
assert "height" in r.json()
@@ -115,14 +114,9 @@ def validate():
nodes = Node.select().where(Node.validated == False)
for node in nodes:
now = datetime.utcnow()
- is_onion = node.url.split(":")[1].endswith(".onion")
logging.info(f"Attempting to validate {node.url}")
- if is_onion:
- logging.info("onion address found")
- node.is_tor = True
try:
- r = requests.get(node.url + "/get_info", timeout=5)
- r.raise_for_status()
+ r = make_request(node.url)
assert "height" in r.json()
assert "nettype" in r.json()
nettype = r.json()["nettype"]
@@ -135,6 +129,7 @@ def validate():
node.last_height = r.json()["height"]
node.datetime_checked = now
node.crypto = crypto
+ node.is_tor = is_onion(node.url)
node.save()
else:
logging.info("unexpected nettype")
diff --git a/xmrnodes/config.example.py b/xmrnodes/config.example.py
index 02cb0ec..116a24c 100644
--- a/xmrnodes/config.example.py
+++ b/xmrnodes/config.example.py
@@ -2,3 +2,5 @@ import os
SECRET_KEY = os.environ.get('SECRET_KEY', 'xxxx')
DATA_DIR = os.environ.get('DATA_DIR', './data')
+TOR_HOST = os.environ.get('TOR_HOST', '127.0.0.1')
+TOR_PORT = os.environ.get('TOR_PORT', 9050)
diff --git a/xmrnodes/helpers.py b/xmrnodes/helpers.py
index a338b51..c065349 100644
--- a/xmrnodes/helpers.py
+++ b/xmrnodes/helpers.py
@@ -1,4 +1,17 @@
from requests import get as r_get
+from xmrnodes import config
+
+
+def make_request(url: str, path="/get_info", data=None):
+ if is_onion(url):
+ proxies = {"http": f"socks5h://{config.TOR_HOST}:{config.TOR_PORT}"}
+ timeout = 18
+ else:
+ proxies = None
+ timeout = 6
+ r = r_get(url + path, timeout=timeout, proxies=proxies, json=data)
+ r.raise_for_status()
+ return r
def determine_crypto(url):
data = {"method": "get_block_header_by_height", "params": {"height": 0}}
@@ -14,8 +27,7 @@ def determine_crypto(url):
]
}
try:
- r = r_get(url + "/json_rpc", json=data, timeout=5)
- r.raise_for_status()
+ r = make_request(url, "/json_rpc", data)
assert "result" in r.json()
hash = r.json()["result"]["block_header"]["hash"]
crypto = "unknown"
@@ -26,3 +38,12 @@ def determine_crypto(url):
return crypto
except:
return "unknown"
+
+def is_onion(url: str):
+ _split = url.split(":")
+ if len(_split) < 2:
+ return False
+ if _split[1].endswith(".onion"):
+ return True
+ else:
+ return False
diff --git a/xmrnodes/static/images/tor.svg b/xmrnodes/static/images/tor.svg
new file mode 100644
index 0000000..6e28fc4
--- /dev/null
+++ b/xmrnodes/static/images/tor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/xmrnodes/templates/index.html b/xmrnodes/templates/index.html
index 11d828f..be40017 100644
--- a/xmrnodes/templates/index.html
+++ b/xmrnodes/templates/index.html
@@ -34,7 +34,6 @@
URL
- Tor
Available
Network
Height
@@ -44,8 +43,7 @@