· All Posts · All in OpenBSD · All in Tor · All in Server

Hosting Tor Hidden Services with Vanity .onion Addresses

Onion services, which are part of the “dark web”, are interesting in a number of different areas outside crime. The United States Naval Research Laboratory developed The Onion Routing Protocol in the mid 1990s to protect U.S. intelligence communications online. It was further developed and received a lot of funding from DARPA, the US State Department’s Internet Freedom Initiative, the EFF and several other organizations over the years. The Tor Project was founded as a non-profit organization in 2006. In a world with increasing censorship, tracking, privacy intrusions and surveillance, Tor provides a way to remain anonymous, access possibly restricted or sensitive content and offer great educational material.

The anonymous internet cartogram 2015

The Tor Network

The tor network is built by clients and server. The Tor Browser enables the client to access the network and to browse both the clear and dark net anonymously. A hidden service is a site you visit on the Tor network with end to end encryption and privacy where the owner of the service anonymous too. A lot of currently available services are very volatile and most don’t stay up for very long (see the Lindy Effect). Few onion services ever become well known and often for the wrong reasons. I write up this page as educational material and for my own notes on how to set up Tor v3 hidden services on OpenBSD servers.

Note that onion services provide adequate security against most real life adversaries that will try to deanonymize you. If a highly motivated adversary with deep pockets like governments are after the service you will need to add more layers of anonymity and purchase servers and bandwidth for hosting with crypto currency and be careful even when you ssh into your machine to cloak your entry IP.

Generate a Vanity v3 Hidden Service Onion Address

Onion addresses are an encoding of a hash of the public key of the service. Note that completely random addresses as well as generated names are easily spoofed, since the visitor clicking on a link somewhere out there can be tricked by the seemingly right .onion prefix without checking the whole address. We generate a custom .onion address only to have a more recognizable address in a list of addresses. Tor Onion v3 hidden services addresses follow torspec/224.

I’m using the tool mkp224o, named after the proposal, which allows to produce a (partially) customized vanity .onion address using a brute-force method. We can clone the source code from GitHub and build it:

git clone

Then we brute force addresses with the prefix noxim, which should take seconds given it’s only 5 characters.

mkdir -p keys
./mkp224o -d ./keys noxim

of which I used the last one and copied it to the server:

scp -r keys/noximhkcqevri46e2kuthman5o6emplfcevppx3hvsvu55qcygj5elyd.onion

The files of interest are


On the server we copy the private key and hostname into it’s place for use in the later step:

doas mkdir -p /var/tor/hidden_service
doas cp hostname /var/tor/hidden_service
doas cp hs_ed25519_secret_key /var/tor/hidden_service/
doas cp hs_ed25519_public_key /var/tor/hidden_service/
# set permissions
doas chown -R _tor:_tor /var/tor/
doas chmod -R 700 /var/tor

Note that we will want to backup this key if we plan to keep this service around.

Setup Tor and the Hidden Service

Install the tor service:

doas pkg_add tor

Edit /etc/tor/torrc, I show you the output of grep -v -E '^#|^$' /etc/tor/torrc here, all uncommented and non blank lines:

Log notice file /var/log/tor/notices.log
RunAsDaemon 1
DataDirectory /var/tor
HiddenServiceDir /var/tor/hidden_service/
HiddenServiceVersion 3
HiddenServicePort 80
User _tor

Ensure the tor service has permissions to write to the log directory from the config:

mkdir -p /var/log/tor
doas chown -R _tor:_tor /var/log/tor/
doas chmod -R 755 /var/log/tor

Then start and enable the tor service

rcctl start tor
rcctl enable tor

If it doesn’t start because of permission issues or otherwise, you can try to run it from the command line to get a hint of what might be wrong: doas -u _tor /usr/local/bin/tor.

I’m adding the log file to log rotate and add the following line to `/etc/newsyslog.conf':

# logfile_name          owner:group     mode count size when  flags
/var/log/tor/notices.log                644  7     250  *     Z

Serve content on the .onion address with httpd

Then we configure httpd with another virtual server section for our hidden service v3 .onion address. Make sure to listen only on localhost to avoid leakage into the local network.

server "noximhkcqevri46e2kuthman5o6emplfcevppx3hvsvu55qcygj5elyd.onion" {
    listen on port 8080
    root "/htdocs/"

Note that I use the very same content that I serve and documented before with httpd over https and the gemini protocol.

Test if the config is workable with doas httpd -n, then restart httpd:

doas rcctl restart httpd

Now we should have noxim…x.onion available through the tor browser. In our access.log we will see the virtual server getting hit from localhost

noximhkcqevri46e2kuthman5o6emplfcevppx3hvsvu55qcygj5elyd.onion - - [24/Jul/2021:13:56:49 +0000] "GET / HTTP/1.1" 200 4350

In a recent post on web analytics dashboard with GoAccess I’m piping the access logs to GoAccess for server side analytics.

Published on Saturday, Jul 24, 2021. Last modified on Tuesday, Jun 28, 2022.
Go back

If you’d like to support me, follow me on Twitter or buy me a coffee. Use Bitcoin
BTC address: bc1q6zjzekdjhp44aws36hdavzc5hhf9p9xnx9j7cv