diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..81bbbae --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +keys/ diff --git a/Dockerfile b/Dockerfile index e3a41ae..5063b0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,39 @@ -FROM debian:jessie +FROM alpine -ENV DEBIAN_FRONTEND=noninteractive -ENV HOME /var/lib/tor +ENV HOME /var/lib/tor +ENV TOR_VERSION 0.2.8.8 -RUN apt-get update && apt-get install --no-install-recommends -y \ - tor \ - python3-pip +RUN apk add --no-cache git libevent-dev openssl-dev gcc make automake ca-certificates autoconf musl-dev && \ + mkdir -p /usr/local/src/ && \ + git clone https://git.torproject.org/tor.git /usr/local/src/tor && \ + cd /usr/local/src/tor && \ + git checkout tor-${TOR_VERSION} && \ + ./autogen.sh && ./configure --disable-asciidoc && make && make install && \ + cd .. && \ + rm -rf tor && \ + apk add --no-cache python3 python3-dev && \ + python3 -m ensurepip && \ + rm -r /usr/lib/python*/ensurepip && \ + pip3 install --upgrade pip setuptools pycrypto && \ + apk del git libevent-dev openssl-dev make automake python3-dev gcc autoconf musl-dev && \ + apk add --no-cache libevent openssl -RUN pip3 install pyentrypoint==0.3.8 +ADD assets/entrypoint-config.yml / +ADD assets/onions /usr/local/src/onions +ADD assets/torrc /var/local/tor/torrc.tpl -ADD assets/entrypoint-config.yml / -ADD assets/onions /usr/local/src/onions -ADD assets/torrc /etc/tor/torrc +RUN mkdir -p /etc/tor/ -RUN cd /usr/local/src/onions && python3 setup.py install +RUN pip install pyentrypoint==0.3.8 + +RUN cd /usr/local/src/onions && python3 setup.py install + +RUN mkdir -p ${HOME}/.tor && \ + addgroup -S -g 107 tor && \ + adduser -S -G tor -u 104 -H -h ${HOME} tor VOLUME ["/var/lib/tor/hidden_service/"] ENTRYPOINT ["pyentrypoint"] -CMD ["tor"] +CMD ["tor"] diff --git a/assets/entrypoint-config.yml b/assets/entrypoint-config.yml index 18483c9..b6c1884 100644 --- a/assets/entrypoint-config.yml +++ b/assets/entrypoint-config.yml @@ -1,7 +1,7 @@ command: tor -user: debian-tor -group: debian-tor +user: tor +group: tor secret_env: - '*_KEY' @@ -11,8 +11,8 @@ pre_conf_commands: - onions --setup-hosts post_conf_commands: - - timeout 3s tor > /dev/null || true + - timeout -t 3 tor > /dev/null || true - onions - - chown -R debian-tor:debian-tor $HOME + - chown -R tor:tor $HOME debug: false diff --git a/assets/onions/onions/Onions.py b/assets/onions/onions/Onions.py index efde355..8ff789e 100644 --- a/assets/onions/onions/Onions.py +++ b/assets/onions/onions/Onions.py @@ -12,11 +12,31 @@ import argparse from jinja2 import Environment from jinja2 import FileSystemLoader +import socket + +from Crypto.PublicKey import RSA +from hashlib import sha1 +from base64 import b32encode + class Setup(object): hidden_service_dir = "/var/lib/tor/hidden_service/" - torrc = '/etc/tor/torrc' + torrc = '/usr/local/etc/tor/torrc' + torrc_template = '/var/local/tor/torrc.tpl' + + def onion_url_gen(self, key): + "Get onion url from private key" + + # Convert private RSA to public DER + priv = RSA.importKey(key.strip()) + der = priv.publickey().exportKey("DER") + + # hash key, keep first half of sha1, base32 encode + onion = b32encode(sha1(der[22:]).digest()[:10]) + + return '{onion}.onion'.format(onion=onion.decode().lower()) + def _add_host(self, host): if host not in self.setup: @@ -31,6 +51,10 @@ class Setup(object): if port not in self.setup[host]['ports']: self.setup[host]['ports'].append(port) + def _get_ip(self): + for host in self.setup: + self.setup[host]['ip'] = str(socket.gethostbyname(host)) + def _get_key(self, host, key): self._add_host(host) assert len(key) > 800 @@ -68,12 +92,17 @@ class Setup(object): if 'key' in conf: serv_dir = os.path.join(self.hidden_service_dir, link) os.makedirs(serv_dir, exist_ok=True) + os.chmod(serv_dir, 0o700) with open(os.path.join(serv_dir, 'private_key'), 'w') as f: f.write(conf['key']) + os.fchmod(f.fileno(), 0o600) + with open(os.path.join(serv_dir, 'hostname'), 'w') as f: + f.write(self.onion_url_gen(conf['key'])) + def _set_conf(self): env = Environment(loader=FileSystemLoader('/')) - temp = env.get_template(self.torrc) + temp = env.get_template(self.torrc_template) with open(self.torrc, mode='w') as f: f.write(temp.render(setup=self.setup, env=os.environ)) @@ -83,6 +112,7 @@ class Setup(object): try: self._get_setup_from_env() self._get_setup_from_links() + self._get_ip() self._set_keys() self._set_conf() except: diff --git a/assets/onions/setup.py b/assets/onions/setup.py index 4fe80d9..5fa5962 100644 --- a/assets/onions/setup.py +++ b/assets/onions/setup.py @@ -6,7 +6,7 @@ from setuptools import setup setup( name='onions', - version='0.1', + version='0.2', packages=find_packages(), @@ -31,6 +31,9 @@ setup( "Topic :: System :: Installation/Setup", ], + install_requires=['pyentrypoint', + 'Jinja2>=2.8', + 'pycrypto',], entry_points={ 'console_scripts': [ diff --git a/assets/torrc b/assets/torrc index 4f087a8..c3858a1 100644 --- a/assets/torrc +++ b/assets/torrc @@ -2,7 +2,7 @@ HiddenServiceDir /var/lib/tor/hidden_service/{{service}} {% for ports in conf['ports'] %} # PORT {{service}} {{ports[0]}} -HiddenServicePort {{ports[0]}} {{service}}:{{ports[1]}} +HiddenServicePort {{ports[0]}} {{conf['ip']}}:{{ports[1]}} {% endfor %} {% endfor %} diff --git a/docker-compose.v2.yml b/docker-compose.v2.yml index f129b1b..34586ee 100644 --- a/docker-compose.v2.yml +++ b/docker-compose.v2.yml @@ -5,7 +5,6 @@ version: "2" services: tor: image: goldy/tor-hidden-service - # or build: . links: - hello diff --git a/docker-compose.yml b/docker-compose.yml index c0bd290..c5b3971 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,6 @@ tor: image: goldy/tor-hidden-service - # or - build: . links: - hello - world