Our experts are always on hand to help answer your questions, get you started, and grow your presence online. You can email us any time
Create your own onion service using Drogon C++ web framework
Tor, an acronym for The Onion Router, is an open-source software that is free to use and promotes anonymous interactions online. It routes internet traffic through a global volunteer-driven overlay network comprising over seven thousand relays. The use of Tor increases the challenge of tracing a user's online activities.
Drogon is a HTTP application framework that's developed using the C++ programming language and supports either C++20 or C++17 with Boost. It's utilized to construct a multitude of web application server programs using C++. Drogon is a versatile, cross-platform framework that is compatible with Linux, macOS, FreeBSD, OpenBSD, HaikuOS, and Windows.
We suggest installing Docker if you're planning to establish an Onion Service and host it yourself. Docker is a software platform designed to facilitate building, testing, and deploying applications with speed. It organizes software into uniform units known as containers, which incorporate all the necessary components for the software's operation, such as libraries, system tools, code, and runtime. Docker enables swift deployment and scaling of applications in any environment, ensuring the smooth running of your code.
Also We suggest utilizing Docker Compose once Docker has been installed. Docker Compose serves as a utility for formulating and executing applications that involve multiple containers. It is instrumental in facilitating a smooth and productive development and deployment process. Docker Compose makes it straightforward to handle your entire application stack, including services, networks, and volumes, through a single, easily understood YAML configuration file. Consequently, all the services from your configuration file can be created and initiated with just one command.
In order to containerize a C++ Drogon Web Application using Docker, you need to download a public Drogon image from the Docker Hub registry. This can be done by executing the below command:
$ docker image pull drogonframework/drogon Using default tag: latest latest: Pulling from drogonframework/drogon aece8493d397: Pull complete b11f61d989b4: Pull complete 58807c8d4ddf: Pull complete 99d8c1dedd58: Pull complete 6eb25abdfcba: Pull complete f6b93a15acd0: Pull complete Digest: sha256:8375b3f136fc875882a781b6d87390378b1a13b1399c79a621274b34a4134ad3 Status: Downloaded newer image for drogonframework/drogon:latest docker.io/drogonframework/drogon:latest
Then, create a folder called 'my_project', and create a folder called 'drogon' and placed inside the 'my_project' folder. You can use below command to create your own C++ Drogon Web Application project. The project name 'my_app' is used to create the Drogon web application project.
$ docker run -v ./drogon:/data/drogon drogonframework/drogon bash -c "cd /data/drogon && drogon_ctl create project my_app && cd my_app/build && cmake .. && make" create a project named my_app -- The CXX compiler identification is GNU 11.4.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/g++-11 - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for C++ include any -- Looking for C++ include any - found -- Looking for C++ include string_view -- Looking for C++ include string_view - found -- Looking for C++ include coroutine -- Looking for C++ include coroutine - not found -- Found Jsoncpp: /usr/include/jsoncpp -- jsoncpp version:1.9.5 -- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libcrypto.so (found version "3.0.2") -- Found c-ares: /usr/include -- Looking for C++ include pthread.h -- Looking for C++ include pthread.h - found -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE -- Found UUID: /usr/lib/x86_64-linux-gnu/libuuid.so -- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.so (found version "1.2.11") -- Found PostgreSQL: /usr/lib/x86_64-linux-gnu/libpq.so (found version "14.9") -- pg inc: /usr/include/postgresql -- Found pg: /usr/lib/x86_64-linux-gnu/libpq.so -- Found SQLite3: /usr/lib/x86_64-linux-gnu/libsqlite3.so -- MySQL Include dir: /usr/include/mariadb -- MySQL client libraries: /usr/lib/x86_64-linux-gnu/libmariadbclient.so -- Found MySQL: /usr/lib/x86_64-linux-gnu/libmariadbclient.so -- Found Hiredis: /usr/lib/x86_64-linux-gnu/libhiredis.so -- Looking for C++ include filesystem -- Looking for C++ include filesystem - found -- Performing Test CXX_FILESYSTEM_NO_LINK_NEEDED -- Performing Test CXX_FILESYSTEM_NO_LINK_NEEDED - Success -- use c++17 -- Configuring done -- Generating done -- Build files have been written to: /data/drogon/my_app/build [ 25%] Building CXX object CMakeFiles/my_app.dir/main.cc.o [ 50%] Linking CXX executable my_app [ 50%] Built target my_app [ 75%] Building CXX object test/CMakeFiles/my_app_test.dir/test_main.cc.o [100%] Linking CXX executable my_app_test [100%] Built target my_app_test
Executing the docker command will mount your host's 'drogon' folder to the container at '/data/drogon'. You can then execute multiple commands using the 'drogonframework/drogon' image. Initially, switch the working directory to '/data/drogon', and then employ the 'drogon_ctl' command to establish a new project named 'my_app'. Following this, proceed to build and compile the project.
Let's look at the 'drogon/my_app/main.cc' file:
#include <drogon/drogon.h> int main() { //Set HTTP listener address and port drogon::app().addListener("0.0.0.0", 5555); //Load config file //drogon::app().loadConfigFile("../config.json"); //drogon::app().loadConfigFile("../config.yaml"); //Run HTTP framework,the method will block in the internal event loop drogon::app().run(); return 0; }
The application use 5555 port to listen the incoming connection. Change the 5555 port to 80 port, then save the file. And rebuild and recompile your project by using below command:
$ docker run -v ./drogon:/data/drogon drogonframework/drogon bash -c "cd /data/drogon/my_app/build && cmake .. && make" -- jsoncpp version:1.9.5 -- Found UUID: /usr/lib/x86_64-linux-gnu/libuuid.so -- pg inc: /usr/include/postgresql -- MySQL Include dir: /usr/include/mariadb -- MySQL client libraries: /usr/lib/x86_64-linux-gnu/libmariadbclient.so -- use c++17 -- Configuring done -- Generating done -- Build files have been written to: /data/drogon/my_app/build Consolidate compiler generated dependencies of target my_app [ 25%] Building CXX object CMakeFiles/my_app.dir/main.cc.o [ 50%] Linking CXX executable my_app [ 50%] Built target my_app Consolidate compiler generated dependencies of target my_app_test [100%] Built target my_app_test
Then, create a default landing page.
echo '<h1>Hello Drogon!</h1>' >> ./drogon/my_app/build/index.html
The configuration of Drogon C++ web framework is ready. Then, create two folders called 'config' and 'hidden_service', and create a new file 'torrc' and placed it inside 'config' folder. The torrc content should be as below:
HiddenServiceDir /var/lib/tor/hidden_service/ HiddenServicePort 80 web:80
This is a Tor config file which configure Tor instance to run a onion hidden service. Your onion service listens the port 80, and redirect the request to the address web:80.
Then, create compose.yaml
services: web: image: drogonframework/drogon volumes: - ./drogon:/data/drogon command: ./my_app working_dir: /data/drogon/my_app/build tor: image: osminogin/tor-simple volumes: - ./config/torrc:/etc/tor/torrc - ./hidden_service:/var/lib/tor/hidden_service
This is the final directory structure looks like:
├── compose.yaml Docker Compose File ├── config Configuration file │ └── torrc ├── drogon Drogon application file │ └── my_app └── hidden_service Tor hidden service file
Following this, execute docker compose up to run the onion service with your own C++ drogon web application.
$ docker compose up [+] Running 3/1 ✔ Network onion-service_default Created 0.2s ✔ Container onion-service-tor-1 Created 0.0s ✔ Container onion-service-web-1 Created 0.0s Attaching to onion-service-tor-1, onion-service-web-1 onion-service-tor-1 | Mar 31 13:51:25.711 [notice] Tor 0.4.8.10 running on Linux with Libevent 2.1.12-stable, OpenSSL 3.1.2, Zlib 1.3, Liblzma 5.4.5, Libzstd 1.5.5 and Unknown N/A as libc. onion-service-tor-1 | Mar 31 13:51:25.711 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://support.torproject.org/faq/staying-anonymous/ onion-service-tor-1 | Mar 31 13:51:25.711 [notice] Read configuration file "/etc/tor/torrc". onion-service-tor-1 | Mar 31 13:51:25.714 [notice] Opening Socks listener on 127.0.0.1:9050 onion-service-tor-1 | Mar 31 13:51:25.715 [notice] Opened Socks listener connection (ready) on 127.0.0.1:9050 onion-service-tor-1 | Mar 31 13:51:25.000 [notice] Parsing GEOIP IPv4 file /usr/share/tor/geoip. onion-service-tor-1 | Mar 31 13:51:25.000 [notice] Parsing GEOIP IPv6 file /usr/share/tor/geoip6. onion-service-tor-1 | Mar 31 13:51:26.000 [notice] Bootstrapped 0% (starting): Starting onion-service-tor-1 | Mar 31 13:51:26.000 [notice] Starting with guard context "default" onion-service-tor-1 | Mar 31 13:51:27.000 [notice] Bootstrapped 5% (conn): Connecting to a relay onion-service-tor-1 | Mar 31 13:51:27.000 [notice] Bootstrapped 10% (conn_done): Connected to a relay onion-service-tor-1 | Mar 31 13:51:27.000 [notice] Bootstrapped 14% (handshake): Handshaking with a relay onion-service-tor-1 | Mar 31 13:51:27.000 [notice] Bootstrapped 15% (handshake_done): Handshake with a relay done onion-service-tor-1 | Mar 31 13:51:27.000 [notice] Bootstrapped 20% (onehop_create): Establishing an encrypted directory connection onion-service-tor-1 | Mar 31 13:51:28.000 [notice] Bootstrapped 25% (requesting_status): Asking for networkstatus consensus onion-service-tor-1 | Mar 31 13:51:28.000 [notice] Bootstrapped 30% (loading_status): Loading networkstatus consensus onion-service-tor-1 | Mar 31 13:51:29.000 [notice] I learned some more directory information, but not enough to build a circuit: We have no usable consensus. onion-service-tor-1 | Mar 31 13:51:29.000 [notice] Bootstrapped 40% (loading_keys): Loading authority key certs onion-service-tor-1 | Mar 31 13:51:29.000 [notice] The current consensus has no exit nodes. Tor can only build internal paths, such as paths to onion services. onion-service-tor-1 | Mar 31 13:51:29.000 [notice] Bootstrapped 45% (requesting_descriptors): Asking for relay descriptors onion-service-tor-1 | Mar 31 13:51:29.000 [notice] I learned some more directory information, but not enough to build a circuit: We need more microdescriptors: we have 0/7489, and can only build 0% of likely paths. (We have 0% of guards bw, 0% of midpoint bw, and 0% of end bw (no exits in consensus, using mid) = 0% of path bw.) onion-service-tor-1 | Mar 31 13:51:30.000 [notice] Bootstrapped 50% (loading_descriptors): Loading relay descriptors onion-service-tor-1 | Mar 31 13:51:31.000 [notice] The current consensus contains exit nodes. Tor can build exit and internal paths. onion-service-tor-1 | Mar 31 13:51:32.000 [notice] Bootstrapped 56% (loading_descriptors): Loading relay descriptors onion-service-tor-1 | Mar 31 13:51:32.000 [notice] Bootstrapped 62% (loading_descriptors): Loading relay descriptors onion-service-tor-1 | Mar 31 13:51:32.000 [notice] Bootstrapped 71% (loading_descriptors): Loading relay descriptors onion-service-tor-1 | Mar 31 13:51:32.000 [notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits onion-service-tor-1 | Mar 31 13:51:33.000 [notice] Bootstrapped 90% (ap_handshake_done): Handshake finished with a relay to build circuits onion-service-tor-1 | Mar 31 13:51:33.000 [notice] Bootstrapped 95% (circuit_create): Establishing a Tor circuit onion-service-tor-1 | Mar 31 13:51:33.000 [notice] Bootstrapped 100% (done): Done
Your onion service URL is in the file ./hidden_service/hostname. Open the Tor browser, and enter your onion service URL.
Your onion service, with C++ Drogon web framework is configured successfully.
Link to Drogon C++ web framework
Our experts are always on hand to help answer your questions, get you started, and grow your presence online. You can email us any time