This will be happening more and more frequently in the online world: people get silenced. If you're a ruler, it's tempting to selectively deliver only certain information and let's face it - surface web is perfectly equipped for such scenarios. Providers of services have too much to lose if disobey. This is just how power works. But that's a bit different topic...
Today we're gonna talk about the world without centralised authorities, the world of Tor hidden services.
Enter the .onion!
In Tor we don't use standard domain names like cz
or eu
. We use specialised .onion
generic name that is resolvable only in Tor network. Compared to standard domain names it has one major difference beyond the scope of the visibility - there's no vendor where you have to purchase a name for you service.
This is how it works - you create a hidden service, a new keypair is generated and part of the public key is then used as your .onion
name. You can read more about the mechanism in this post.
Please read previous 2 paragraphs again - there's no authority that's responsible for the allocation of names. And when there's no authority - you can't approach it and make it obey with the force 👊
Then you just point Tor daemon to your webserver and voila - everyone with Tor browser (or alternative configuration with SOCKS5 proxy) can access your hidden service!
Now let's create our first hidden service. That's gonna be fun.
Part I: server
We need some server first. It can be anything, you can use tiny Raspberry Pi or you can purchase some VPS from Public Cloud providers. I don't have any specific recommendations here. Server in your homelab is more decentralized, on the other hand VPS is easy to obtain. It's up to you.
I'm gonna use VPS purchased from Digital Ocean pre-installed with the latest LTS Ubuntu.
In a couple of seconds I can connect with ssh there and proceed with the configuration!
Part II: application
In this tutorial we'll be serving some dummy content from the application written in Go. For the sake of simplicity I'm gonna use some snippets from the Fiber framework's homepage. So here we go, this is our application.
package main
import "github.com/gofiber/fiber/v2"
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World 👋!")
})
app.Listen(":3000")
}
Once again, this is Go but you can write your application in any available tool. And of you want to serve static content - use Caddy or Nginx.
So now I'm gonna build and test the app:
go mod init main
go mod tidy
go build main.go
./main&
curl localhost:3000
This is what we get as the output:
Hello, World 👋!
Part III: supervision
In the modern operating system we can always use some way how to supervise your applications. This is extremely important and I'm gonna give you one specific example: when your server restarts, you want to make sure that applications starts together with the server.
In the case we use Ubuntu so systemd service unit needs to configured.
So let's move the application to some well-known path
mkdir /opt/app
mv main /opt/app/main
and create the systemd service unit in /etc/systemd/system/app.service
file:
[Unit]
Description=App
After=network.target
[Service]
Type=simple
ExecStart=/opt/app/main
[Install]
WantedBy=multi-user.target
Now we can enable and start the service with systemctl
commands:
systemctl enable app
systemctl start app
Status of the service can be verified by invoking systemctl status app
:
● app.service - App
Loaded: loaded (/etc/systemd/system/app.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2022-03-02 18:08:29 UTC; 2s ago
Main PID: 2289 (main)
Tasks: 4 (limit: 1132)
Memory: 1.3M
CGroup: /system.slice/app.service
└─2289 /opt/app/main
Part IV: Tor daemon
All the stuff we were doing till now was pretty much the same as you'd do for standard surface web app, right? So let's make it special. To do so we need to install Tor daemon first.
In this Ubuntu 20.04 we just need to create a new apt source in /etc/apt/sources.list.d/tor.list
deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org focal main
deb-src [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org focal main
add public key to the keyring
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null
and install the package:
apt-get update
apt-get install tor -y
If you're using different operating system - check out the official documentation. You know the drill I guess 😁
As the result we have Tor daemon running!
systemctl status tor
● tor.service - Anonymizing overlay network for TCP (multi-instance-master)
Loaded: loaded (/lib/systemd/system/tor.service; enabled; vendor preset: enabled)
Active: active (exited) since Wed 2022-03-02 18:16:30 UTC; 1min 28s ago
Main PID: 2959 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 1132)
Memory: 0B
CGroup: /system.slice/tor.service
Part V: pointing Tor to our app
And this is the very last part of this tutorial. Tor just needs to be configured to "advertise" our application to the network.
Open the main configuration file /etc/tor/torrc
and add following lines to the respective part of the configuration.
HiddenServiceDir /var/lib/tor/app/
HiddenServicePort 80 127.0.0.1:3000
The second line basically says that incoming traffic on port 80 should be routed to localhost:300. And this is the port where the simple app listens.
Tor daemon needs to be restarted first with systemctl restart tor
command and whent it's up again we can inspect /var/lib/tor/app/
directory - the home directory of our hidden service.
ls /var/lib/tor/app/ -lah
total 24K
drwx--S--- 3 debian-tor debian-tor 4.0K Mar 2 18:22 .
drwx--S--- 4 debian-tor debian-tor 4.0K Mar 2 18:23 ..
drwx--S--- 2 debian-tor debian-tor 4.0K Mar 2 18:22 authorized_clients
-rw------- 1 debian-tor debian-tor 63 Mar 2 18:22 hostname
-rw------- 1 debian-tor debian-tor 64 Mar 2 18:22 hs_ed25519_public_key
-rw------- 1 debian-tor debian-tor 96 Mar 2 18:22 hs_ed25519_secret_key
The last 2 lines are interesting, this is the key pair I was talking about. Please note that private key needs to be kept in secret, anyone with access to this key can use your onion name for some nasty s**t! And when we talk about the name, let's just check the contents of the hostname
file.
cat /var/lib/tor/app/hostname
ocig6kqiahyictb5y7o37ympfragi4nlzimuylwsfco76ksi2l5edvyd.onion
And this is, ladies and gentlemen, a domain name we can use from Tor browser. Let's do it.
Result
Install Tor browser or Brave (Brave needs to be launched in specialised Tor mode) and enter onion name to the address bar.
This is the service we were working on! It looks just like any other web application but it has one major feature - putting this down requires much more effort that the surface web equivalent.
Now you can share your fantastic content even with the folks who lives in less free countries 🔥🔥🔥
Do you need any help with Tor hidden service? Don't hesitate to contact me. I'm 100% committed to make world a better place through the free speech and better privacy ❤️
Title image: https://www.deviantart.com/wuphaz/art/Tor-wallpaper-682786904
Top comments (1)
Thanks very useful! Do you know how to setup a fiber server on a remote VPS to do just to forward a URL get request?
I am running a home service via Tor, and I would like a mobile app to access it, the problem is that the app only access clearnet urls. Can I set up a remote VPS that receives get requests and forwards them to my onion home address?