Tor hidden services (also called onion services) allow you to host websites, APIs, or any network service that is accessible exclusively through the Tor network. Unlike conventional servers that expose your IP address to the internet, hidden services route all traffic through Tor’s onion routing, concealing both your location and the identity of your users. This guide walks you through setting up a basic hidden service, configuring it securely, and integrating it into your development workflow.

Prerequisites

Before you begin, ensure you have access to a Linux server (Debian, Ubuntu, or Fedora are all well-supported) and the Tor software. You will need root or sudo access to configure the service. This guide assumes you are comfortable working from the command line and understand basic networking concepts.

Installing Tor

Most Linux distributions include Tor in their default repositories. On Ubuntu or Debian:

sudo apt update
sudo apt install tor

On Fedora or RHEL-based systems:

sudo dnf install tor

Verify the installation by checking the Tor version:

tor --version

You should see output indicating Tor is installed. If you need a newer version, consider using the Tor Project’s official repository.

Configuring Your First Hidden Service

The Tor configuration file is located at /etc/tor/torrc on most Linux systems. Open this file with your preferred text editor:

sudo nano /etc/tor/torrc

Scroll down to the section labeled ## This section is for onion services. You will find commented-out examples. Add the following configuration to create a basic hidden service:

HiddenServiceDir /var/lib/tor/my_hidden_service
HiddenServicePort 80 127.0.0.1:8080

Breaking this down:

Save the file and restart Tor:

sudo systemctl restart tor

Retrieving Your Onion Address

After Tor restarts, check the hidden service directory for the generated hostname:

sudo cat /var/lib/tor/my_hidden_service/hostname

This command returns a string ending in .onion — your service’s public address. Share this address with users who have Tor Browser installed. They can access your service by entering the .onion address directly in the Tor Browser address bar.

Running a Web Server for Your Hidden Service

Your hidden service needs a local web server to serve content. A simple Python HTTP server works well for testing:

# Run on port 8080 to match our Tor configuration
python3 -m http.server 8080 --directory /var/www/html

For production deployments, consider using nginx or Apache. Configure your web server to listen only on localhost (127.0.0.1) to prevent accidental exposure of your content outside the Tor network.

Security Hardening for Hidden Services

Running a hidden service requires additional security considerations beyond a standard web server.

Disable Directory Information Leakage

By default, Tor nodes can learn about your hidden service through directory requests. Add the following to your torrc to reduce this exposure:

HiddenServiceDir /var/lib/tor/my_hidden_service
HiddenServicePort 80 127.0.0.1:8080
HiddenServiceVersion 3

Using version 3 onion addresses provides improved cryptography and better resistance to enumeration attacks compared to version 2 addresses.

Restrict Access by Client Authorization

For private services accessible only to authorized users, configure client authentication:

HiddenServiceDir /var/lib/tor/private_service
HiddenServicePort 80 127.0.0.1:8081
HiddenServiceVersion 3
HiddenServiceAuthorizeClient stealth myapp

This configuration creates a stealth authorization scheme named “myapp”. After restarting Tor, retrieve the client authentication line from the hostname file:

sudo cat /var/lib/tor/private_service/hostname

The output includes an authentication string that authorized clients add to their Tor configuration. Users must configure this in their torrc:

ClientOnionAuthDir /var/lib/tor/authdir

Place the authentication file in the specified directory with the format hostname:port=key. This ensures only authorized clients can reach your service.

Run Tor in a Container

For isolated deployments, run Tor inside a Docker container:

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y tor && rm -rf /var/lib/apt/lists/*
COPY torrc /etc/tor/torrc
RUN mkdir -p /var/lib/tor/hidden_service
RUN chown -R debian-tor:debian-tor /var/lib/tor
USER debian-tor
CMD ["tor"]

Build and run the container:

docker build -t tor-hidden-service .
docker run -d -p 127.0.0.1:9050:9050 --name my-tor-service tor-hidden-service

This approach keeps your Tor installation isolated from your host system.

Automating Deployment with Systemd

Create a systemd service to manage your web application alongside Tor:

[Unit]
Description=My Hidden Service Web App
After=network.target tor.service
Requires=tor.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

This ensures your application starts after Tor is ready. Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp

Testing Your Hidden Service

From your local machine, install Tor Browser and navigate to your .onion address. Verify that:

You can also test from the command line using torsocks:

torsocks curl http://your-onion-address.onion

This confirms your service works for users connecting through Tor.

Performance Considerations

Hidden services introduce latency because traffic bounces through multiple Tor nodes. To optimize:

Summary

Setting up a Tor hidden service involves installing Tor, configuring your torrc file, and ensuring your local web server is properly secured. For developers, the key steps are using version 3 onion addresses, restricting access through client authorization when needed, and running services in isolated environments. With your hidden service running, you can offer access to your application without revealing your server’s location or exposing it to the broader internet.

Built by theluckystrike — More at zovo.one