Making a Tor Version of Your Site

Making a Tor Version of Your Site

A short intro to making your site available on tor


Converting your clearnet service (that’s Tor lingo for a normal website) to an onion service might be easy or it might take a lot of work depending on your service and how it functions.

Tor users have a big aversion to JavaScript, as the whole point of Tor is anonymous browsing. Popular uses of JavaScript include tracking and fingerprinting, which defeats the main purpose of Tor.

Creating an onion service would allow users to anonymously browse your website without being tracked by any tracking service, government agency or any other prying eyes.

Setting Up Tor

Note: this section is platform independent as it’s only the configuration file for Tor. If any issues arise when installing, I’d recommend browsing the internet.

There are two ways of obtaining Tor, either by download Tor’s source code from here and built it yourself locally or install it via. package manager.

After installation there should be a configuration file under /etc/tor/torrc, this is the default configuration file the Tor program will read from. There are a couple things to edit here, they are:

  • A name for the node
  • A control port with password
  • An email address to be reached by
  • Our hidden service configuration
  • Logging

See below for the configuration file

# shorthand: 1 = true, 0 = false
# A nickname for the relay
Nickname turtletechies123

# email to address the owner of the node

# Explicitly stating we're not an exit nor entry node
ExitRelay 0
BridgeRelay 0

# set the data directory to somewhere the tor process can read/write/exec to, e.g.,
# DataDirectory /home/tor
# DataDirectory /data/tor
# DataDirectory /var/lib/tor

# Our hidden service
HiddenServiceDir /var/lib/tor/<your-website>
HiddenServicePort <incoming port> localhost:<server port>
# HiddenServicePort 443 localhost:8080

# Logging info (optional)
Log notice file /desired/output/path
Log debug file /desired/output/path

# Monitor the process using an application like Nyx
CookieAuthentication 1

# a hashed password via. tor's command line
HashedControlPassword 16:--------------------------------

# run the process as a daemon
RunAsDaemon 1

Some key things to note for the hidden service, the HiddenServiceDir contains information and cryptographic keys for your onion service.

The line specifies a virtual port which is the port your onion service will be using (e.g., long-onion-link.onion:8080) and will redirect that incoming traffic to localhost:8080 (or whatever port your web server is listening on).

Make sure that any directory which Tor uses has strict permissions, Tor does not like to share its files.

sudo chmod 700 /directory/being/used/by/Tor

See the Tor Project’s website for more about hidden services.

Advertising your Hidden Service

There are many ways we can accomplish this but the main one is to inject our onion link into the HTTP headers sent to the client. But there are some conditions which need to be met first:

  • The Onion-Location value must be a valid URL with http: or https: protocol and an .onion hostname

  • The webpage defining the Onion-Location header must be served over HTTPS

  • The webpage defining the Onion-Location header must not be an onion site.

You can find some code snippets for nginx, Apache and Caddy from the official Tor Project website.

You can also use the <meta> tag in your HTML page by adding

        <meta http-equiv="onion-location" content="http://linktoyouronionservice.onion" />

But this still has to conform to the three requirements stated previously.

What Changes?

To your website? Nothing really, the only thing you’ve done is allow incoming connections from the Tor network. Cookies, sessions will largely work the same. Note that I say “largely” because this depends on the level of JavaScript you’re using.

Working with Tor

This is more of a broad topic, there are several things about Tor that are different that the clearnet. One difference is that most users (should) have JS disabled by default, this is a big issue for most sites since they rely heavily on JavaScript to build small components and handle small logic all the way to building their entire website on the fly (frameworks like React, Angular, Vue, etc.).

If your service requires some level of identification for users, it’s not the end of the world. The anonymity provided by Tor is practically impossible to crack by yourself, but there are ways to work around this fact.

Things to Consider

The whole point of the Tor network is to anonymize its users and a good portion of security relies on identifying users or managing connections. That being said it’s important to note, any user would practically never have the exact same IP nor route they took to get to your website, twice.

