{"id":694,"date":"2021-01-01T17:30:04","date_gmt":"2021-01-01T17:30:04","guid":{"rendered":"https:\/\/dft.wiki\/?p=694"},"modified":"2026-06-09T13:21:03","modified_gmt":"2026-06-09T17:21:03","slug":"setting-up-a-hidden-service-http-in-the-darkweb-tor","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=694","title":{"rendered":"Setting Up a Hidden Service (HTTP) in the DarkWeb (Tor)"},"content":{"rendered":"<p>Tor is a secure network originally created by the US government in the 1990s [<a href=\"https:\/\/en.wikipedia.org\/wiki\/Tor_(anonymity_network)\">Read More<\/a>].<\/p>\n<p>The Tor Project [<a href=\"https:\/\/www.torproject.org\/\">Link<\/a>] continues the research and development of the &#8220;Onion&#8221; network and browser.<\/p>\n<p>Assuming you already know what it is and how it works (or have used it before), let&#8217;s set up an HTTP hidden service on the Tor network.<\/p>\n<p>We will use Linux (Ubuntu 20.04) for the server. It can also be done on a Raspberry Pi (I will try and share that later).<\/p>\n<p>There are 3 main things needed for this process:<\/p>\n<ul>\n<li>A web server\n<ul>\n<li>We will set up a simple web server using Python 3, but Apache2 or NGINX is recommended for a more reliable service.<\/li>\n<li>Note that the web service will only be accessible from localhost (127.0.0.1) because the Tor service also runs on localhost, and the service will be hidden from outside the Tor network.<\/li>\n<\/ul>\n<\/li>\n<li>Tor Network installed on your server\n<ul>\n<li>Note the difference: Tor Browser is a client that browses inside the Tor Network.<\/li>\n<li>You will receive a unique .onion address for the service.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>With that said, let&#8217;s set it up:<\/p>\n<pre>sudo mkdir \/var\/www\/tor_service\r\ncd \/var\/www\/tor_service\r\npython3 -m http.server --bind <strong>127.0.0.1<\/strong> <strong>8080<\/strong><\/pre>\n<p>The last command starts the HTTP server, accessible only at <strong>127.0.0.1<\/strong> on port <strong>8080<\/strong>, serving the <strong>current directory<\/strong>. Feel free to adjust as needed. This command will lock your terminal while the server is running, so leave it open and use a new terminal to continue.<\/p>\n<pre>sudo nano \/var\/www\/tor_service\/index.html<\/pre>\n<p>Add any HTML content, for example:<\/p>\n<pre>&lt;html&gt;&lt;body&gt;Hello World!&lt;\/body&gt;&lt;html&gt;<\/pre>\n<p>Then test your web server:<\/p>\n<pre>curl http:\/\/127.0.0.1:8080<\/pre>\n<p>You should see the plain text of the HTML code.<\/p>\n<p>Now install Tor:<\/p>\n<pre>sudo apt install tor -y\r\nsudo nano \/etc\/tor\/<strong>torrc<\/strong><\/pre>\n<p>If <strong>torrc<\/strong> is not there, try searching for it with <strong>whereis tor<\/strong>.<\/p>\n<p>Look for the lines below, uncomment them, and adjust to match the configuration shown, or reflect any changes you made to your HTTP server.<\/p>\n<pre>HiddenServiceDir \/var\/lib\/tor\/hidden_service\/\r\nHiddenServicePort 80 127.0.0.1:8080<\/pre>\n<p>Start the Tor service and check the address assigned to your server:<\/p>\n<pre>sudo tor<\/pre>\n<p>If no error message appears, the service is running fine. This terminal will also stay locked while Tor is running, so open a third terminal and retrieve the generated address:<\/p>\n<pre>sudo cat \/var\/lib\/tor\/hidden_service\/hostname<\/pre>\n<p>You should see something like:<br \/>\n<strong>4l67wy7uuntt6i4tlmdznqjyqq7rwxrtwddcatkvfc6ivclfxtbndeyd.onion<\/strong><\/p>\n<p>This is your address on the Tor network, think of it as a &#8220;domain&#8221;.<\/p>\n<p>Note that for this exercise you used 3 terminals:<\/p>\n<ul>\n<li>First to run the HTTP server;<\/li>\n<li>Second to run Tor;<\/li>\n<li>Third to check the hostname (.onion address).<\/li>\n<\/ul>\n<p>The first and second terminals must keep running to keep the hidden service active. This works well for testing or simulations, but not for a production environment.<\/p>\n<p>For a more permanent setup, run the HTTP server as a service using Apache2 or NGINX.<\/p>\n<p>To configure Tor to run as a daemon, uncomment the following line in <strong>\/etc\/tor\/torrc<\/strong>:<\/p>\n<pre><strong>RunAsDaemon 1<\/strong><\/pre>\n<p>Also update the following line in <strong>\/lib\/systemd\/system\/tor.service<\/strong>:<\/p>\n<pre>ExecStart=<strong>\/usr\/sbin\/tor -f \/etc\/tor\/torrc<\/strong><\/pre>\n<p>Reboot your system and test everything.<\/p>\n<p>To run multiple services on different ports with different .onion addresses, follow this syntax:<\/p>\n<pre>HiddenServiceDir \/var\/lib\/tor\/hidden_service\/\r\nHiddenServicePort 80 127.0.0.1:80\r\nHiddenServicePort 22 127.0.0.1:22\r\n\r\nHiddenServiceDir \/var\/lib\/tor\/other_hidden_service\/\r\nHiddenServicePort 80 127.0.0.1:8080<\/pre>\n<hr \/>\n<p>Feel free to visit the project <a href=\"https:\/\/dft.wiki\/\">RPi Zero Tor Hidden Service<\/a>.<\/p>\n<hr \/>\n<p>Tip: define the geolocation of the entry and exit nodes.<\/p>\n<pre>sudo apt install tor-geoipdb -y\r\nsudo nano ~\/.local\/share\/torbrowser\/tbb\/x86_64\/tor-browser_en-US\/Browser\/TorBrowser\/Data\/Tor\/torrc<\/pre>\n<p>Append:<\/p>\n<pre>EntryNodes {us} StrictNodes 0\r\nExitNodes {de},{ca} StrictNodes 1<\/pre>\n<p>Country code shortlist:<\/p>\n<pre>AUSTRALIA {au}\r\nBELGIUM {be}\r\nBRAZIL {br}\r\nCANADA {ca}\r\nFRANCE {fr}\r\nGERMANY {de}\r\nHONG KONG {hk}\r\nINDIA {in}\r\nRUSSIAN FEDERATION {ru}\r\nSWEDEN {se}\r\nSWITZERLAND {ch}\r\nUNITED KINGDOM {uk}\r\nUNITED STATES {us}<\/pre>\n<p>See the full list at [<a href=\"https:\/\/sccmrookie.blogspot.com\/2016\/03\/tor-country-codes-list.html\">Link<\/a>].<\/p>\n<hr \/>\n<p><strong>BONUS<\/strong><\/p>\n<p>Configure your web server on the clearnet to inform visitors that it also offers an .onion address:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2841\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2021\/01\/Screenshot_2022-03-13_12-49-11.png\" alt=\"\" width=\"403\" height=\"116\" srcset=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2021\/01\/Screenshot_2022-03-13_12-49-11.png 403w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2021\/01\/Screenshot_2022-03-13_12-49-11-300x86.png 300w\" sizes=\"auto, (max-width: 403px) 100vw, 403px\" \/><\/p>\n<p>NGINX configuration:<\/p>\n<pre>server {\r\n    listen 443 ssl http2;\r\n    listen [::]:443 ssl http2;\r\n\r\n    server_name example.com;\r\n\r\n    ssl_certificate \/etc\/ssl\/fullchain.pem; \r\n    ssl_certificate_key \/etc\/ssl\/privkey.pem;\r\n\r\n    <strong>add_header Onion-Location http:\/\/<span style=\"color: #ff0000;\">&lt;your-onion-address&gt;<\/span>.onion$request_uri;<\/strong>\r\n\r\n    index index.html;\r\n    root \/var\/www\/html;\r\n\r\n    location \/ {\r\n        try_files $uri $uri\/ =404;\r\n    }\r\n}<\/pre>\n<p><strong>Note:<\/strong> only copy and paste the line in bold into your configuration. The rest of the example is just to show where the additional line should be placed. Don&#8217;t forget to restart the web server and verify it worked using a Tor browser.<\/p>\n<pre>sudo nginx -t\r\nsudo nginx -s reload<\/pre>\n<p>APACHE configuration:<\/p>\n<pre>&lt;VirtualHost *:443&gt;\r\nServerName example.com\r\nDocumentRoot \/var\/www\/html\r\n\r\n<strong>Header set Onion-Location \"http:\/\/<span style=\"color: #ff0000;\">&lt;your-onion-address&gt;<\/span>.onion%{REQUEST_URI}s\"<\/strong>\r\n\r\nSSLEngine on\r\nSSLCertificateFile \"\/etc\/ssl\/example.com.cert\"\r\nSSLCertificateKeyFile \"\/etc\/ssl\/example.com.key\"\r\n&lt;\/VirtualHost&gt;<\/pre>\n<p>Test your configuration and reload the web server:<\/p>\n<pre>sudo apachectl configtest\r\nsudo systemctl reload apache2<\/pre>\n<hr \/>\n<p>See also how to Set Up a Tor Node [<a href=\"https:\/\/dft.wiki\/?p=2354\">Link<\/a>].<\/p>\n<p>See also how to create a Tor Snowflake [<a href=\"https:\/\/dft.wiki\/?p=2346\">Link<\/a>].<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tor is a secure network originally created by the US government in the 1990s [Read [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-694","post","type-post","status-publish","format-standard","hentry","category-web"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/694","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=694"}],"version-history":[{"count":13,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/694\/revisions"}],"predecessor-version":[{"id":5803,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/694\/revisions\/5803"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=694"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}