mirror of
https://github.com/cmehay/docker-tor-hidden-service
synced 2024-11-18 09:25:54 +00:00
commit
f104c78c7c
1
.gitignore
vendored
1
.gitignore
vendored
@ -105,3 +105,4 @@ ENV/
|
||||
|
||||
# more
|
||||
key/
|
||||
.vscode
|
||||
|
@ -1,5 +1,6 @@
|
||||
repos:
|
||||
- repo: git://github.com/pre-commit/pre-commit-hooks
|
||||
sha: v0.9.1
|
||||
rev: v2.2.1
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-docstring-first
|
||||
@ -10,12 +11,14 @@
|
||||
args:
|
||||
- --exclude=__init__.py
|
||||
language_version: python3
|
||||
- id: autopep8-wrapper
|
||||
language_version: python3
|
||||
- id: requirements-txt-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/pre-commit/mirrors-autopep8
|
||||
rev: 'v1.4.4'
|
||||
hooks:
|
||||
- id: autopep8
|
||||
- repo: git://github.com/asottile/reorder_python_imports
|
||||
sha: v0.3.5
|
||||
rev: v1.4.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
language_version: python3
|
||||
|
10
.travis.yml
10
.travis.yml
@ -1,10 +1,10 @@
|
||||
sudo: false
|
||||
dist: xenial
|
||||
language: python
|
||||
python:
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- '3.6'
|
||||
- '3.7'
|
||||
install: pip install tox-travis pre-commit
|
||||
script:
|
||||
- pre-commit run --all-files
|
||||
- tox
|
||||
- pre-commit run --all-files
|
||||
- tox
|
||||
|
56
Dockerfile
56
Dockerfile
@ -1,39 +1,43 @@
|
||||
FROM alpine
|
||||
FROM alpine:latest
|
||||
ARG tor_version
|
||||
|
||||
ENV HOME /var/lib/tor
|
||||
|
||||
RUN apk add --no-cache git libevent-dev openssl-dev gcc make automake ca-certificates autoconf musl-dev coreutils && \
|
||||
mkdir -p /usr/local/src/ && \
|
||||
git clone https://git.torproject.org/tor.git /usr/local/src/tor && \
|
||||
cd /usr/local/src/tor && \
|
||||
git checkout $(git branch -a | grep 'release' | sort -V | tail -1) && \
|
||||
./autogen.sh && \
|
||||
./configure \
|
||||
--disable-asciidoc \
|
||||
--sysconfdir=/etc \
|
||||
--disable-unittests && \
|
||||
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 coreutils && \
|
||||
apk add --no-cache libevent openssl
|
||||
RUN apk add --no-cache git libevent-dev openssl-dev gcc make automake ca-certificates autoconf musl-dev coreutils zlib-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 \
|
||||
--sysconfdir=/etc \
|
||||
--disable-unittests && \
|
||||
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 && \
|
||||
apk del git libevent-dev openssl-dev make automake python3-dev autoconf musl-dev coreutils && \
|
||||
apk add --no-cache libevent openssl
|
||||
|
||||
RUN mkdir -p /etc/tor/
|
||||
|
||||
ADD assets/entrypoint-config.yml /
|
||||
ADD assets/onions /usr/local/src/onions
|
||||
ADD assets/torrc /var/local/tor/torrc.tpl
|
||||
COPY assets/onions /usr/local/src/onions
|
||||
COPY assets/torrc /var/local/tor/torrc.tpl
|
||||
|
||||
|
||||
RUN cd /usr/local/src/onions && python3 setup.py install
|
||||
RUN cd /usr/local/src/onions && apk add --no-cache openssl-dev libffi-dev gcc python3-dev libc-dev && \
|
||||
python3 setup.py install && \
|
||||
apk del libffi-dev gcc python3-dev libc-dev openssl-dev
|
||||
|
||||
RUN mkdir -p ${HOME}/.tor && \
|
||||
addgroup -S -g 107 tor && \
|
||||
adduser -S -G tor -u 104 -H -h ${HOME} tor
|
||||
addgroup -S -g 107 tor && \
|
||||
adduser -S -G tor -u 104 -H -h ${HOME} tor
|
||||
|
||||
COPY assets/entrypoint-config.yml /
|
||||
|
||||
VOLUME ["/var/lib/tor/hidden_service/"]
|
||||
|
||||
|
25
Makefile
25
Makefile
@ -1,23 +1,28 @@
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
|
||||
TOR_VERSION = $(shell bash last_tor_version.sh)
|
||||
|
||||
test:
|
||||
tox
|
||||
|
||||
tag:
|
||||
git tag v$(TOR_VERSION)
|
||||
|
||||
check:
|
||||
pre-commit run --all-files
|
||||
|
||||
build:
|
||||
docker-compose build
|
||||
- echo build with tor version $(TOR_VERSION)
|
||||
docker-compose -f docker-compose.build.yml build
|
||||
|
||||
rebuild:
|
||||
docker-compose -f docker-compose.build.yml build --no-cache
|
||||
|
||||
run: build
|
||||
docker-compose up
|
||||
docker-compose -f docker-compose-v1.yml up
|
||||
|
||||
build-v2:
|
||||
docker-compose -f docker-compose.v2.yml build
|
||||
|
||||
run-v2: build-v2
|
||||
run-v2: build
|
||||
docker-compose -f docker-compose.v2.yml up
|
||||
|
||||
build-v3:
|
||||
docker-compose -f docker-compose.v3.yml build
|
||||
|
||||
run-v3: build-v3
|
||||
run-v3: build
|
||||
docker-compose -f docker-compose.v3.yml up
|
||||
|
15
Pipfile
Normal file
15
Pipfile
Normal file
@ -0,0 +1,15 @@
|
||||
[[source]]
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
tox = "*"
|
||||
|
||||
[dev-packages]
|
||||
tox = "*"
|
||||
pre-commit = "*"
|
||||
ptpython = "*"
|
||||
cryptography = "*"
|
||||
pylint = "*"
|
||||
autopep8 = "*"
|
415
Pipfile.lock
generated
Normal file
415
Pipfile.lock
generated
Normal file
@ -0,0 +1,415 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "98040ea608cfb470b37bd65b2b0092dc483e9d7781b613c1f526285eb992d3a0"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.python.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"filelock": {
|
||||
"hashes": [
|
||||
"sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633",
|
||||
"sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6"
|
||||
],
|
||||
"version": "==3.0.10"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f",
|
||||
"sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746"
|
||||
],
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
|
||||
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
|
||||
],
|
||||
"version": "==1.8.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||
],
|
||||
"version": "==1.12.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
|
||||
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
|
||||
],
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"tox": {
|
||||
"hashes": [
|
||||
"sha256:69620e19de33a6b7ee8aeda5478791b3618ff58f0b869dbd0319fb71aa903deb",
|
||||
"sha256:e5cdb1653aa27b3e46b5c390de6b6d51d31afcfdbd9d1222d82d76b82ad03d9b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.8.6"
|
||||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417",
|
||||
"sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39"
|
||||
],
|
||||
"version": "==16.4.3"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"asn1crypto": {
|
||||
"hashes": [
|
||||
"sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
|
||||
"sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
|
||||
],
|
||||
"version": "==0.24.0"
|
||||
},
|
||||
"aspy.yaml": {
|
||||
"hashes": [
|
||||
"sha256:ae249074803e8b957c83fdd82a99160d0d6d26dff9ba81ba608b42eebd7d8cd3",
|
||||
"sha256:c7390d79f58eb9157406966201abf26da0d56c07e0ff0deadc39c8f4dbc13482"
|
||||
],
|
||||
"version": "==1.2.0"
|
||||
},
|
||||
"astroid": {
|
||||
"hashes": [
|
||||
"sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4",
|
||||
"sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4"
|
||||
],
|
||||
"version": "==2.2.5"
|
||||
},
|
||||
"autopep8": {
|
||||
"hashes": [
|
||||
"sha256:33d2b5325b7e1afb4240814fe982eea3a92ebea712869bfd08b3c0393404248c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4.3"
|
||||
},
|
||||
"cffi": {
|
||||
"hashes": [
|
||||
"sha256:00b97afa72c233495560a0793cdc86c2571721b4271c0667addc83c417f3d90f",
|
||||
"sha256:0ba1b0c90f2124459f6966a10c03794082a2f3985cd699d7d63c4a8dae113e11",
|
||||
"sha256:0bffb69da295a4fc3349f2ec7cbe16b8ba057b0a593a92cbe8396e535244ee9d",
|
||||
"sha256:21469a2b1082088d11ccd79dd84157ba42d940064abbfa59cf5f024c19cf4891",
|
||||
"sha256:2e4812f7fa984bf1ab253a40f1f4391b604f7fc424a3e21f7de542a7f8f7aedf",
|
||||
"sha256:2eac2cdd07b9049dd4e68449b90d3ef1adc7c759463af5beb53a84f1db62e36c",
|
||||
"sha256:2f9089979d7456c74d21303c7851f158833d48fb265876923edcb2d0194104ed",
|
||||
"sha256:3dd13feff00bddb0bd2d650cdb7338f815c1789a91a6f68fdc00e5c5ed40329b",
|
||||
"sha256:4065c32b52f4b142f417af6f33a5024edc1336aa845b9d5a8d86071f6fcaac5a",
|
||||
"sha256:51a4ba1256e9003a3acf508e3b4f4661bebd015b8180cc31849da222426ef585",
|
||||
"sha256:59888faac06403767c0cf8cfb3f4a777b2939b1fbd9f729299b5384f097f05ea",
|
||||
"sha256:59c87886640574d8b14910840327f5cd15954e26ed0bbd4e7cef95fa5aef218f",
|
||||
"sha256:610fc7d6db6c56a244c2701575f6851461753c60f73f2de89c79bbf1cc807f33",
|
||||
"sha256:70aeadeecb281ea901bf4230c6222af0248c41044d6f57401a614ea59d96d145",
|
||||
"sha256:71e1296d5e66c59cd2c0f2d72dc476d42afe02aeddc833d8e05630a0551dad7a",
|
||||
"sha256:8fc7a49b440ea752cfdf1d51a586fd08d395ff7a5d555dc69e84b1939f7ddee3",
|
||||
"sha256:9b5c2afd2d6e3771d516045a6cfa11a8da9a60e3d128746a7fe9ab36dfe7221f",
|
||||
"sha256:9c759051ebcb244d9d55ee791259ddd158188d15adee3c152502d3b69005e6bd",
|
||||
"sha256:b4d1011fec5ec12aa7cc10c05a2f2f12dfa0adfe958e56ae38dc140614035804",
|
||||
"sha256:b4f1d6332339ecc61275bebd1f7b674098a66fea11a00c84d1c58851e618dc0d",
|
||||
"sha256:c030cda3dc8e62b814831faa4eb93dd9a46498af8cd1d5c178c2de856972fd92",
|
||||
"sha256:c2e1f2012e56d61390c0e668c20c4fb0ae667c44d6f6a2eeea5d7148dcd3df9f",
|
||||
"sha256:c37c77d6562074452120fc6c02ad86ec928f5710fbc435a181d69334b4de1d84",
|
||||
"sha256:c8149780c60f8fd02752d0429246088c6c04e234b895c4a42e1ea9b4de8d27fb",
|
||||
"sha256:cbeeef1dc3c4299bd746b774f019de9e4672f7cc666c777cd5b409f0b746dac7",
|
||||
"sha256:e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7",
|
||||
"sha256:e21162bf941b85c0cda08224dade5def9360f53b09f9f259adb85fc7dd0e7b35",
|
||||
"sha256:fb6934ef4744becbda3143d30c6604718871495a5e36c408431bf33d9c146889"
|
||||
],
|
||||
"version": "==1.12.2"
|
||||
},
|
||||
"cfgv": {
|
||||
"hashes": [
|
||||
"sha256:6e9f2feea5e84bc71e56abd703140d7a2c250fc5ba38b8702fd6a68ed4e3b2ef",
|
||||
"sha256:e7f186d4a36c099a9e20b04ac3108bd8bb9b9257e692ce18c8c3764d5cb12172"
|
||||
],
|
||||
"version": "==1.6.0"
|
||||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:066f815f1fe46020877c5983a7e747ae140f517f1b09030ec098503575265ce1",
|
||||
"sha256:210210d9df0afba9e000636e97810117dc55b7157c903a55716bb73e3ae07705",
|
||||
"sha256:26c821cbeb683facb966045e2064303029d572a87ee69ca5a1bf54bf55f93ca6",
|
||||
"sha256:2afb83308dc5c5255149ff7d3fb9964f7c9ee3d59b603ec18ccf5b0a8852e2b1",
|
||||
"sha256:2db34e5c45988f36f7a08a7ab2b69638994a8923853dec2d4af121f689c66dc8",
|
||||
"sha256:409c4653e0f719fa78febcb71ac417076ae5e20160aec7270c91d009837b9151",
|
||||
"sha256:45a4f4cf4f4e6a55c8128f8b76b4c057027b27d4c67e3fe157fa02f27e37830d",
|
||||
"sha256:48eab46ef38faf1031e58dfcc9c3e71756a1108f4c9c966150b605d4a1a7f659",
|
||||
"sha256:6b9e0ae298ab20d371fc26e2129fd683cfc0cfde4d157c6341722de645146537",
|
||||
"sha256:6c4778afe50f413707f604828c1ad1ff81fadf6c110cb669579dea7e2e98a75e",
|
||||
"sha256:8c33fb99025d353c9520141f8bc989c2134a1f76bac6369cea060812f5b5c2bb",
|
||||
"sha256:9873a1760a274b620a135054b756f9f218fa61ca030e42df31b409f0fb738b6c",
|
||||
"sha256:9b069768c627f3f5623b1cbd3248c5e7e92aec62f4c98827059eed7053138cc9",
|
||||
"sha256:9e4ce27a507e4886efbd3c32d120db5089b906979a4debf1d5939ec01b9dd6c5",
|
||||
"sha256:acb424eaca214cb08735f1a744eceb97d014de6530c1ea23beb86d9c6f13c2ad",
|
||||
"sha256:c8181c7d77388fe26ab8418bb088b1a1ef5fde058c6926790c8a0a3d94075a4a",
|
||||
"sha256:d4afbb0840f489b60f5a580a41a1b9c3622e08ecb5eec8614d4fb4cd914c4460",
|
||||
"sha256:d9ed28030797c00f4bc43c86bf819266c76a5ea61d006cd4078a93ebf7da6bfd",
|
||||
"sha256:e603aa7bb52e4e8ed4119a58a03b60323918467ef209e6ff9db3ac382e5cf2c6"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.6.1"
|
||||
},
|
||||
"docopt": {
|
||||
"hashes": [
|
||||
"sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
|
||||
],
|
||||
"version": "==0.6.2"
|
||||
},
|
||||
"filelock": {
|
||||
"hashes": [
|
||||
"sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633",
|
||||
"sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6"
|
||||
],
|
||||
"version": "==3.0.10"
|
||||
},
|
||||
"identify": {
|
||||
"hashes": [
|
||||
"sha256:244e7864ef59f0c7c50c6db73f58564151d91345cd9b76ed793458953578cadd",
|
||||
"sha256:8ff062f90ad4b09cfe79b5dfb7a12e40f19d2e68a5c9598a49be45f16aba7171"
|
||||
],
|
||||
"version": "==1.4.1"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:46fc60c34b6ed7547e2a723fc8de6dc2e3a1173f8423246b3ce497f064e9c3de",
|
||||
"sha256:bc136180e961875af88b1ab85b4009f4f1278f8396a60526c0009f503a1a96ca"
|
||||
],
|
||||
"version": "==0.9"
|
||||
},
|
||||
"isort": {
|
||||
"hashes": [
|
||||
"sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43",
|
||||
"sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a"
|
||||
],
|
||||
"version": "==4.3.17"
|
||||
},
|
||||
"jedi": {
|
||||
"hashes": [
|
||||
"sha256:2bb0603e3506f708e792c7f4ad8fc2a7a9d9c2d292a358fbbd58da531695595b",
|
||||
"sha256:2c6bcd9545c7d6440951b12b44d373479bf18123a401a52025cf98563fbd826c"
|
||||
],
|
||||
"version": "==0.13.3"
|
||||
},
|
||||
"lazy-object-proxy": {
|
||||
"hashes": [
|
||||
"sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33",
|
||||
"sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39",
|
||||
"sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019",
|
||||
"sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088",
|
||||
"sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b",
|
||||
"sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e",
|
||||
"sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6",
|
||||
"sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b",
|
||||
"sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5",
|
||||
"sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff",
|
||||
"sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd",
|
||||
"sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7",
|
||||
"sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff",
|
||||
"sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d",
|
||||
"sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2",
|
||||
"sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35",
|
||||
"sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4",
|
||||
"sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514",
|
||||
"sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252",
|
||||
"sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109",
|
||||
"sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f",
|
||||
"sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c",
|
||||
"sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92",
|
||||
"sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577",
|
||||
"sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d",
|
||||
"sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d",
|
||||
"sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f",
|
||||
"sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a",
|
||||
"sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b"
|
||||
],
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"mccabe": {
|
||||
"hashes": [
|
||||
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
|
||||
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
|
||||
],
|
||||
"version": "==0.6.1"
|
||||
},
|
||||
"nodeenv": {
|
||||
"hashes": [
|
||||
"sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"
|
||||
],
|
||||
"version": "==1.3.3"
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
"sha256:17cc2d7a945eb42c3569d4564cdf49bde221bc2b552af3eca9c1aad517dcdd33",
|
||||
"sha256:2e9574cb12e7112a87253e14e2c380ce312060269d04bd018478a3c92ea9a376"
|
||||
],
|
||||
"version": "==0.4.0"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f",
|
||||
"sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746"
|
||||
],
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"pre-commit": {
|
||||
"hashes": [
|
||||
"sha256:75a9110eae00d009c913616c0fc8a6a02e7716c4a29a14cac9b313d2c7338ab0",
|
||||
"sha256:f882c65316eb5b705fe4613e92a7c91055c1800102e4d291cfd18912ec9cf90e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.15.1"
|
||||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780",
|
||||
"sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1",
|
||||
"sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"
|
||||
],
|
||||
"version": "==2.0.9"
|
||||
},
|
||||
"ptpython": {
|
||||
"hashes": [
|
||||
"sha256:51a74abe931f692360a32d650c2ba1ca329c08f3ed9b1de8abcd1164e0b0a6a7",
|
||||
"sha256:938ee050e37d61c138dbbeb21383dfef8b9ed4ffb453a5f34041f42025bf5042",
|
||||
"sha256:ebe9d68ea7532ec8ab306d4bdc7ec393701cd9bbd6eff0aa3067c821f99264d4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.4"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
|
||||
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
|
||||
],
|
||||
"version": "==1.8.0"
|
||||
},
|
||||
"pycodestyle": {
|
||||
"hashes": [
|
||||
"sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56",
|
||||
"sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"
|
||||
],
|
||||
"version": "==2.5.0"
|
||||
},
|
||||
"pycparser": {
|
||||
"hashes": [
|
||||
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
|
||||
],
|
||||
"version": "==2.19"
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a",
|
||||
"sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d"
|
||||
],
|
||||
"version": "==2.3.1"
|
||||
},
|
||||
"pylint": {
|
||||
"hashes": [
|
||||
"sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09",
|
||||
"sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.3.1"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c",
|
||||
"sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95",
|
||||
"sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2",
|
||||
"sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4",
|
||||
"sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad",
|
||||
"sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba",
|
||||
"sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1",
|
||||
"sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e",
|
||||
"sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673",
|
||||
"sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13",
|
||||
"sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19"
|
||||
],
|
||||
"version": "==5.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||
],
|
||||
"version": "==1.12.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
|
||||
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
|
||||
],
|
||||
"version": "==0.10.0"
|
||||
},
|
||||
"tox": {
|
||||
"hashes": [
|
||||
"sha256:69620e19de33a6b7ee8aeda5478791b3618ff58f0b869dbd0319fb71aa903deb",
|
||||
"sha256:e5cdb1653aa27b3e46b5c390de6b6d51d31afcfdbd9d1222d82d76b82ad03d9b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.8.6"
|
||||
},
|
||||
"typed-ast": {
|
||||
"hashes": [
|
||||
"sha256:035a54ede6ce1380599b2ce57844c6554666522e376bd111eb940fbc7c3dad23",
|
||||
"sha256:037c35f2741ce3a9ac0d55abfcd119133cbd821fffa4461397718287092d9d15",
|
||||
"sha256:049feae7e9f180b64efacbdc36b3af64a00393a47be22fa9cb6794e68d4e73d3",
|
||||
"sha256:19228f7940beafc1ba21a6e8e070e0b0bfd1457902a3a81709762b8b9039b88d",
|
||||
"sha256:2ea681e91e3550a30c2265d2916f40a5f5d89b59469a20f3bad7d07adee0f7a6",
|
||||
"sha256:3a6b0a78af298d82323660df5497bcea0f0a4a25a0b003afd0ce5af049bd1f60",
|
||||
"sha256:5385da8f3b801014504df0852bf83524599df890387a3c2b17b7caa3d78b1773",
|
||||
"sha256:606d8afa07eef77280c2bf84335e24390055b478392e1975f96286d99d0cb424",
|
||||
"sha256:69245b5b23bbf7fb242c9f8f08493e9ecd7711f063259aefffaeb90595d62287",
|
||||
"sha256:6f6d839ab09830d59b7fa8fb6917023d8cb5498ee1f1dbd82d37db78eb76bc99",
|
||||
"sha256:730888475f5ac0e37c1de4bd05eeb799fdb742697867f524dc8a4cd74bcecc23",
|
||||
"sha256:9819b5162ffc121b9e334923c685b0d0826154e41dfe70b2ede2ce29034c71d8",
|
||||
"sha256:9e60ef9426efab601dd9aa120e4ff560f4461cf8442e9c0a2b92548d52800699",
|
||||
"sha256:af5fbdde0690c7da68e841d7fc2632345d570768ea7406a9434446d7b33b0ee1",
|
||||
"sha256:b64efdbdf3bbb1377562c179f167f3bf301251411eb5ac77dec6b7d32bcda463",
|
||||
"sha256:bac5f444c118aeb456fac1b0b5d14c6a71ea2a42069b09c176f75e9bd4c186f6",
|
||||
"sha256:bda9068aafb73859491e13b99b682bd299c1b5fd50644d697533775828a28ee0",
|
||||
"sha256:d659517ca116e6750101a1326107d3479028c5191f0ecee3c7203c50f5b915b0",
|
||||
"sha256:eddd3fb1f3e0f82e5915a899285a39ee34ce18fd25d89582bc89fc9fb16cd2c6"
|
||||
],
|
||||
"markers": "implementation_name == 'cpython'",
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417",
|
||||
"sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39"
|
||||
],
|
||||
"version": "==16.4.3"
|
||||
},
|
||||
"wcwidth": {
|
||||
"hashes": [
|
||||
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
|
||||
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
|
||||
],
|
||||
"version": "==0.1.7"
|
||||
},
|
||||
"wrapt": {
|
||||
"hashes": [
|
||||
"sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
|
||||
],
|
||||
"version": "==1.11.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478",
|
||||
"sha256:682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4"
|
||||
],
|
||||
"version": "==0.3.3"
|
||||
}
|
||||
}
|
||||
}
|
190
README.md
190
README.md
@ -2,7 +2,161 @@
|
||||
|
||||
[![Build Status](https://travis-ci.org/cmehay/docker-tor-hidden-service.svg?branch=master)](https://travis-ci.org/cmehay/docker-tor-hidden-service)
|
||||
|
||||
Create a tor hidden service with a link
|
||||
## Setup
|
||||
|
||||
### Setup hosts
|
||||
|
||||
From 2019, new conf to handle tor v3 address has been added. Here an example with `docker-compose` v2+:
|
||||
|
||||
```yaml
|
||||
version: "2"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service:0.3.5.8
|
||||
links:
|
||||
- hello
|
||||
- world
|
||||
- again
|
||||
environment:
|
||||
# Set mapping ports
|
||||
HELLO_TOR_SERVICE_HOSTS: 80:hello:80,800:hello:80,8888:hello:80
|
||||
# Set private key
|
||||
HELLO_TOR_SERVIVE_KEY: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
|
||||
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
|
||||
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
|
||||
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
|
||||
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
|
||||
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
|
||||
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
|
||||
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
|
||||
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
|
||||
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
|
||||
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
|
||||
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
|
||||
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
# hello and again will share the same onion v3 address
|
||||
FOO_TOR_SERVICE_HOSTS: 88:again:80,8000:world:80
|
||||
FOO_TOR_SERVICE_VERSION: '3'
|
||||
# tor v3 address private key base 64 encoded
|
||||
FOO_TOR_SERVICE_KEY: |
|
||||
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++
|
||||
j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
|
||||
|
||||
hello:
|
||||
image: tutum/hello-world
|
||||
hostname: hello
|
||||
|
||||
world:
|
||||
image: tutum/hello-world
|
||||
hostname: world
|
||||
|
||||
again:
|
||||
image: tutum/hello-world
|
||||
hostname: again
|
||||
```
|
||||
|
||||
This configuration will output:
|
||||
|
||||
```
|
||||
foo: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88, xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000
|
||||
hello: 5azvyr7dvvr4cldn.onion:80, 5azvyr7dvvr4cldn.onion:800, 5azvyr7dvvr4cldn.onion:8888
|
||||
```
|
||||
|
||||
#### Environment variables
|
||||
|
||||
##### `{SERVICE}_TOR_SERVICE_HOSTS`
|
||||
|
||||
The config patern for this variable is: `{exposed_port}:{hostname}:{port}}`
|
||||
|
||||
For example `80:hello:8080` will expose a onion service on port 80 to the port 8080 of hello hostname.
|
||||
|
||||
You can concatenate services using comas.
|
||||
|
||||
##### `{SERVICE}_TOR_SERVICE_VERSION`
|
||||
|
||||
Can be `2` or `3`. Set the tor address type.
|
||||
|
||||
`2` gives short addresses `5azvyr7dvvr4cldn.onion` and `3` long addresses `xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion`
|
||||
|
||||
|
||||
##### `{SERVICE}_TOR_SERVICE_KEY`
|
||||
|
||||
You can set the private key for the current service.
|
||||
|
||||
Tor v2 addresses uses RSA PEM keys like:
|
||||
```
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
|
||||
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
|
||||
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
|
||||
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
|
||||
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
|
||||
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
|
||||
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
|
||||
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
|
||||
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
|
||||
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
|
||||
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
|
||||
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
|
||||
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
```
|
||||
|
||||
Tor v3 addresses uses ed25519 binary keys. It should be base64 encoded:
|
||||
```
|
||||
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
|
||||
```
|
||||
#### Secrets
|
||||
|
||||
Secret key can be set through docker `secrets`, see `docker-compose.v3.yml` for example.
|
||||
|
||||
|
||||
### Tools
|
||||
|
||||
A command line tool `onions` is available in container to get `.onion` url when container is running.
|
||||
|
||||
```sh
|
||||
# Get services
|
||||
$ docker exec -ti torhiddenproxy_tor_1 onions
|
||||
hello: vegm3d7q64gutl75.onion:80
|
||||
world: b2sflntvdne63amj.onion:80
|
||||
|
||||
# Get json
|
||||
$ docker exec -ti torhiddenproxy_tor_1 onions --json
|
||||
{"hello": ["b2sflntvdne63amj.onion:80"], "world": ["vegm3d7q64gutl75.onion:80"]}
|
||||
```
|
||||
|
||||
### Auto reload
|
||||
|
||||
Changing `/etc/tor/torrc` file triggers a `SIGHUP` signal to `tor` to reload configuration.
|
||||
|
||||
To disable this behavior, add `ENTRYPOINT_DISABLE_RELOAD` in environment.
|
||||
|
||||
### Versions
|
||||
|
||||
Container version will follow tor release versions.
|
||||
|
||||
### pyentrypoint
|
||||
|
||||
This container uses [`pyentrypoint`](https://github.com/cmehay/pyentrypoint) to generate its setup.
|
||||
|
||||
If you need to use the legacy version, please checkout the `legacy` branch or pull `goldy/tor-hidden-service:legacy`.
|
||||
|
||||
### pytor
|
||||
|
||||
This containner uses [`pytor`](https://github.com/cmehay/pytor) to mannages tor cryptography, generate keys and compute onion urls.
|
||||
|
||||
|
||||
# Legacy deprecated doc
|
||||
|
||||
ALL THE DOC BELLOW IS LEGACY, IT'S STILL WORKING BUT IT'S NOT RECOMMENDED ANYMORE AND COULD BE DROPPED IN FUTURE RELEASES.
|
||||
|
||||
### Create a tor hidden service with a link
|
||||
|
||||
```sh
|
||||
# run a container with a network application
|
||||
@ -22,8 +176,6 @@ $ docker run -ti --link something --volume /path/to/keys:/var/lib/tor/hidden_ser
|
||||
|
||||
Look at the `docker-compose.yml` file to see how to use it.
|
||||
|
||||
## Setup
|
||||
|
||||
### Set private key
|
||||
|
||||
Private key is settable by environment or by copying file in `hostname/private_key` in docket volume (`hostname` is the link name).
|
||||
@ -127,35 +279,3 @@ Links setting are required when using docker-compose v2. See `docker-compose.v2.
|
||||
### Copose v3 support and secrets
|
||||
|
||||
Links setting are required when using docker-compose v3. See `docker-compose.v3.yml` for example.
|
||||
|
||||
#### Secrets
|
||||
|
||||
Secret key can be set through docker `secrets`, see `docker-compose.v3.yml` for example.
|
||||
|
||||
### Tools
|
||||
|
||||
A command line tool `onions` is available in container to get `.onion` url when container is running.
|
||||
|
||||
```sh
|
||||
# Get services
|
||||
$ docker exec -ti torhiddenproxy_tor_1 onions
|
||||
hello: vegm3d7q64gutl75.onion:80
|
||||
world: b2sflntvdne63amj.onion:80
|
||||
|
||||
# Get json
|
||||
$ docker exec -ti torhiddenproxy_tor_1 onions --json
|
||||
{"hello": ["b2sflntvdne63amj.onion:80"], "world": ["vegm3d7q64gutl75.onion:80"]}
|
||||
```
|
||||
|
||||
### Auto reload
|
||||
|
||||
Changing `/etc/tor/torrc` file trigger a `SIGHUP` signal to `tor` to reload configuration.
|
||||
|
||||
To disable this behavior, add `ENTRYPOINT_DISABLE_RELOAD` in environment.
|
||||
|
||||
|
||||
### pyentrypoint
|
||||
|
||||
This container is using [`pyentrypoint`](https://github.com/cmehay/pyentrypoint) to generate its setup.
|
||||
|
||||
If you need to use the legacy version, please checkout the `legacy` branch or pull `goldy/tor-hidden-service:legacy`.
|
||||
|
@ -7,11 +7,13 @@ secret_env:
|
||||
- '*_KEY'
|
||||
- '*_PORTS'
|
||||
- '*_SERVICE_NAME'
|
||||
- '*_TOR_SERVICE_*'
|
||||
|
||||
pre_conf_commands:
|
||||
- onions --setup-hosts
|
||||
|
||||
post_conf_commands:
|
||||
- chmod -R 700 $HOME
|
||||
- chown -R tor:tor $HOME
|
||||
|
||||
reload:
|
||||
|
@ -3,6 +3,7 @@ import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from base64 import b64decode
|
||||
from json import dumps
|
||||
from re import match
|
||||
|
||||
@ -46,6 +47,10 @@ class Setup(object):
|
||||
assert len(key) > 800
|
||||
self.setup[host]['key'] = key
|
||||
|
||||
def _load_keys_in_services(self):
|
||||
for service in self.services:
|
||||
service.load_key()
|
||||
|
||||
def _get_service(self, host, service):
|
||||
self._add_host(host)
|
||||
self.setup[host]['service'] = service
|
||||
@ -66,30 +71,39 @@ class Setup(object):
|
||||
if service:
|
||||
return service
|
||||
|
||||
def add_empty_group(self, name):
|
||||
def add_empty_group(self, name, version=None):
|
||||
if self.find_group_by_name(name):
|
||||
raise Exception('Group {name} already exists'.format(name=name))
|
||||
group = ServicesGroup(name=name)
|
||||
group = ServicesGroup(name=name, version=version)
|
||||
self.services.append(group)
|
||||
return group
|
||||
|
||||
def add_new_service(self, host, name=None, ports=None, key=None):
|
||||
def add_new_service(self,
|
||||
host,
|
||||
name=None,
|
||||
ports=None,
|
||||
key=None):
|
||||
group = self.find_group_by_name(name)
|
||||
service = self.find_service_by_host(host)
|
||||
if group:
|
||||
service = group.get_service_by_host(host)
|
||||
else:
|
||||
service = self.find_service_by_host(host)
|
||||
if not service:
|
||||
service = Service(host=host)
|
||||
if not group:
|
||||
group = ServicesGroup(
|
||||
service=service,
|
||||
name=name,
|
||||
hidden_service_dir=self.hidden_service_dir
|
||||
hidden_service_dir=self.hidden_service_dir,
|
||||
)
|
||||
else:
|
||||
group.add_service(service)
|
||||
if group not in self.services:
|
||||
self.services.append(group)
|
||||
elif group and service not in group.services:
|
||||
group.add_service(service)
|
||||
else:
|
||||
group = self.find_group_by_service(service)
|
||||
self.find_group_by_service(service)
|
||||
if key:
|
||||
group.add_key(key)
|
||||
if ports:
|
||||
@ -108,22 +122,69 @@ class Setup(object):
|
||||
self.add_new_service(host=host, ports=ports)
|
||||
|
||||
def _set_key(self, host, key):
|
||||
self.add_new_service(host=host, key=key)
|
||||
self.add_new_service(host=host, key=key.encode())
|
||||
|
||||
def _setup_from_env(self):
|
||||
match_map = (
|
||||
(r'([A-Z0-9]*)_PORTS', self._set_ports),
|
||||
(r'([A-Z0-9]*)_KEY', self._set_key),
|
||||
)
|
||||
for key, val in os.environ.items():
|
||||
for reg, call in match_map:
|
||||
def _setup_from_env(self, match_map):
|
||||
for reg, call in match_map:
|
||||
for key, val in os.environ.items():
|
||||
m = match(reg, key)
|
||||
if m:
|
||||
call(m.groups()[0].lower(), val)
|
||||
|
||||
def _setup_keys_and_ports_from_env(self):
|
||||
self._setup_from_env(
|
||||
(
|
||||
(r'([A-Z0-9]+)_PORTS', self._set_ports),
|
||||
(r'([A-Z0-9]+)_KEY', self._set_key),
|
||||
)
|
||||
)
|
||||
|
||||
def get_or_create_empty_group(self, name, version=None):
|
||||
group = self.find_group_by_name(name)
|
||||
if group:
|
||||
if version:
|
||||
group.set_version(version)
|
||||
return group
|
||||
return self.add_empty_group(name, version)
|
||||
|
||||
def _set_group_version(self, name, version):
|
||||
'Setup groups with version'
|
||||
group = self.get_or_create_empty_group(name, version=version)
|
||||
group.set_version(version)
|
||||
|
||||
def _set_group_key(self, name, key):
|
||||
'Set key for service group'
|
||||
group = self.get_or_create_empty_group(name)
|
||||
if group.version == 3:
|
||||
group.add_key(b64decode(key))
|
||||
else:
|
||||
group.add_key(key)
|
||||
|
||||
def _set_group_hosts(self, name, hosts):
|
||||
'Set services for service groups'
|
||||
self.get_or_create_empty_group(name)
|
||||
for host_map in hosts.split(','):
|
||||
host_map = host_map.strip()
|
||||
port_from, host, port_dest = host_map.split(':', 2)
|
||||
if host == 'unix' and port_dest.startswith('/'):
|
||||
self.add_new_service(host=name, name=name, ports=host_map)
|
||||
else:
|
||||
ports = '{frm}:{dst}'.format(frm=port_from, dst=port_dest)
|
||||
self.add_new_service(host=host, name=name, ports=ports)
|
||||
|
||||
def _setup_services_from_env(self):
|
||||
self._setup_from_env(
|
||||
(
|
||||
(r'([A-Z0-9]+)_TOR_SERVICE_VERSION', self._set_group_version),
|
||||
(r'([A-Z0-9]+)_TOR_SERVICE_KEY', self._set_group_key),
|
||||
(r'([A-Z0-9]+)_TOR_SERVICE_HOSTS', self._set_group_hosts),
|
||||
)
|
||||
)
|
||||
|
||||
def _get_setup_from_env(self):
|
||||
self._set_service_names()
|
||||
self._setup_from_env()
|
||||
self._setup_keys_and_ports_from_env()
|
||||
self._setup_services_from_env()
|
||||
|
||||
def _get_setup_from_links(self):
|
||||
containers = DockerLinks().to_containers()
|
||||
@ -162,6 +223,7 @@ class Setup(object):
|
||||
self.setup = {}
|
||||
self._get_setup_from_env()
|
||||
self._get_setup_from_links()
|
||||
self._load_keys_in_services()
|
||||
self.check_services()
|
||||
self.apply_conf()
|
||||
|
||||
@ -201,38 +263,65 @@ class Onions(Setup):
|
||||
|
||||
def torrc_parser(self):
|
||||
|
||||
self.torrc_dict = {}
|
||||
|
||||
def parse_dir(line):
|
||||
_, path = line.split()
|
||||
group_name = os.path.basename(path)
|
||||
group = (self.find_group_by_name(group_name)
|
||||
or self.add_empty_group(group_name))
|
||||
return group
|
||||
self.torrc_dict[group_name] = {
|
||||
'services': [],
|
||||
}
|
||||
return group_name
|
||||
|
||||
def parse_port(line, service_group):
|
||||
def parse_port(line, name):
|
||||
_, port_from, dest = line.split()
|
||||
service_host, port = dest.split(':')
|
||||
ports_str = '{port_from}:{dest}'
|
||||
name = service_host
|
||||
ports_param = ports_str.format(port_from=port_from,
|
||||
dest=port)
|
||||
if port.startswith('/'):
|
||||
name = service_group.name
|
||||
service_host = name
|
||||
ports_param = ports_str.format(port_from=port_from,
|
||||
dest=dest)
|
||||
service = (service_group.get_service_by_host(name)
|
||||
or Service(name))
|
||||
service.add_ports(ports_param)
|
||||
if service not in service_group.services:
|
||||
service_group.add_service(service)
|
||||
self.torrc_dict[name]['services'].append({
|
||||
'host': service_host,
|
||||
'ports': ports_param,
|
||||
})
|
||||
|
||||
def parse_version(line, name):
|
||||
_, version = line.split()
|
||||
self.torrc_dict[name]['version'] = int(version)
|
||||
|
||||
def setup_services():
|
||||
for name, setup in self.torrc_dict.items():
|
||||
version = setup.get('version', 2)
|
||||
group = (self.find_group_by_name(name)
|
||||
or self.add_empty_group(name, version=version))
|
||||
for service_dict in setup.get('services', []):
|
||||
host = service_dict['host']
|
||||
service = (group.get_service_by_host(host)
|
||||
or Service(host))
|
||||
service.add_ports(service_dict['ports'])
|
||||
if service not in group.services:
|
||||
group.add_service(service)
|
||||
self._load_keys_in_services()
|
||||
|
||||
if not os.path.exists(self.torrc):
|
||||
return
|
||||
with open(self.torrc, 'r') as f:
|
||||
for line in f.readlines():
|
||||
if line.startswith('HiddenServiceDir'):
|
||||
service_group = parse_dir(line)
|
||||
if line.startswith('HiddenServicePort'):
|
||||
parse_port(line, service_group)
|
||||
try:
|
||||
with open(self.torrc, 'r') as f:
|
||||
for line in f.readlines():
|
||||
if line.startswith('HiddenServiceDir'):
|
||||
name = parse_dir(line)
|
||||
if line.startswith('HiddenServicePort'):
|
||||
parse_port(line, name)
|
||||
if line.startswith('HiddenServiceVersion'):
|
||||
parse_version(line, name)
|
||||
except BaseException:
|
||||
raise Exception(
|
||||
'Fail to parse torrc file. Please check the file'
|
||||
)
|
||||
setup_services()
|
||||
|
||||
def __str__(self):
|
||||
if not self.services:
|
||||
@ -257,6 +346,7 @@ def main():
|
||||
help='Setup hosts')
|
||||
|
||||
args = parser.parse_args()
|
||||
logging.getLogger().setLevel(logging.WARNING)
|
||||
try:
|
||||
onions = Onions()
|
||||
if args.setup:
|
||||
@ -264,6 +354,7 @@ def main():
|
||||
else:
|
||||
onions.torrc_parser()
|
||||
except BaseException as e:
|
||||
logging.exception(e)
|
||||
error_msg = str(e)
|
||||
else:
|
||||
error_msg = None
|
||||
@ -271,7 +362,6 @@ def main():
|
||||
if error_msg:
|
||||
print(dumps({'error': error_msg}))
|
||||
sys.exit(1)
|
||||
logging.getLogger().setLevel(logging.ERROR)
|
||||
print(onions.to_json())
|
||||
else:
|
||||
if error_msg:
|
||||
|
@ -1,42 +1,67 @@
|
||||
'This class define a service link'
|
||||
import base64
|
||||
import binascii
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
from base64 import b32encode
|
||||
from hashlib import sha1
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from pytor import OnionV2
|
||||
from pytor import OnionV3
|
||||
|
||||
|
||||
class ServicesGroup(object):
|
||||
|
||||
name = None
|
||||
_priv_key = None
|
||||
_key_in_secrets = False
|
||||
version = None
|
||||
imported_key = False
|
||||
_default_version = 2
|
||||
_imported_key = False
|
||||
_onion = None
|
||||
_hidden_service_dir = "/var/lib/tor/hidden_service/"
|
||||
|
||||
hidden_service_dir = "/var/lib/tor/hidden_service/"
|
||||
|
||||
def __init__(self, name=None, service=None, hidden_service_dir=None):
|
||||
def __init__(self,
|
||||
name=None,
|
||||
service=None,
|
||||
version=None,
|
||||
hidden_service_dir=None):
|
||||
|
||||
name_regex = r'^[a-zA-Z0-9-_]+$'
|
||||
|
||||
self.hidden_service_dir = hidden_service_dir or self.hidden_service_dir
|
||||
self.onion_map = {
|
||||
2: OnionV2,
|
||||
3: OnionV3,
|
||||
}
|
||||
|
||||
if not name and not service:
|
||||
raise Exception(
|
||||
'Init service group with a name or service at least'
|
||||
)
|
||||
self.services = []
|
||||
self.name = name or service.host
|
||||
if hidden_service_dir:
|
||||
self._hidden_service_dir = hidden_service_dir
|
||||
if not re.match(name_regex, self.name):
|
||||
raise Exception(
|
||||
'Group {name} has invalid name'.format(name=self.name)
|
||||
)
|
||||
if service:
|
||||
self.add_service(service)
|
||||
self.set_version(version or self._default_version)
|
||||
self.gen_key()
|
||||
|
||||
self.load_key()
|
||||
if not self._priv_key:
|
||||
self.gen_key()
|
||||
def set_version(self, version):
|
||||
version = int(version)
|
||||
if version not in self.onion_map:
|
||||
raise Exception(
|
||||
'Url version {version} is not supported'.format(version)
|
||||
)
|
||||
self.version = version
|
||||
self._onion = self.onion_map[version]()
|
||||
|
||||
@property
|
||||
def hidden_service_dir(self):
|
||||
return os.path.join(self._hidden_service_dir, self.name)
|
||||
|
||||
def add_service(self, service):
|
||||
if service not in self.services:
|
||||
@ -50,15 +75,22 @@ class ServicesGroup(object):
|
||||
return service
|
||||
|
||||
def add_key(self, key):
|
||||
if self._key_in_secrets:
|
||||
if self._imported_key:
|
||||
logging.warning('Secret key already set, overriding')
|
||||
self._priv_key = key
|
||||
self._key_in_secrets = False
|
||||
# Try to decode key from base64 encoding
|
||||
# import the raw data if the input cannot be decoded as base64
|
||||
try:
|
||||
key = base64.b64decode(key)
|
||||
except binascii.Error:
|
||||
pass
|
||||
self._onion.set_private_key(key)
|
||||
self._imported_key = True
|
||||
|
||||
def __iter__(self):
|
||||
yield 'name', self.name
|
||||
yield 'onion', self.onion_url
|
||||
yield 'urls', list(self.urls)
|
||||
yield 'version', self.version
|
||||
|
||||
def __str__(self):
|
||||
return '{name}: {urls}'.format(name=self.name,
|
||||
@ -66,16 +98,7 @@ class ServicesGroup(object):
|
||||
|
||||
@property
|
||||
def onion_url(self):
|
||||
"Get onion url from private key"
|
||||
|
||||
# Convert private RSA to public DER
|
||||
priv = RSA.importKey(self._priv_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())
|
||||
return self._onion.onion_hostname
|
||||
|
||||
@property
|
||||
def urls(self):
|
||||
@ -88,30 +111,17 @@ class ServicesGroup(object):
|
||||
'Write key on disk and set tor service'
|
||||
if not hidden_service_dir:
|
||||
hidden_service_dir = self.hidden_service_dir
|
||||
serv_dir = os.path.join(hidden_service_dir, self.name)
|
||||
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(self._priv_key)
|
||||
os.fchmod(f.fileno(), 0o600)
|
||||
with open(os.path.join(serv_dir, 'hostname'), 'w') as f:
|
||||
f.write(self.onion_url)
|
||||
if not os.path.isdir(hidden_service_dir):
|
||||
pathlib.Path(hidden_service_dir).mkdir(parents=True)
|
||||
self._onion.write_hidden_service(hidden_service_dir, force=True)
|
||||
|
||||
def _load_key(self, key_file):
|
||||
if os.path.exists(key_file):
|
||||
with open(key_file, 'r') as f:
|
||||
key = f.read().encode()
|
||||
if not len(key):
|
||||
return
|
||||
try:
|
||||
rsa = RSA.importKey(key)
|
||||
self._priv_key = rsa.exportKey("PEM").decode()
|
||||
except BaseException:
|
||||
raise('Fail to load key for {name} services'.format(
|
||||
name=self.name
|
||||
))
|
||||
with open(key_file, 'rb') as f:
|
||||
self._onion.set_private_key_from_file(f)
|
||||
|
||||
def load_key(self):
|
||||
def load_key(self, override=False):
|
||||
if self._imported_key and not override:
|
||||
return
|
||||
self.load_key_from_secrets()
|
||||
self.load_key_from_conf()
|
||||
|
||||
@ -122,8 +132,9 @@ class ServicesGroup(object):
|
||||
return
|
||||
try:
|
||||
self._load_key(secret_file)
|
||||
self._key_in_secrets = True
|
||||
except BaseException:
|
||||
self._imported_key = True
|
||||
except BaseException as e:
|
||||
logging.exception(e)
|
||||
logging.warning('Fail to load key from secret, '
|
||||
'check the key or secret name collision')
|
||||
|
||||
@ -131,16 +142,17 @@ class ServicesGroup(object):
|
||||
'Load key from disk if exists'
|
||||
if not hidden_service_dir:
|
||||
hidden_service_dir = self.hidden_service_dir
|
||||
key_file = os.path.join(hidden_service_dir,
|
||||
self.name,
|
||||
'private_key')
|
||||
self._load_key(key_file)
|
||||
if not os.path.isdir(hidden_service_dir):
|
||||
return
|
||||
self._onion.load_hidden_service(hidden_service_dir)
|
||||
|
||||
def gen_key(self):
|
||||
'Generate new 1024 bits RSA key for hidden service'
|
||||
self._priv_key = RSA.generate(
|
||||
bits=1024,
|
||||
).exportKey("PEM").decode()
|
||||
self.imported_key = False
|
||||
return self._onion.gen_new_private_key()
|
||||
|
||||
@property
|
||||
def _priv_key(self):
|
||||
return self._onion.get_private_key()
|
||||
|
||||
|
||||
class Ports:
|
||||
|
@ -6,7 +6,7 @@ from setuptools import setup
|
||||
setup(
|
||||
name='onions',
|
||||
|
||||
version='0.4.1',
|
||||
version='0.5.0',
|
||||
|
||||
packages=find_packages(),
|
||||
|
||||
@ -31,10 +31,9 @@ setup(
|
||||
"Topic :: System :: Installation/Setup",
|
||||
],
|
||||
|
||||
install_requires=['pyentrypoint==0.5.1',
|
||||
'Jinja2>=2.8',
|
||||
'pycrypto', ],
|
||||
|
||||
install_requires=['pyentrypoint==0.5.2',
|
||||
'Jinja2>=2.10',
|
||||
'pytor>=0.1.2'],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'onions = onions:main',
|
||||
|
@ -2,6 +2,7 @@ import json
|
||||
import os
|
||||
import re
|
||||
from base64 import b32encode
|
||||
from base64 import b64decode
|
||||
from hashlib import sha1
|
||||
|
||||
import pytest
|
||||
@ -9,8 +10,9 @@ from Crypto.PublicKey import RSA
|
||||
from onions import Onions
|
||||
|
||||
|
||||
def get_key_and_onion():
|
||||
key = '''
|
||||
def get_key_and_onion(version=2):
|
||||
key = {}
|
||||
key[2] = '''
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQCsMP4gl6g1Q313miPhb1GnDr56ZxIWGsO2PwHM1infkbhlBakR
|
||||
6DGQfpE31L1ZKTUxY0OexKbW088v8qCOfjD9Zk1i80JP4xzfWQcwFZ5yM/0fkhm3
|
||||
@ -27,24 +29,40 @@ La/7Syrnobngsh/vX90CQB+PSSBqiPSsK2yPz6Gsd6OLCQ9sdy2oRwFTasH8sZyl
|
||||
bhJ3M9WzP/EMkAzyW8mVs1moFp3hRcfQlZHl6g1U9D8=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
'''
|
||||
|
||||
onion = b32encode(
|
||||
onion = {}
|
||||
pub = {}
|
||||
onion[2] = b32encode(
|
||||
sha1(
|
||||
RSA.importKey(
|
||||
key.strip()
|
||||
key[2].strip()
|
||||
).publickey().exportKey(
|
||||
"DER"
|
||||
)[22:]
|
||||
).digest()[:10]
|
||||
).decode().lower() + '.onion'
|
||||
|
||||
return key.strip(), onion
|
||||
key[3] = '''
|
||||
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++j96H1X/gq14N
|
||||
wLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
|
||||
'''
|
||||
|
||||
pub[3] = '''
|
||||
PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAAC9kzftiea/kb+TWlCEVNpfUJLVk+rFIoMG
|
||||
m9/hW13isA==
|
||||
'''
|
||||
|
||||
onion[3] = 'xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion'
|
||||
|
||||
return key[version].strip(), onion[version]
|
||||
|
||||
|
||||
def get_torrc_template():
|
||||
return r'''
|
||||
{% for service_group in services %}
|
||||
HiddenServiceDir /var/lib/tor/hidden_service/{{service_group.name}}
|
||||
HiddenServiceDir {{service_group.hidden_service_dir}}
|
||||
{% if service_group.version == 3 %}
|
||||
HiddenServiceVersion 3
|
||||
{% endif %}
|
||||
{% for service in service_group.services %}
|
||||
{% for port in service.ports %}
|
||||
{% if port.is_socket %}
|
||||
@ -155,7 +173,7 @@ ff02::2 ip6-allrouters
|
||||
172.17.0.2 compose_service1_1 bf447f22cdba
|
||||
'''.strip()
|
||||
|
||||
fs.CreateFile('/etc/hosts', contents=etc_host)
|
||||
fs.create_file('/etc/hosts', contents=etc_host)
|
||||
|
||||
monkeypatch.setattr(os, 'environ', env)
|
||||
|
||||
@ -190,34 +208,57 @@ def test_key(monkeypatch):
|
||||
assert onion.services[0].onion_url == onion_url
|
||||
|
||||
|
||||
def test_key_in_secret(fs, monkeypatch):
|
||||
def test_key_v3(monkeypatch):
|
||||
key, onion_url = get_key_and_onion(version=3)
|
||||
env = {
|
||||
'SERVICE1_SERVICE_NAME': 'group1',
|
||||
'SERVICE2_SERVICE_NAME': 'group1',
|
||||
'SERVICE3_SERVICE_NAME': 'group2',
|
||||
'SERVICE1_PORTS': '80:80',
|
||||
'SERVICE2_PORTS': '81:80,82:8000',
|
||||
'SERVICE3_PORTS': '80:unix://unix.socket',
|
||||
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80,81:service2:80',
|
||||
'GROUP1_TOR_SERVICE_VERSION': '3',
|
||||
'GROUP1_TOR_SERVICE_KEY': key,
|
||||
}
|
||||
|
||||
monkeypatch.setattr(os, 'environ', env)
|
||||
|
||||
key, onion_url = get_key_and_onion()
|
||||
onion = Onions()
|
||||
onion._get_setup_from_env()
|
||||
onion._load_keys_in_services()
|
||||
|
||||
fs.CreateFile('/run/secrets/group1', contents=key)
|
||||
assert len(os.environ) == 3
|
||||
assert len(onion.services) == 1
|
||||
|
||||
assert onion.services[0].onion_url == onion_url
|
||||
|
||||
|
||||
def test_key_in_secret(fs, monkeypatch):
|
||||
env = {
|
||||
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80',
|
||||
'GROUP2_TOR_SERVICE_HOSTS': '80:service2:80',
|
||||
'GROUP3_TOR_SERVICE_HOSTS': '80:service3:80',
|
||||
'GROUP3_TOR_SERVICE_VERSION': '3',
|
||||
}
|
||||
|
||||
monkeypatch.setattr(os, 'environ', env)
|
||||
|
||||
key_v2, onion_url_v2 = get_key_and_onion()
|
||||
key_v3, onion_url_v3 = get_key_and_onion(version=3)
|
||||
|
||||
fs.create_file('/run/secrets/group1', contents=key_v2)
|
||||
fs.create_file('/run/secrets/group3', contents=b64decode(key_v3))
|
||||
|
||||
onion = Onions()
|
||||
onion._get_setup_from_env()
|
||||
onion._load_keys_in_services()
|
||||
|
||||
group1 = onion.find_group_by_name('group1')
|
||||
group2 = onion.find_group_by_name('group2')
|
||||
group3 = onion.find_group_by_name('group3')
|
||||
|
||||
# assert group._priv_key == key
|
||||
assert group1.onion_url == onion_url
|
||||
assert group2.onion_url != onion_url
|
||||
assert group1.onion_url == onion_url_v2
|
||||
assert group2.onion_url not in [onion_url_v2, onion_url_v3]
|
||||
assert group3.onion_url == onion_url_v3
|
||||
|
||||
|
||||
def test_configuration(fs, monkeypatch):
|
||||
def test_configuration(fs, monkeypatch, tmpdir):
|
||||
|
||||
env = {
|
||||
'SERVICE1_SERVICE_NAME': 'group1',
|
||||
'SERVICE2_SERVICE_NAME': 'group1',
|
||||
@ -225,44 +266,72 @@ def test_configuration(fs, monkeypatch):
|
||||
'SERVICE1_PORTS': '80:80',
|
||||
'SERVICE2_PORTS': '81:80,82:8000',
|
||||
'SERVICE3_PORTS': '80:unix://unix.socket',
|
||||
'GROUP3_TOR_SERVICE_VERSION': '2',
|
||||
'GROUP3_TOR_SERVICE_HOSTS': '80:service4:888,81:service5:8080',
|
||||
'GROUP4_TOR_SERVICE_VERSION': '3',
|
||||
'GROUP4_TOR_SERVICE_HOSTS': '81:unix://unix2.sock',
|
||||
'GROUP3V3_TOR_SERVICE_VERSION': '3',
|
||||
'GROUP3V3_TOR_SERVICE_HOSTS': '80:service4:888,81:service5:8080',
|
||||
'SERVICE5_TOR_SERVICE_HOSTS': '80:service5:80'
|
||||
}
|
||||
|
||||
hidden_dir = '/var/lib/tor/hidden_service'
|
||||
|
||||
monkeypatch.setattr(os, 'environ', env)
|
||||
monkeypatch.setattr(os, 'fchmod', lambda x, y: None)
|
||||
|
||||
key, onion_url = get_key_and_onion()
|
||||
torrc_tpl = get_torrc_template()
|
||||
|
||||
fs.CreateFile('/var/local/tor/torrc.tpl', contents=torrc_tpl)
|
||||
fs.CreateFile('/etc/tor/torrc')
|
||||
fs.create_file('/var/local/tor/torrc.tpl', contents=torrc_tpl)
|
||||
fs.create_file('/etc/tor/torrc')
|
||||
fs.create_dir(hidden_dir)
|
||||
|
||||
onion = Onions()
|
||||
onion._get_setup_from_env()
|
||||
onion._load_keys_in_services()
|
||||
onion.apply_conf()
|
||||
|
||||
onions_urls = {}
|
||||
for dir in os.listdir(hidden_dir):
|
||||
with open(os.path.join(hidden_dir, dir, 'hostname'), 'r') as f:
|
||||
onions_urls[dir] = f.read().strip()
|
||||
|
||||
with open('/etc/tor/torrc', 'r') as f:
|
||||
torrc = f.read()
|
||||
|
||||
print(torrc)
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group1' in torrc
|
||||
assert 'HiddenServicePort 80 service1:80' in torrc
|
||||
assert 'HiddenServicePort 81 service2:80' in torrc
|
||||
assert 'HiddenServicePort 82 service2:8000' in torrc
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group2' in torrc
|
||||
assert 'HiddenServicePort 80 unix://unix.socket' in torrc
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group3' in torrc
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group4' in torrc
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group3v3' in torrc
|
||||
assert 'HiddenServiceDir /var/lib/tor/hidden_service/service5' in torrc
|
||||
assert torrc.count('HiddenServicePort 80 service4:888') == 2
|
||||
assert torrc.count('HiddenServicePort 81 service5:8080') == 2
|
||||
assert torrc.count('HiddenServicePort 80 service5:80') == 1
|
||||
assert torrc.count('HiddenServicePort 81 unix://unix2.sock') == 1
|
||||
assert torrc.count('HiddenServiceVersion 3') == 2
|
||||
|
||||
# Check parser
|
||||
onion2 = Onions()
|
||||
onion2.torrc_parser()
|
||||
|
||||
assert len(onion2.services) == 2
|
||||
assert len(onion2.services) == 6
|
||||
|
||||
assert set(
|
||||
group.name for group in onion2.services
|
||||
) == set(['group1', 'group2'])
|
||||
# ) == set(['group1', 'group2'])
|
||||
) == set(['group1', 'group2', 'group3', 'group4', 'group3v3', 'service5'])
|
||||
|
||||
for group in onion2.services:
|
||||
if group.name == 'group1':
|
||||
assert len(group.services) == 2
|
||||
assert group.version == 2
|
||||
assert group.onion_url == onions_urls[group.name]
|
||||
assert set(
|
||||
service.host for service in group.services
|
||||
) == set(['service1', 'service2'])
|
||||
@ -279,6 +348,8 @@ def test_configuration(fs, monkeypatch):
|
||||
) == set([(81, 80), (82, 8000)])
|
||||
if group.name == 'group2':
|
||||
assert len(group.services) == 1
|
||||
assert group.version == 2
|
||||
assert group.onion_url == onions_urls[group.name]
|
||||
assert set(
|
||||
service.host for service in group.services
|
||||
) == set(['group2'])
|
||||
@ -288,6 +359,53 @@ def test_configuration(fs, monkeypatch):
|
||||
(port.port_from, port.dest) for port in service.ports
|
||||
) == set([(80, 'unix://unix.socket')])
|
||||
|
||||
if group.name in ['group3', 'group3v3']:
|
||||
assert len(group.services) == 2
|
||||
assert group.version == 2 if group.name == 'group3' else 3
|
||||
assert group.onion_url == onions_urls[group.name]
|
||||
assert set(
|
||||
service.host for service in group.services
|
||||
) == set(['service4', 'service5'])
|
||||
for service in group.services:
|
||||
if service.host == 'service4':
|
||||
assert len(service.ports) == 1
|
||||
assert set(
|
||||
(port.port_from, port.dest) for port in service.ports
|
||||
) == set([(80, 888)])
|
||||
if service.host == 'service5':
|
||||
assert len(service.ports) == 1
|
||||
assert set(
|
||||
(port.port_from, port.dest) for port in service.ports
|
||||
) == set([(81, 8080)])
|
||||
|
||||
if group.name == 'group4':
|
||||
assert len(group.services) == 1
|
||||
assert group.version == 3
|
||||
assert group.onion_url == onions_urls[group.name]
|
||||
assert set(
|
||||
service.host for service in group.services
|
||||
) == set(['group4'])
|
||||
for service in group.services:
|
||||
assert service.host == 'group4'
|
||||
assert len(service.ports) == 1
|
||||
assert set(
|
||||
(port.port_from, port.dest) for port in service.ports
|
||||
) == set([(81, 'unix://unix2.sock')])
|
||||
|
||||
if group.name == 'service5':
|
||||
assert len(group.services) == 1
|
||||
assert group.version == 2
|
||||
assert group.onion_url == onions_urls[group.name]
|
||||
assert set(
|
||||
service.host for service in group.services
|
||||
) == set(['service5'])
|
||||
for service in group.services:
|
||||
assert service.host == 'service5'
|
||||
assert len(service.ports) == 1
|
||||
assert set(
|
||||
(port.port_from, port.dest) for port in service.ports
|
||||
) == set([(80, 80)])
|
||||
|
||||
|
||||
def test_groups(monkeypatch):
|
||||
env = {
|
||||
|
@ -1,5 +1,8 @@
|
||||
{% for service_group in services %}
|
||||
HiddenServiceDir /var/lib/tor/hidden_service/{{service_group.name}}
|
||||
HiddenServiceDir {{service_group.hidden_service_dir}}
|
||||
{% if service_group.version == 3 %}
|
||||
HiddenServiceVersion 3
|
||||
{% endif %}
|
||||
{% for service in service_group.services %}
|
||||
{% for port in service.ports %}
|
||||
{% if port.is_socket %}
|
||||
|
11
docker-compose.build.yml
Normal file
11
docker-compose.build.yml
Normal file
@ -0,0 +1,11 @@
|
||||
# docker version 3 builder
|
||||
|
||||
version: "3.1"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
tor_version: $TOR_VERSION
|
@ -1,7 +1,9 @@
|
||||
# docker-compose.yml example
|
||||
# LEGACY CONFIGURATION
|
||||
# SEE README FOR INFORMATIONS
|
||||
|
||||
tor:
|
||||
image: goldy/tor-hidden-service
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
links:
|
||||
- hello
|
||||
- world
|
59
docker-compose.v2.legacy.yml
Normal file
59
docker-compose.v2.legacy.yml
Normal file
@ -0,0 +1,59 @@
|
||||
# docker version 2 example
|
||||
|
||||
version: "2"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
links:
|
||||
- hello
|
||||
- world
|
||||
- again
|
||||
environment:
|
||||
# Set mapping ports
|
||||
HELLO_PORTS: 80:80,800:80,8888:80
|
||||
# Set private key
|
||||
HELLO_KEY: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
|
||||
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
|
||||
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
|
||||
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
|
||||
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
|
||||
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
|
||||
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
|
||||
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
|
||||
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
|
||||
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
|
||||
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
|
||||
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
|
||||
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
WORLD_PORTS: 8000:80
|
||||
|
||||
AGAIN_PORTS: 88:80
|
||||
|
||||
# hello and again will share the same onion_adress
|
||||
AGAIN_SERVICE_NAME: foo
|
||||
HELLO_SERVICE_NAME: foo
|
||||
|
||||
# Keep keys in volumes
|
||||
volumes:
|
||||
- tor-keys:/var/lib/tor/hidden_service/
|
||||
|
||||
hello:
|
||||
image: tutum/hello-world
|
||||
hostname: hello
|
||||
|
||||
world:
|
||||
image: tutum/hello-world
|
||||
hostname: world
|
||||
|
||||
again:
|
||||
image: tutum/hello-world
|
||||
hostname: again
|
||||
|
||||
volumes:
|
||||
tor-keys:
|
||||
driver: local
|
@ -4,7 +4,7 @@ version: "2"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
build: .
|
||||
links:
|
||||
- world
|
||||
|
@ -4,17 +4,16 @@ version: "2"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service
|
||||
build: .
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
links:
|
||||
- hello
|
||||
- world
|
||||
- again
|
||||
environment:
|
||||
# Set mapping ports
|
||||
HELLO_PORTS: 80:80,800:80,8888:80
|
||||
HELLO_TOR_SERVICE_HOSTS: 80:hello:80,800:hello:80,8888:hello:80
|
||||
# Set private key
|
||||
HELLO_KEY: |
|
||||
HELLO_TOR_SERVIVE_KEY: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
|
||||
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
|
||||
@ -31,13 +30,13 @@ services:
|
||||
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
WORLD_PORTS: 8000:80
|
||||
|
||||
AGAIN_PORTS: 88:80
|
||||
|
||||
# hello and again will share the same onion_adress
|
||||
AGAIN_SERVICE_NAME: foo
|
||||
HELLO_SERVICE_NAME: foo
|
||||
FOO_TOR_SERVICE_HOSTS: 88:again:80,8000:world:80
|
||||
FOO_TOR_SERVICE_VERSION: '3'
|
||||
# tor v3 address private key base 64 encoded
|
||||
FOO_TOR_SERVICE_KEY: |
|
||||
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++
|
||||
j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
|
||||
|
||||
# Keep keys in volumes
|
||||
volumes:
|
||||
|
@ -4,23 +4,19 @@ version: "3.1"
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: goldy/tor-hidden-service
|
||||
build: .
|
||||
image: goldy/tor-hidden-service:$TOR_VERSION
|
||||
links:
|
||||
- hello
|
||||
- world
|
||||
- again
|
||||
environment:
|
||||
# Set mapping ports
|
||||
HELLO_PORTS: 80:80,800:80,8888:80
|
||||
# Set version 3 on BAR group
|
||||
BAR_TOR_SERVICE_HOSTS: '80:hello:80,88:world:80'
|
||||
BAR_TOR_SERVICE_VERSION: '3'
|
||||
|
||||
WORLD_PORTS: 8000:80
|
||||
# hello and again will share the same v2 onion_adress
|
||||
FOO_TOR_SERVICE_HOSTS: '88:again:80,80:hello:80,800:hello:80,8888:hello:80'
|
||||
|
||||
AGAIN_PORTS: 88:80
|
||||
|
||||
# hello and again will share the same onion_adress
|
||||
AGAIN_SERVICE_NAME: foo
|
||||
HELLO_SERVICE_NAME: foo
|
||||
|
||||
# Keep keys in volumes
|
||||
volumes:
|
||||
@ -31,6 +27,9 @@ services:
|
||||
- source: foo
|
||||
target: foo
|
||||
mode: 0400
|
||||
- source: bar
|
||||
target: bar
|
||||
mode: 0400
|
||||
|
||||
hello:
|
||||
image: tutum/hello-world
|
||||
@ -50,4 +49,6 @@ volumes:
|
||||
|
||||
secrets:
|
||||
foo:
|
||||
file: ./foo_private_key
|
||||
file: ./private_key_foo_v2
|
||||
bar:
|
||||
file: ./private_key_bar_v3
|
||||
|
2
last_tor_version.sh
Normal file
2
last_tor_version.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
git ls-remote --tags https://git.torproject.org/tor.git | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1
|
BIN
private_key_bar_v3
Normal file
BIN
private_key_bar_v3
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user