For incoming connections, imagine a bottle neck. On the clearnet, you’re receiving connections from thousands of different IPs, whereas via. the hidden service, it’s just one. This IP would usually be localhost or maybe if you got fancy with your configuration it’s coming from an IP on your local network.

Which means you can’t identify a user via. a connection. Since users also disable JavaScript, and the Tor browser is designed to be generic, you can’t really fingerprint users either.

This might affect things such as Google Analytics (I think it’s safe to say that if people are using Tor they are not a fan of Google) since each connection would come from your local IP. Session variables and cookies would still work the same, although most users clear their cookie caches often.

The noscript Tag

In the modern age, JavaScript has somewhat of a bad reputation because it is used to serve ads and tracking services. There are popular plugins to disable JS such as UBlock Origin to block tracking, noscript to block JavaScript and most, if not all browsers have an option to disable JavaScript.

It’s important to note that JavaScript, like any other programming language or framework, is a tool. It’s how it’s used which determines whether it’s good or bad.

Here is some sample code to demonstrate a <noscript> tag. Here the code would notify users what features of the website will not work without JavaScript. A developer can leverage the power of plain HTML and CSS to implement something better.

        // launch your React or Angular script ...
        <section class="nojs">
                <!-- insert extra content here -->
                <p>The following features will <bold>not</bold> work without javascript </p>

The thing with the noscript tag is that the front-facing JavaScript would be disabled since the browser wouldn’t allow the execution of JavaScript within the browser. What’s more important is that the JavaScript running on the backend (if there is any) still runs fine. So your Node.JS & ExpressJS tech stack running as your backend would be completely unaffected.

A great example of handling disabled JavaScript is StackExchange (and their similar sites). They have a simple, red banner at the top of their websites which plainly states: “StackExchange works best with JavaScript enabled”. The website itself is not impaired by the fact that a user has JavaScript disabled.

What developers could do is test if the user has JavaScript when they connect to a website (test for the absence of an Ajax call, or maybe the user upon entry is directed to a reverse proxy), the website will then notify the backend if the user has JavaScript disabled which would then either;

  • redirect to an non-JavaScript service (kinda like what DuckDuckGo does)

  • use a template, build a the response on the backend and send the compiled .HTML response back to the user

See more about the <noscript> tag here.

Dealing with Bots

There are many bots on the internet, some good and some, very annoying. To fight against bots, you could implement a Captcha system to view their site, something like what Cloudflare does to prevent DDoS attacks or bot connections.

Another idea is after the user verifies with Cloudflare; you redirect them to your website without JS. A nice service to the Tor network since most users dislike the usage of JavaScript.

Dealing with Anonymity

Maybe you’re running a chat service, and a banned user notices that your website has a Tor site. They might use that service to make an anonymous account and go back to harassing users or whatever their intentions are.

You could implement fingerprinting but this would only get you so far since the Tor browser is designed to be generic, making fingerprinting next to impossible.

A solution could be only allowing users to sign-up over the clearnet. Over the clearnet you’d have a much easier time banning bad users. Unless they use a VPN or something else to obscure their real IP, then you could block that incoming connection if it’s a known VPN server.

One thing to note, you can easily identify who a user is on Tor if they sign into an account with personal information on your website. As a general rule, only the account creator would know the credentials. To that same token, if the name is “John/Jane Doe” or some other alias it wouldn’t provide much information.


When making a site available via Tor, there is one very important security consideration to take into account: all incoming traffic will appear from the IP address (localhost). So if you try to protect any internal endpoints by only making them available to local IPs, they make become exposed. This is called an SSRF (Server Side Request Forger) exploit.

For more info:


Creating an onion service with Tor is beneficial since it enables more anonymous traffic on the internet and with this influx in traffic, hopefully it would encourage more people to pursue more alternative internet browsing options.

Using the ideas provided in this article you could migrate your clearnet service over to Tor. Tor is an amazing tool to keep users anonymous, but keep in mind the anonymity portion is largely on the user to not unveil themselves, keep that in mind.