From e21cecd178b31660db07eb41e99084deb3318faf Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 1 Aug 2024 03:18:45 +0100 Subject: [PATCH] test version --- .env | 3 + .gitignore | 3 + Dockerfile | 92 ++++++++ LICENSE | 340 ++++++++++++++++++++++++++++++ README.md | 174 +++++++++++++++ config/1torrc.da | 42 ++++ config/new_torrc.da | 48 +++++ config/tor-apt-sources.list | 2 + config/torrc | 49 +++++ doc/arm.png | Bin 0 -> 84899 bytes docker-compose.yml | 160 ++++++++++++++ keys/authority_certificate | 45 ++++ keys/authority_identity_key | 41 ++++ keys/authority_signing_key | 27 +++ keys/ed25519_master_id_public_key | Bin 0 -> 64 bytes keys/ed25519_master_id_secret_key | Bin 0 -> 96 bytes keys/ed25519_signing_cert | Bin 0 -> 172 bytes keys/ed25519_signing_secret_key | Bin 0 -> 96 bytes keys/secret_id_key | Bin 0 -> 888 bytes keys/secret_onion_key | Bin 0 -> 888 bytes keys/secret_onion_key_ntor | Bin 0 -> 96 bytes scripts/da_fingerprint | 12 ++ scripts/docker-entrypoint | 107 ++++++++++ torrc.da.template | 47 +++++ util/README.md | 12 ++ util/control_port.py | 42 ++++ util/get_consensus.py | 8 + util/read_consensus.py | 9 + 28 files changed, 1263 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config/1torrc.da create mode 100644 config/new_torrc.da create mode 100644 config/tor-apt-sources.list create mode 100644 config/torrc create mode 100644 doc/arm.png create mode 100644 docker-compose.yml create mode 100644 keys/authority_certificate create mode 100644 keys/authority_identity_key create mode 100644 keys/authority_signing_key create mode 100644 keys/ed25519_master_id_public_key create mode 100644 keys/ed25519_master_id_secret_key create mode 100644 keys/ed25519_signing_cert create mode 100644 keys/ed25519_signing_secret_key create mode 100644 keys/secret_id_key create mode 100644 keys/secret_onion_key create mode 100644 keys/secret_onion_key_ntor create mode 100644 scripts/da_fingerprint create mode 100644 scripts/docker-entrypoint create mode 100644 torrc.da.template create mode 100644 util/README.md create mode 100644 util/control_port.py create mode 100644 util/get_consensus.py create mode 100644 util/read_consensus.py diff --git a/.env b/.env new file mode 100644 index 0000000..a60d60a --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +DA1_NICKNAME=DA1 +DA2_NICKNAME=DA2 +DA3_NICKNAME=DA3 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30e63b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +./tor/* +./*.sh + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c6d3c2f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,92 @@ +# +# Dockerfile for the Private Tor Network +# +# This is a dockerfile to build a Debian host and +# compile a version of tor from the Tor apt repos. +# NOTE: This is a modification of chriswayg's solid +# base. +# +# Usage: +# This works best using a docker compose command so you can run the +# necessary other servers for it to talk to. But if you want o run +# manually: +# +# docker run --rm -it -e ROLE=DA antitree/tor-server /bin/bash + +FROM debian:latest +MAINTAINER Antitree antitree@protonmail.com + +# Sets which version of tor to use. See the Tor Projects git page for available tags +# Examples: +# * tor-0.2.8.4-rc +# * tor-0.2.7.6 +# * tor-0.2.7.5 +# * release-0.2.1 +ENV TOR_VER="tor-0.4.8.12" +#ENV TOR_VER="master" +# NOTE sometimes the master branch doesn't compile so I'm sticking with the release +# feel free to change this to master to get the latest and greatest + +# Sets the nickname if you didn't set one, default ports, and the path +# where to mount the key material used by the clients. +ENV TERM=xterm \ + TOR_ORPORT=9001 \ + TOR_DIRPORT=9030 \ + TOR_DIR=/tor + + +ARG NICKNAME +ENV NICKNAME $NICKNAME + +# Install build dependencies +RUN apt-get update && \ + build_temps="build-essential automake" && \ + build_deps="libssl-dev zlib1g-dev libevent-dev ca-certificates\ + dh-apparmor libseccomp-dev \ + git" && \ + DEBIAN_FRONTEND=noninteractive apt-get -y --no-install-recommends install $build_deps $build_temps \ + init-system-helpers \ + pwgen && \ + mkdir /src && \ + apt-get update && \ + apt-get install -y tor iproute2 && \ + apt-get install -y gettext && \ + cd /src && \ + git clone https://git.torproject.org/tor.git && \ + cd tor && \ + git checkout ${TOR_VER} && \ + ./autogen.sh && \ + ./configure --disable-asciidoc && \ + make && \ + make install && \ + apt-get -y purge --auto-remove $build_temps && \ + apt-get clean && rm -r /var/lib/apt/lists/* && \ + rm -rf /src/* + +# Copy the base tor configuration file +COPY ./config/torrc* /etc/tor/ + +# Copy docker-entrypoint and the fingerprint script +COPY ./scripts/ /usr/local/bin/ + + +# Persist data (Usually don't want this) +#VOLUME /etc/tor /var/lib/tor + +# Create the shared directory +RUN mkdir -p ${TOR_DIR} + +# Копирование шаблона конфигурации +COPY torrc.da.template /etc/tor/torrc.da.template + +# Использование `envsubst` для замены переменных в шаблоне и создания файла torrc +RUN envsubst < /etc/tor/torrc.da.template > /etc/tor/torrc.da + +# ORPort, DirPort, ObfsproxyPort +# TODO make these match the env variables +# TODO is this necessary anymore? +EXPOSE 9001 9030 9051 + +ENTRYPOINT ["docker-entrypoint"] + +CMD ["tor", "-f", "/etc/tor/torrc"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8cdb845 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4452a20 --- /dev/null +++ b/README.md @@ -0,0 +1,174 @@ +## Private Tor Network on Docker + +##### An isolated, private tor network running entirely in Docker containers + +### Quickstart + +The easiest way to get a tor network up and running is to use the docker-compose create and then scale function + +``` +docker-compose up +docker-compose scale relay=5 exit=3 +``` + +This will create 3 directory authorities (DA's), 1 client listning on port 9050, 5 relays, and 3 exits. You can scale to whatever you want. + +### Uses + +If you're going "Why do I want this?" here's a few examples: + +**tor research**: learn how tor interacts with nodes, make modifications to settings and see what happens, understand how the Tor Network operates without affecting real people. Originally this project was part of a class I wrote to teach about how tor works. + +**tor development**: in the case you're working on a patch that is more complex and requires seeing what happens on the tor network, you can apply the patches to the containers. + +**traffic analysis**: Test out the latest tor exploit and pretend to be a nation state adversary. + +*If this needs to be said, this should never be used as a replacement for tor. This is for research purposes alone.* + +### Storage & Tor Network Configuration + +All of the required information that other nodes need to know about on the network are stored in a named volume `torvol` which you can find the path for doing `docker volume inspect privatetornetwork_torvol` or use `docker volume ls` to find its name on your system. + +If you are running multiple instances or are rebuilding it, make sure you delete this named volume or you'll accidentally use a previous iteration's keys. Easiest way is: + +~~~ +docker-compose rm +docker volume rm privatetornetwork_torvol +~~~ + +### Running Individual Roles + +You can manually build a tor network if you don't want to use docker-compose but you'll need to make sure you pass the correct DA fingerprints to each of the servers. Also make sure you create a user defined interface so that it doesn't try to use the default bridge. For example, this would make the first directory authority (DA) +`docker run -e ROLE=DA --network tornet antitree/private-tor` + +Or setup a relay: +`docker run -e ROLE=RELAY --network tornet antitree/private-tor` + +Watching the logs on a relay +`docker logs -f {name of your container}` + +Available roles right now are: + +* DA - directory authority +* RELAY - non-exit relay +* EXIT - exit relay +* CLIENT - exposes the tor socks port on 9050 to the host + +### Versions +You can run a variety of the most common tor versions by changing the image name from "antitree/private-tor:latest" to something like "antitree/private-tor:0.3.2". Current tags supported are from 0.2.6 to 0.3.5. + +If you'd like to try a very specific version you can rebuild the Dockerfile and edit the ["TOR_VER"](https://github.com/antitree/private-tor-network/blob/master/Dockerfile#L25) environment variable. These values should match the [branch names](https://gitweb.torproject.org/tor.git/refs/heads) from the official tor repo. + + +### Onion Services + +If you'd like to run an onion service, you can use the `TOR_HS_PORT` and `TOR_HS_ADDRESS` environment variables. By default, there is a hidden service setup in the docker-compose.yml file. + +Example configuration that will run an onion service named "hs" and a web server named "web". This will link the web service to the onion service so that "hs" will forward connections to "web" on port 80. This is done using the `links` configuration feature for docker-compose. + +``` + hs: + image: antitree/private-tor + expose: + - "80" + environment: + ROLE: HS + # This will create a hidden service that points to + # the service "web" which is runing nginx. You can + # change this to whatever ip or hostname you want + TOR_HS_PORT: "80" + TOR_HS_ADDR: "web" + volumes: + - ./tor:/tor + depends_on: + - da1 + - da2 + - da3 + links: + - web + web: + image: nginx + expose: + - "80" +``` + +NOTE: By default, this just displays the nginx start page so you may want to replace the image with a more interesting one or configure the nginx container with some static HTML to host. + +### Tor configuration + +This configuration is based on the Tor documentation for how to run a private tor network. You should also check out [Chutney](https://gitweb.torproject.org/chutney.git/) which does something similar with separate processes instead of containers. If you need to make a modification (such as changing the timing of the DA's) edit the `config/torrc` and/or `config/torrc.da` files. You may need to modify the Dockerfile as well. + +### Environment variables + +The container is built off of [chriswayg/tor-server](https://github.com/chriswayg/tor-server) but has been heavily modified to support some other env variables that you can pass to it: + +* TOR_ORPORT - default is 7000 +* TOR_DIRPORT - default is 9030 +* TOR_DIR - container path to mount a persistent tor material. default is /tor +* TOR_CONTROL_PWD - set the control port password to something besides "password" +* TOR_HS_PORT - port to listen for an onion service on +* TOR_HS_ADDR - IP or hostname of service you want to point an onion service to + +### Things to try + +The `/util/` directory contains a few scripts to play with one the host computer. Once you have a +private tor network up and running you can try out some of the tools in there. + +**Using Arm**: + +With the tor control port exposed to the host, you can use arm to monitor the client. +``` +apt-get install tor-arm +arm +``` +NOTE: There is a password to protect the control port right now. Enter "password" when prompted + +![arm screenshot](https://raw.githubusercontent.com/antitree/private-tor-network/master/doc/arm.png) + +You can also connect arm to one of the containers if you know it's ip. You can find the IPs by running the +`get_consensus.py` script provided or however otherway you feel like. + +```arm -i 172.19.0.3:9051``` + +**Get Consensus**: + +```python util/get_consensus.py``` + +This will connect to the CLIENT docker container via the tor Control Port and download the consensus which +contains the nicknames and IPs of the relays on the network. (If this is blank, you may have to wait 30s +while they decided on a consensus.) + +**Tor-prompt**: + +If you've installed arm you will probably also have the `tor-prompt` command. You can use it to manually +gather information about some of the containers that have their Control Port exposed like so: + +``` +tor-prompt -i {ip_of_ontainer}:9051 +Control Port password: password +``` + + +### Debugging + +Here are a few things to try if you're runing into issues: + +* Check the tor logs sent to stdout `docker logs -f torserver_da_1` +* Check all the logs with `docker-compose logs` +* Enable verbose logging by changing the `./config/torrc` +* Check permissions for your ./tor folder +* Delete the files in your ./tor folder so you can start from scratch (or specifically the torrc.da file) +* To cleanup the environment and start over you can use `docker-compose kill` and `docker-compose rm -ra` to remove them all. + +### TODO + +* Wait for someone to yell at me about using scale like this and then move to the new networking + +### Dislaimer + +This project is in no way associated with the Tor Project or their developers. Like many people I'm a fan of Tor and recommend considering ways you can help the project. Consider running a relay, donating, or writing code. + +### Resources +- https://github.com/andrewmichaelsmith/private-tor-network-kube Used some of this work to port to a kubernetes config +- https://github.com/chriswayg/tor-server +- https://www.torproject.org/docs/tor-relay-debian.html.en diff --git a/config/1torrc.da b/config/1torrc.da new file mode 100644 index 0000000..0345189 --- /dev/null +++ b/config/1torrc.da @@ -0,0 +1,42 @@ +AuthoritativeDirectory 1 +V3AuthoritativeDirectory 1 + +# Speed up the consensus cycle as fast as it will go +# Voting Interval can be: +# 10, 12, 15, 18, 20, 24, 25, 30, 36, 40, 45, 50, 60, ... +# Testing Initial Voting Interval can be: +# 5, 6, 8, 9, or any of the possible values for Voting Interval, +# as they both need to evenly divide 30 minutes. +# If clock desynchronisation is an issue, use an interval of at least: +# 18 * drift in seconds, to allow for a clock slop factor +TestingV3AuthInitialVotingInterval 300 +#V3AuthVotingInterval 15 +# VoteDelay + DistDelay must be less than VotingInterval +TestingV3AuthInitialVoteDelay 5 +V3AuthVoteDelay 5 +TestingV3AuthInitialDistDelay 5 +V3AuthDistDelay 5 +# This is autoconfigured by chutney, so you probably don't want to use it +#TestingV3AuthVotingStartOffset 0 + +# Work around situations where the Exit, Guard and HSDir flags aren't being set +# These flags are all set eventually, but it takes Guard up to ~30 minutes +# We could be more precise here, but it's easiest just to vote everything +# Clients are sensible enough to filter out Exits without any exit ports, +# and Guards and HSDirs without ORPorts +# If your tor doesn't recognise TestingDirAuthVoteExit/HSDir, +# either update your chutney to a 2015 version, +# or update your tor to a later version, most likely 0.2.6.2-final + +# These are all set in common.i in the Comprehensive/Rapid sections +# Work around Exit requirements +#TestingDirAuthVoteExit * +# Work around bandwidth thresholds for exits +#TestingMinExitFlagThreshold 0 +# Work around Guard uptime requirements +#TestingDirAuthVoteGuard * +# Work around HSDir uptime and ORPort connectivity requirements +#TestingDirAuthVoteHSDir * + +Address 127.0.0.1 +DirAuthority Alex 127.0.0.1:9030 7EB85B97333C276E7D88000F074DFCD534CE69E2 diff --git a/config/new_torrc.da b/config/new_torrc.da new file mode 100644 index 0000000..bb9b5a6 --- /dev/null +++ b/config/new_torrc.da @@ -0,0 +1,48 @@ +AuthoritativeDirectory 1 +V3AuthoritativeDirectory 1 + +# Speed up the consensus cycle as fast as it will go +# Voting Interval can be: +# 10, 12, 15, 18, 20, 24, 25, 30, 36, 40, 45, 50, 60, ... +# Testing Initial Voting Interval can be: +# 5, 6, 8, 9, or any of the possible values for Voting Interval, +# as they both need to evenly divide 30 minutes. +# If clock desynchronisation is an issue, use an interval of at least: +# 18 * drift in seconds, to allow for a clock slop factor +TestingV3AuthInitialVotingInterval 300 +#V3AuthVotingInterval 15 +# VoteDelay + DistDelay must be less than VotingInterval +TestingV3AuthInitialVoteDelay 5 +V3AuthVoteDelay 5 +TestingV3AuthInitialDistDelay 5 +V3AuthDistDelay 5 +# This is autoconfigured by chutney, so you probably don't want to use it +#TestingV3AuthVotingStartOffset 0 + +# Work around situations where the Exit, Guard and HSDir flags aren't being set +# These flags are all set eventually, but it takes Guard up to ~30 minutes +# We could be more precise here, but it's easiest just to vote everything +# Clients are sensible enough to filter out Exits without any exit ports, +# and Guards and HSDirs without ORPorts +# If your tor doesn't recognise TestingDirAuthVoteExit/HSDir, +# either update your chutney to a 2015 version, +# or update your tor to a later version, most likely 0.2.6.2-final + +# These are all set in common.i in the Comprehensive/Rapid sections +# Work around Exit requirements +#TestingDirAuthVoteExit * +# Work around bandwidth thresholds for exits +#TestingMinExitFlagThreshold 0 +# Work around Guard uptime requirements +#TestingDirAuthVoteGuard * +# Work around HSDir uptime and ORPort connectivity requirements +#TestingDirAuthVoteHSDir * + + +DirAuthority Alex 127.0.0.1:9030 7EB85B97333C276E7D88000F074DFCD534CE69E2 +#v3ident=b80992426b37f9ad9e2335ee1c26239da838d4c7 + +ContactInfo Alex Voronkov +# Address 89.129.190.248 + +Address 127.0.0.1:9030 diff --git a/config/tor-apt-sources.list b/config/tor-apt-sources.list new file mode 100644 index 0000000..46a1699 --- /dev/null +++ b/config/tor-apt-sources.list @@ -0,0 +1,2 @@ +deb http://deb.torproject.org/torproject.org latest main +deb-src http://deb.torproject.org/torproject.org latest main diff --git a/config/torrc b/config/torrc new file mode 100644 index 0000000..49f453e --- /dev/null +++ b/config/torrc @@ -0,0 +1,49 @@ +# Run Tor as a regular user (do not change this) +#User debian-tor + +TestingTorNetwork 1 + +## Comprehensive Bootstrap Testing Options ## +# These typically launch a working minimal Tor network in 25s-30s, +# and a working HS Tor network in 40-45s. +# See authority.tmpl for a partial explanation +#AssumeReachable 0 +#Default PathsNeededToBuildCircuits 0.6 +#Disable TestingDirAuthVoteExit +#Disable TestingDirAuthVoteHSDir +#Default V3AuthNIntervalsValid 3 + +## Rapid Bootstrap Testing Options ## +# These typically launch a working minimal Tor network in 6s-10s +# These parameters make tor networks bootstrap fast, +# but can cause consensus instability and network unreliability +# (Some are also bad for security.) +AssumeReachable 1 +PathsNeededToBuildCircuits 0.25 +TestingDirAuthVoteExit * +TestingDirAuthVoteHSDir * +V3AuthNIntervalsValid 2 + +## Always On Testing Options ## +# We enable TestingDirAuthVoteGuard to avoid Guard stability requirements +TestingDirAuthVoteGuard * +# We set TestingMinExitFlagThreshold to 0 to avoid Exit bandwidth requirements +TestingMinExitFlagThreshold 0 +# VoteOnHidServDirectoriesV2 needs to be set for HSDirs to get the HSDir flag +#Default VoteOnHidServDirectoriesV2 1 + +## Options that we always want to test ## +Sandbox 1 + +# Private tor network configuration +RunAsDaemon 0 +ConnLimit 60 +ShutdownWaitLength 0 +#PidFile /var/lib/tor/pid +Log info stdout +ProtocolWarnings 1 +SafeLogging 0 +DisableDebuggerAttachment 0 + +DirPortFrontPage /usr/share/doc/tor/tor-exit-notice.html + diff --git a/doc/arm.png b/doc/arm.png new file mode 100644 index 0000000000000000000000000000000000000000..01d6b4922264e1124b7265eb94094a7d02ff331e GIT binary patch literal 84899 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

h%1t7fmh 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 + sh -c " + echo $DA1_NICKNAME && + mkdir -p /tor/$DA1_NICKNAME/keys && + cp -r /keys/* /tor/$DA1_NICKNAME/keys && + tor -f /etc/tor/torrc" + + da2: + build: + context: . + dockerfile: Dockerfile + args: + NICKNAME: ${DA2_NICKNAME} + environment: + ROLE: DA + DA2_NICKNAME: DA2 + + + volumes: + ## Needed to keep track of other nodes + - ./tor:/tor + - ./keys:/keys + + command: > + sh -c " + echo $DA2_NICKNAME && + mkdir -p /tor/$DA2_NICKNAME/keys && + cp -r /keys/* /tor/$DA2_NICKNAME/keys && + tor -f /etc/tor/torrc" + + da3: + build: + context: . + dockerfile: Dockerfile + args: + NICKNAME: ${DA3_NICKNAME} + environment: + ROLE: DA + DA3_NICKNAME: DA3 + + + volumes: + ## Needed to keep track of other nodes + - ./tor:/tor + - ./keys:/keys + + command: > + sh -c " + echo $DA3_NICKNAME && + mkdir -p /tor/$DA3_NICKNAME/keys && + cp -r /keys/* /tor/$DA3_NICKNAME/keys && + tor -f /etc/tor/torrc" + + relay: + image: tor-network:latest + #expose: + # - "7000" + # - "9030" + environment: + ROLE: RELAY + volumes: + - ./tor:/tor + depends_on: + # Make sure the DA's are already up + - da1 + - da2 + - da3 + - build_image + exit: + image: tor-network:latest + #expose: + # - "7000" + # - "9030" + environment: + ROLE: EXIT + volumes: + - ./tor:/tor + depends_on: + # Make sure the DA's are already up + - da1 + - da2 + - da3 + - build_image + client: + image: tor-network:latest + ports: + # Setups a listener on host machine + - "9050:9050" + - "9051:9051" + volumes: + - ./tor:/tor + - ./keys:/keys + environment: + ROLE: CLIENT + + command: > + sh -c " + mkdir -p /tor/$(hostname)/keys && + cp -r /keys /tor/$(hostname) && + tor -f /etc/tor/torrc" + depends_on: + - da1 + - da2 + - da3 + - build_image + hs: + image: tor-network:latest + #expose: + # - "80" + environment: + ROLE: HS + # This will create a hidden service that points to + # the service "web" which is runing nginx. You can + # change this to whatever ip or hostname you want + TOR_HS_PORT: "80" + TOR_HS_ADDR: "web" + volumes: + - ./tor:/tor + depends_on: + - da1 + - da2 + - da3 + - build_image + links: + - web + web: + image: nginx + #expose: + # - "80" + + + + build_image: + build: + context: . + dockerfile: Dockerfile + volumes: + ## Needed to keep track of other nodes + - ./tor:/tor + image: tor-network:latest + command: ["/bin/true"] + diff --git a/keys/authority_certificate b/keys/authority_certificate new file mode 100644 index 0000000..a6db2c7 --- /dev/null +++ b/keys/authority_certificate @@ -0,0 +1,45 @@ +dir-key-certificate-version 3 +fingerprint 7EB85B97333C276E7D88000F074DFCD534CE69E2 +dir-key-published 2024-07-30 22:40:50 +dir-key-expires 2025-07-30 22:40:50 +dir-identity-key +-----BEGIN RSA PUBLIC KEY----- +MIIBigKCAYEAzr7AjPNjZv3I6GTGRV+Azn6FB4xDpm73aaIYqGTQIq+/Qi1Ot0P4 +t1Vmil0eXxRCqsoRDVNKzi+6FSAvvbnFocbMHd85y6iJawAJNO3Pt8F2dORZO+ya +GMQv9/5ZiYAYYvGyruJwbJEf77jxSnlm95lOr25JdWTHq+53dZCLP7AK1SPsGdZy +ZUlV0U1QwnvTpVE5PQPQMN+tRfeqAI2LENPLdGQjU4Msys39VWXt6FUdwVoX0VAl +MZ62GYoFRATXG8z+OwHxjNe8GEyhPuVrLWxCGGE9rGvp3M57TjN0W+F0REYYq704 +EOvryzDUECuYODVssqZx8kcpIzIhNFe9R9ycd0hfowJd51kWSwWvQpY3IvZ6AGhQ +JopS0JJTIeo0sLceldsbd+f7C8nBq7R+uQfX8J6BTWx88JLcmJ3gwi23bsZY98Dx +vIo/Q+cVNJyVMtMHrqeqimgMA7I/qc16ru7ke0O2qNmUqeOTkIJItN3Aeu0yhAzB +mwTWcgPfW+U1AgMBAAE= +-----END RSA PUBLIC KEY----- +dir-signing-key +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEArQbVX2pXYtYANevfNnOJQ8D0/pGCxTxIIk6JA+YhVYazgLfLPktA +naKBnXpZyntuApyKXqwhSN3PemnGzwE1Nps2Cs8wJlqQGUvokcF0lmtfj+gTuyz4 +HYpEzD74W9oJe7cEbB/Ee8oFW/NE/xMH1Rr9SnBWSHH2n9XunJWpxhiHZ4u8vh1F +0Uc4ycbgRwD2fpAOIkkI7piIc76YVPpbB2RWgKWbWv6iWW7Umffre0DrSqOzrCEq +QuKPNLygoPPvrDSa36AJUfUqltFlzXoxDtVUn7hCZYWrUahXBWobUF0/jNVkvTpo +niZ7U3RWtgiMgiKAMX0qoH87pU0kUxMbzQIDAQAB +-----END RSA PUBLIC KEY----- +dir-key-crosscert +-----BEGIN ID SIGNATURE----- +pCFFAuM5oQNpIGzcdSGnoU2cImKIVcpw6asu2KiFTM+QRnLUS5ZgVEt7FpSQrMO3 +pe1sOj1RtqASAu8pyqLRrGcxukxHmYLA/og13X2ODhgdazA1tNFnuQqe0SZR9jct +5QWu0Mp+p3SMnfxRP91DF8Sx0au7w9M7kfHBO3Wcur2F/lX8LMcMAB3P34Mw8hWV +Dw2irLUKpZk9KtAZ2RShUC4rZkd70ZlF/DMHcthj1PiJBLdQZgsermUPBLwl05SG +emSy4YWL9gcTnF9ZreoPlgxjdQcBl7+CaAXd5KHXUnu+bECNLAazsLprr+NtvK9N +NJstnB5KHI4CgzGIWFP0WA== +-----END ID SIGNATURE----- +dir-key-certification +-----BEGIN SIGNATURE----- +HTHxvVcN+4X2OhjN57HbE0j+A01nRLuV6bHZqbT5Be+FPNd6E9ACp2hpp3vQRggv +xLp0xGZndUNMgu2nsnf3Rgn5DYjT1BqkdJkF+K5ICr4e6XekYsBnbHjtWgCq1yTl +7bZjPwHotFtMitAojXaG56kFLjtoY1/c0c3HqWp4xsMfk2jss5JHoK5IQVee/ttp +Ba/5X054zUy8Ar8ZvNEpcCx3Vat2IY79n+S4vJKHoroM5EE72FVBK4q5cj6bSlkK +Am1BmIZsmJrhoSej2cFM+V5ReAdNv5s+GcFF1hnQPaidtqnwOb414L73iS68nfJp +4dwPhtIDQdZjNTT1+mntpHBG4xSV7UeokDcARsSEQX7Pv7tA6ijTKGCASAg+3Z0h +pp9ZTxxoAh1MwRfcCQp6qFTIkUVhg6yitDVT0B3BFkKeEXTZormO0aQ5w15JJEtu +CfGfjw95D3otZ15Jgvgt+ylPVcvHriu9mZsnnSsifx8sv82ofBiEqCYWukzewU6B +-----END SIGNATURE----- diff --git a/keys/authority_identity_key b/keys/authority_identity_key new file mode 100644 index 0000000..dbf165e --- /dev/null +++ b/keys/authority_identity_key @@ -0,0 +1,41 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +/RLZprr8F4pi6m4QPng= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/keys/authority_signing_key b/keys/authority_signing_key new file mode 100644 index 0000000..e1847c9 --- /dev/null +++ b/keys/authority_signing_key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEArQbVX2pXYtYANevfNnOJQ8D0/pGCxTxIIk6JA+YhVYazgLfL +PktAnaKBnXpZyntuApyKXqwhSN3PemnGzwE1Nps2Cs8wJlqQGUvokcF0lmtfj+gT +uyz4HYpEzD74W9oJe7cEbB/Ee8oFW/NE/xMH1Rr9SnBWSHH2n9XunJWpxhiHZ4u8 +vh1F0Uc4ycbgRwD2fpAOIkkI7piIc76YVPpbB2RWgKWbWv6iWW7Umffre0DrSqOz +rCEqQuKPNLygoPPvrDSa36AJUfUqltFlzXoxDtVUn7hCZYWrUahXBWobUF0/jNVk +vTponiZ7U3RWtgiMgiKAMX0qoH87pU0kUxMbzQIDAQABAoIBAASZWAkwckZyHlx/ +F7lCp4sLzldCyA0AfphXkrActMQGbN5d8s5XTRQPL308kin1OAMHTbLH3UxB7oIs +f6zL5ANtVBJyqXTWbmX/6e3sxpSulggTl1JOXNLZowvcv1iTemCYq1Zgk2vl/m/W +GnKzkkrcYGE76Z55PnIkKFWdPPPDFcwFYmk/oCBR+Rn5YtteUHFJfHMZlE9clG6h +m3fw3QKQn43LcMJJveiI2ISkBAq0Y4aqDGNR95Z13z8MqqqZwbJlmKMk4O5dM82p +2UdvwEAvAm+AhQYjozT2LWI/lO6TkzcUHTyjFmgIdCb2vb0XGqfI0hZ5hXoOlmM3 +TgbS0B8CgYEAvFXWtbqtZ4aAOvrN9plppNISB8ywxD7E4ErWVdUnFZPR9XqWTbyk +IA6p7Q+GWdKy2InpcmvCWgbkopX3gHYj7QbBfpTSVu7CPnqY2LcorOC6QuHZwPkR +Qfo1oszbOjdN4rmQ58ClGx52p5ERCgbd/Zgpv4qyFtBJbiTGS9dbiZMCgYEA6zD7 +tmD/zU5WKBuTC/Fa7q4xXOwJ9MZ2L7URtwTsamOuLWRlfPd3KFgxL+vXMweYgctd +WPwnouMqlWIpSA+1oIwMj1PfaHGRcoGOHHI2LI3RyqMs8GO4Xs5RFf6bYnQ96A/a +oumar+lppV10WBJhr6SAqDnVBI0c5O5iryeooR8CgYA9V7AhbPZB+/sUOtCO+5T/ +TDT3OWJx6QfzDi0Vs+GRE56VWCJQm5rRnjUWs7HM2+XIxdK1pAefjxM1Kad9vf0h +nMu1UP/ZtNarxv61x6KF/IRueGWWhwlp9fc2WYcmRREnQc3Czmp4lMmM9qEYJPh1 +OvSOILy01Y61Q2EbHr//5QKBgQCOTGC/hAjBSzhNpAFgJHOEHdi4BAgyFTHEw6Uo +Os5fwFfOFwRgi8mIm3OHLwZRVbMsNMMR596DazaEk5OuifK2ZIXk4jY1lyENSt2U +0HV+l3/rPrcd6vfORL5CtH2HIBWkppL+JqD09iB5cQXHk7eO8dT186eyzT5CNQl4 +OGKKuQKBgQCgrTNN1GF9rJ3x8Kf7Se6fMc2kBkU0B5biwapDER+iriW3BkHbUp47 +32QP5HBKnbvbBhTfB/99VrwLbnU6cFW/qICXdQo6b2J30PehNWzOFcl5vKRIb1Pc +UrpwQpZWX/+XnpflVtKrEMegkK/p3KBqOvoXRC9NNJET0+OXuuvtVg== +-----END RSA PRIVATE KEY----- diff --git a/keys/ed25519_master_id_public_key b/keys/ed25519_master_id_public_key new file mode 100644 index 0000000000000000000000000000000000000000..5805b209d7650f030d5d9b8ba1a35ec7637e4f2e GIT binary patch literal 64 zcmcDuRY*-SGBq`{EHl(CC{4=AOtw-esVqn}P_VUSU|={nX-npxmxUjm3f;-yRZwU3 U?yZqPpWNpr*1Hb1bq<$|0qIa09RL6T literal 0 HcmV?d00001 diff --git a/keys/ed25519_master_id_secret_key b/keys/ed25519_master_id_secret_key new file mode 100644 index 0000000000000000000000000000000000000000..24fbd2363a60506b83d72361f0c2f4699d08bd3d GIT binary patch literal 96 zcmV-m0H6OoJs@RdGBq_ZId(BEb7f<4Wpp|qba`-PFd#iW00008oZovRC_*RbC}l(D z7Mw(9L<1rTQO^a5d%j7#HXu_ANqa(*y*%PewKV@}a&BORC3s&3?&C$<(rxin`2DEz C03}cW literal 0 HcmV?d00001 diff --git a/keys/ed25519_signing_cert b/keys/ed25519_signing_cert new file mode 100644 index 0000000000000000000000000000000000000000..b450321a19008e18c79d94f61285a69b4d1cdf16 GIT binary patch literal 172 zcmV;d08{@xJs@RdGBq_ZId(BEV`Xx5Iv{j;aAhScOUb z>!a1s9BSo%h-4w`POI4_QHfe7-s&0cQ5OLKAOrxxlC)|3>2dJo65MaPaDF=O?J^LK z9`k|)-9UYQK+-eEnPs8q9z%3lO#x(?%Uj{Hm+!@!DFhLFQt^6adYDB_%^2hVY6t{xvqNxJlFvvK*?ZycCv#XQykU89n5l C@h2?+ literal 0 HcmV?d00001 diff --git a/keys/secret_id_key b/keys/secret_id_key new file mode 100644 index 0000000000000000000000000000000000000000..f26b240242a95b5a4a0c51614021db5958c56246 GIT binary patch literal 888 zcmZvbxwfiE001ZED{k(&hgHyEf`$fcRG`@eGC+3OSNZyRGx1bfNhS6B`v*~0k^W=Z z;K#I(2ORn5E(iaLU*d_7Iwe6ot0%E{rrUJPsCv7f_GqxH znORwfS>{dzHl{TSBg%-hT+8MN;U)@FvvCvMjXSO@!&&ZCmg^G(W%iI^($Wk#eS3@` zz(6EGrvluxD6~k2QxT+}sW;Pcd%m;UwjR z_sEguksWT61u-yY3=cXt&866&T;9X+JUwn&uPZPB5zEk9P;!0~$71XR`O>*Bf=99e zwTro%k4t!ccd0l?Z2+!|-#1Js&Ukfb8#a@|rR!G962@@$M|xfdcgfU*BA&Y6OCl!; zK(0Eehub_Rz&=a!5oWk$-X}BC-C()3s2iATm%6d5WrZjovs=||ln_!G$hy?rKrI6S zBo}mX#fG%LsP79=jj9Q?$O5Qg#F^GIaq<1cfpj8LH~^KA?jSU-sZ_9 z-C0p~*So)kGW2SIJgY%A+LV?WfvCN%*!&SHVk! XdKT8*zVc4~H}T&-vJU@$tH1sM@T49_ literal 0 HcmV?d00001 diff --git a/keys/secret_onion_key b/keys/secret_onion_key new file mode 100644 index 0000000000000000000000000000000000000000..62f96f992d44749629024afdc4b63e4375f38322 GIT binary patch literal 888 zcmZvbx3a5N003R{6}M;Z5Cj4W7l)iPNYH@*2@#GsAkx>{&$YMRZfExQ_g_RsGu)pr z0zZCeq##y)EG7FRelf=|q&qM~04(tt$bJDEKk1NK;@gREvR99L(CY_*a zYuI~Tf;WN0Ugj{*-76fgY}$i~`+hj9@{>LNFoT`+4&9TuH*6Ed41W7e+pJ)L}m~6;(g{J>ZBl$*U?JnhRSW6szvN{!|~KR zQ;e4>$`>>c{+AL-92pBA3r-=-PT!8Pe%l%}M5=mbbu3R(dUIhD3!K!pp7c3z`37)8WDsLuyq205!k-%ljAKf4 ztX?ej6sz9~t{s`pabSYT<$PAn*!MlKnF=XE+gaB8@idBc#U$ECxmjPPs4NQi+^@V@ zOD@eWlEdi3!uN$fg_FHx?h+P4Ytjri#Y1-IHWO6V#$&c4c#!ApApqm;wEfK6-Fh-1 zrxj$-<8#Iq3!>)4*~0h2l*V0Dq2ZeEnteE;b``LRA(GN`>WF@)Xa4n3V2Z%t`28;C zf{dS!O|;wE6PjGl);Qdr^-!}j%EY>9-Ews?X=m{E3{yX}E<|2Fqzd3#_N~}_>g}Yv Y3jB6H!tOKL{NLDr`zWsb|6Bd_4}C)&_W%F@ literal 0 HcmV?d00001 diff --git a/keys/secret_onion_key_ntor b/keys/secret_onion_key_ntor new file mode 100644 index 0000000000000000000000000000000000000000..9f380188a563e3fa88a2fbd1b3f8e3ce445fc030 GIT binary patch literal 96 zcmcDuRY*26H8r#>Gqh63&&$luQ?RvVKmdh_D^iLd#k~m&H%z`fbE{04_T0;6_B*YM urtr$0`db-O6lCs_W_Dpt|JMg0y?H#1S1ewiUbbP`kCJ;~5-;w2-~#~F&?bTa literal 0 HcmV?d00001 diff --git a/scripts/da_fingerprint b/scripts/da_fingerprint new file mode 100644 index 0000000..7f37a99 --- /dev/null +++ b/scripts/da_fingerprint @@ -0,0 +1,12 @@ +#!/bin/sh +# version 2 +TOR_NICK=$(grep "^Nick" /etc/tor/torrc | awk -F ' ' '{print $2}') +AUTH=$(grep "fingerprint" $TOR_DIR/$TOR_NICK/keys/* | awk -F " " '{print $2}') +NICK=$(cat $TOR_DIR/$TOR_NICK/fingerprint| awk -F " " '{print $1}') +RELAY=$(cat $TOR_DIR/$TOR_NICK/fingerprint|awk -F " " '{print $2}') +SERVICE=$(grep "dir-address" $TOR_DIR/$TOR_NICK/keys/* | awk -F " " '{print $2}') +IPADDR=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') + +TORRC="DirAuthority $TOR_NICK orport=${TOR_ORPORT} no-v2 v3ident=$AUTH $SERVICE $RELAY" + +echo $TORRC diff --git a/scripts/docker-entrypoint b/scripts/docker-entrypoint new file mode 100644 index 0000000..e685517 --- /dev/null +++ b/scripts/docker-entrypoint @@ -0,0 +1,107 @@ +#!/bin/bash +set -o errexit + +# Fudge the sleep to try and keep the consensus +#FUDGE=$(( ( RANDOM % 100) + 20 )) +FUDGE=3 + +echo -e "\n========================================================" + +if [ ! -e /tor-config-done ]; then + touch /tor-config-done # only run this once + + # Generate a random name + RPW=$(pwgen -0A 10) + export TOR_NICKNAME=${ROLE}${RPW} + echo "Setting random Nickname: ${TOR_NICKNAME}" + echo -e "\nNickname ${TOR_NICKNAME}" >> /etc/tor/torrc + + # Host specific modifications to the torrc file + echo -e "DataDirectory ${TOR_DIR}/${TOR_NICKNAME}" >> /etc/tor/torrc + # Updated to handle docker stack/swarm network overlays + TOR_IP=$(ip addr show eth1 | grep "inet" | grep -v '\/32'| awk '{print $2}' | cut -f1 -d'/') + NICS=$(ip addr | grep 'state UP' | awk '{print $2}' | cut -f1 -d':') + + echo "Address ${TOR_IP}" >> /etc/tor/torrc + echo -e "ControlPort 0.0.0.0:9051" >> /etc/tor/torrc + if [ -z "${TOR_CONTROL_PWD}" ]; then + TOR_CONTROL_PWD="16:6971539E06A0F94C6011414768D85A25949AE1E201BDFE10B27F3B3EBA" + fi + echo -e "HashedControlPassword ${TOR_CONTROL_PWD}" >> /etc/tor/torrc + + # Changes to the torrc file based on the desired role + case ${ROLE} in + DA) + echo "Setting role to DA" + cat /etc/tor/torrc.da >> /etc/tor/torrc + echo -e "OrPort ${TOR_ORPORT}" >> /etc/tor/torrc + echo -e "Dirport ${TOR_DIRPORT}" >> /etc/tor/torrc + echo -e "ExitPolicy accept *:*" >> /etc/tor/torrc + KEYPATH=${TOR_DIR}/${TOR_NICKNAME}/keys + mkdir -p ${KEYPATH} + echo "password" | tor-gencert --create-identity-key -m 12 -a ${TOR_IP}:${TOR_DIRPORT} \ + -i ${KEYPATH}/authority_identity_key \ + -s ${KEYPATH}/authority_signing_key \ + -c ${KEYPATH}/authority_certificate \ + --passphrase-fd 0 + tor --list-fingerprint --orport 1 \ + --dirserver "x 127.0.0.1:1 ffffffffffffffffffffffffffffffffffffffff" \ + --datadirectory ${TOR_DIR}/${TOR_NICKNAME} + echo "Saving DA fingerprint to shared path" + da_fingerprint >> ${TOR_DIR}/torrc.da + echo "Waiting for other DA's to come up..." + ;; + RELAY) + echo "Setting role to RELAY" + echo -e "OrPort ${TOR_ORPORT}" >> /etc/tor/torrc + echo -e "Dirport ${TOR_DIRPORT}" >> /etc/tor/torrc + echo -e "ExitPolicy accept private:*" >> /etc/tor/torrc + + echo "Waiting for other DA's to come up..." + ;; + EXIT) + echo "Setting role to EXIT" + echo -e "OrPort ${TOR_ORPORT}" >> /etc/tor/torrc + echo -e "Dirport ${TOR_DIRPORT}" >> /etc/tor/torrc + echo -e "ExitPolicy accept *:*" >> /etc/tor/torrc + echo "Waiting for other DA's to come up..." + ;; + CLIENT) + echo "Setting role to CLIENT" + echo -e "SOCKSPort 0.0.0.0:9050" >> /etc/tor/torrc + ;; + HS) + # NOTE By default the HS role will point to a service running on port 80 + # but there is no service running on port 80. You can either attach to + # the container and start one, or better yet, point to another docker + # container on the network by setting the TOR_HS_ADDR to its IP + echo "Setting role to HIDDENSERVICE" + echo -e "HiddenServiceDir ${TOR_DIR}/${TOR_NICKNAME}/hs" >> /etc/tor/torrc + if [ -z "${TOR_HS_PORT}" ]; then + TOR_HS_PORT=80 + fi + if [ -z "${TOR_HS_ADDR}" ]; then + TOR_HS_ADDR=127.0.0.1 + fi + echo -e "HiddenServicePort ${TOR_HS_PORT} ${TOR_HS_ADDR}:${TOR_HS_PORT}" >> /etc/tor/torrc + ;; + *) + echo "Role variable missing" + exit 1 + ;; + esac + + # Buffer to let the directory authority list be built + sleep $FUDGE + cat ${TOR_DIR}/torrc.da >> /etc/tor/torrc + +fi + +echo -e "\n========================================================" +# display Tor version & torrc in log +tor --version +cat /etc/tor/torrc +echo -e "========================================================\n" + +# else default to run whatever the user wanted like "bash" +exec "$@" diff --git a/torrc.da.template b/torrc.da.template new file mode 100644 index 0000000..366b4e3 --- /dev/null +++ b/torrc.da.template @@ -0,0 +1,47 @@ +AuthoritativeDirectory 1 +V3AuthoritativeDirectory 1 + +# Speed up the consensus cycle as fast as it will go +# Voting Interval can be: +# 10, 12, 15, 18, 20, 24, 25, 30, 36, 40, 45, 50, 60, ... +# Testing Initial Voting Interval can be: +# 5, 6, 8, 9, or any of the possible values for Voting Interval, +# as they both need to evenly divide 30 minutes. +# If clock desynchronisation is an issue, use an interval of at least: +# 18 * drift in seconds, to allow for a clock slop factor +TestingV3AuthInitialVotingInterval 300 +#V3AuthVotingInterval 15 +# VoteDelay + DistDelay must be less than VotingInterval +TestingV3AuthInitialVoteDelay 5 +V3AuthVoteDelay 5 +TestingV3AuthInitialDistDelay 5 +V3AuthDistDelay 5 +# This is autoconfigured by chutney, so you probably don't want to use it +#TestingV3AuthVotingStartOffset 0 + +# Work around situations where the Exit, Guard and HSDir flags aren't being set +# These flags are all set eventually, but it takes Guard up to ~30 minutes +# We could be more precise here, but it's easiest just to vote everything +# Clients are sensible enough to filter out Exits without any exit ports, +# and Guards and HSDirs without ORPorts +# If your tor doesn't recognise TestingDirAuthVoteExit/HSDir, +# either update your chutney to a 2015 version, +# or update your tor to a later version, most likely 0.2.6.2-final + +# These are all set in common.i in the Comprehensive/Rapid sections +# Work around Exit requirements +#TestingDirAuthVoteExit * +# Work around bandwidth thresholds for exits +#TestingMinExitFlagThreshold 0 +# Work around Guard uptime requirements +#TestingDirAuthVoteGuard * +# Work around HSDir uptime and ORPort connectivity requirements +#TestingDirAuthVoteHSDir * + +Address 127.0.0.1 +DirAuthority Alex 127.0.0.1:9030 7EB85B97333C276E7D88000F074DFCD534CE69E2 + +Nickname ${NICKNAME} +DataDirectory /tor/${NICKNAME} + +# Nickname ${TOR_NICKNAME} diff --git a/util/README.md b/util/README.md new file mode 100644 index 0000000..8555671 --- /dev/null +++ b/util/README.md @@ -0,0 +1,12 @@ +## Utils + +This folder contains various scripts to let you perform +functions on your tor instance. Many of these are from the +[Stem Website](https://stem.torproject.org) which has +additional documentation on functions you can perform. + +Other examples: + +Use tor-prompt to interact with a docker process: + +```tor-prompt -i 172.16.0.3:9051`` diff --git a/util/control_port.py b/util/control_port.py new file mode 100644 index 0000000..8d5b921 --- /dev/null +++ b/util/control_port.py @@ -0,0 +1,42 @@ +# Connects to the control port to test that the private network is working +import getpass +import sys + +import stem +import stem.connection + +from stem.control import Controller + +if __name__ == '__main__': + try: + controller = Controller.from_port() + except stem.SocketError as exc: + print("Unable to connect to tor on port 9051: %s" % exc) + sys.exit(1) + + try: + controller.authenticate() + except stem.connection.MissingPassword: + pw = getpass.getpass("Controller password: ") + + try: + controller.authenticate(password = pw) + except stem.connection.PasswordAuthFailed: + print("Unable to authenticate, password is incorrect") + sys.exit(1) + except stem.connection.AuthenticationFailure as exc: + print("Unable to authenticate: %s" % exc) + sys.exit(1) + + print("List of DAs found:") + for desc in controller.get_network_statuses(): + print("found relay %s (%s)" % (desc.nickname, desc.address)) + + print("List of Relays Found:") + for desc in controller.get_microdescriptors(): + print("found relay %s (%s)" % (desc.identifier, desc.or_addresses)) + + + + print("Tor is running version %s" % controller.get_version()) + controller.close() diff --git a/util/get_consensus.py b/util/get_consensus.py new file mode 100644 index 0000000..2f35a42 --- /dev/null +++ b/util/get_consensus.py @@ -0,0 +1,8 @@ +from stem.control import Controller + +with Controller.from_port(port = 9051) as controller: + controller.authenticate("password") + + print("List of relays found on the network:") + for desc in controller.get_network_statuses(): + print("%s (%s) at %s" % (desc.nickname, desc.fingerprint, desc.address)) diff --git a/util/read_consensus.py b/util/read_consensus.py new file mode 100644 index 0000000..5d3399d --- /dev/null +++ b/util/read_consensus.py @@ -0,0 +1,9 @@ +from stem.descriptor import parse_file +import sys + +try: + path = sys.argv[1] + for desc in parse_file(path): + print('found relay %s (%s)' % (desc.nickname, desc.fingerprint)) +except IOError: + print("File not found. make sure you supply it with a cached consensus file location: %s" % path)