[Solved] Running Subdomains on .onion services

Hi I searched for a config for tor on this forum and it kind of worked. I was able to reach the root of the onion service but when I tried to set up Subdomains it failed because caddy complained, that it listens for the Hiddenservice port on two configuration blocks.

I tried to run multiple hidden services with the same hostname but tor doesn’t like that at all.

This is my current configuration and I would like to setup Subdomains Like www.xxxxxxxxxx.onion and pgp.xxxxxxxxxxxx.onion

(onion) {
  prometheus
  log /var/log/caddy/access.log {
    ipmask 255.255.255.0 ffff:ffff:ffff:fff0::
  }
  errors /var/log/caddy/error.log
  tls off
}

http://conorblc245kc43q.onion:80 :8868 {
  import onion
  root /var/www/onion
}

Also I found a plugin for caddy that adds support for opportunistic onion services - would this solve my problem?

And is it possible to serve them with a TLS certificate so it can benefit from http/2 ?

Hi @conorlburns,

Can you elaborate further on these statements:

It’s a little difficult to guess at what to troubleshoot without specifics here. Try to establish, in detail:

  • What you tried
  • What you expected to happen
  • What happened instead

Including full error messages and output, if possible.

I did find these resources:

How can we help? | Tor Project | Support
https://gist.github.com/mtigas/565718bbb928ce439e95

They indicate to me that a Tor hidden service simply reverse proxies from its virtual port to a real port on your host, and that the Tor service doesn’t distinguish subdomains. Instead, the browser sends the subdomain as part of the Host header, which Caddy can handle; you should just need to add the site label for them.

Ok I tried to duplicate the nginx setup from the gist with caddy and got this:

mail.conor-burns.com systemd[1]: Started Caddy HTTP/2 web server. 
Mar 06 07:44:33 mail.conor-burns.com caddy[13655]: 2019/03/06 07:44:33 error inspecting server blocks: duplicate site key: :8868
Mar 06 07:44:33 mail.conor-burns.com systemd[1]: caddy.service: Main process exited, code=exited, status=1/FAILURE
Mar 06 07:44:33 mail.conor-burns.com systemd[1]: caddy.service: Failed with result 'exit-code'.                                                                                        

With this config:

http://www.conorblc245kc43q.onion:80 :8868 {
  import onion
  redir https://http://conorblc245kc43q.onion:80{uri}
}
http://conorblc245kc43q.onion:80 :8868 {
  import onion
  root /var/www/onion
}
http://pgp.conorblc245kc43q.onion:80 :8868 {
  import onion
  root /var/www/onion
}

(I forgot to change the root but it was /var/www/pgp for pgp.xxxxxxxx.onion when I testet it yesterday)

Before I asked here I ran multiple Hiddenservices under the same hostname so I had 3 different ports to listen on but caddy or tor mixed them up so when I visited pgp.xxxxxxxxxx.onion I got xxxxxxxxx.onion and with www.xxxxxxxxx.onion I got pgp and with the root I got the root.

The cause of that issue is that you have three technically separate site definitions, and each one has :8868 as a site label. Multiple site definitions can’t share the same label between them.

Ok and how am I supposed to run different site roots on Subdomains with tor?

There needs to be some way Caddy can differentiate.

Right now, in plain English, you’re telling Caddy:

  1. For a request via any scheme, for any hostname, for any path, on port 8868: serve the first site.
  2. For a request via any scheme, for any hostname, for any path, on port 8868: serve the second site.
  3. For a request via any scheme, for any hostname, for any path, on port 8868: serve the third site.

Do you see the problem? It’s ambiguous. There’s no way for Caddy to tell which of the three sites you actually want to serve here when a request comes in that matches.

You need to differentiate the sites. Maybe by including the hostname?

I wrote that I tried running the hidden services with three different ports…

With this tor config

HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8869             
HiddenServicePort 80 127.0.0.1:8868
HiddenServicePort 80 127.0.0.1:8867

And then used the config from above with different ports

The Caddyfile you posted above, with the duplicate site key: :8868 error, didn’t have those three separate ports; you repeated 8868 three times.

Yeah but I said that I tried it with different ports but tor didn’t like that

Here: I tried that but it just mixed stuff up

I don’t know what the troubleshooting procedure is for Tor not liking something.

I can tell you that Caddy can host multiple sites on a single port, differentiating by hostname, or scheme, or path, or any combination thereof. As long as your clients are regular modern HTTP browsers, you should be able to rely on Caddy to respond correctly for a given request.

If that’s not the case, post some details (the Caddyfile you’re using, the problem that’s occurring, what requests you’re sending to Caddy, and what error messages you’re getting) and I can try to figure out what’s going wrong.

Thanks for you reply I really appreciate your help!
I’ll try to do my best at providing the required configs and errors:

Torrc:

RunAsDaemon 1
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8869
HiddenServicePort 80 127.0.0.1:8868
HiddenServicePort 80 127.0.0.1:8867

Is this the right way to run multiple Subdomains for the same root domain with Tor?

Caddyfile:

(onion) {

  prometheus
  log /var/log/caddy/access.log {
    ipmask 255.255.255.0 ffff:ffff:ffff:fff0::
  }
  errors /var/log/caddy/error.log
  tls off
}
http://www.conorblc245kc43q.onion:80 :8868 {
  import onion
  redir https://http://conorblc245kc43q.onion:80{uri}
}
http://conorblc245kc43q.onion:80 :8869 {
  import onion
  root /var/www/onion
}
http://pgp.conorblc245kc43q.onion:80 :8867 {
  import onion
  root /var/www/pgp
}

Tor behavior when accessing http://conorblc245kc43q.onion: Everything alright

Tor behavior when accessing http://pgp.conorblc245kc43q.onion: Wrong site - serving the root site (not redirecting just serving the same content)

Tor behavior when accessing http://www.conorblc245kc43q.onion: Everything alright - redirecting to root

Now when I restart caddy it gets really crazy.
When I visit root everything is fine but when I visit www.xxxx.onion I get the content for the pgp subdomain and for the pgp subdomain I get the root redirect what www would normally do. And if refresh the site multiple times it will so sometimes load the root or the pgp or the www. It’s completely random.

I’m guessing that Tor listens on 80 on the outside and redirects that to one of the 3 ports randomly and then caddy does everything right and serves the content for that specified port. How would it be possible to fix Tor in a way that it gives caddy the right port.

Yeah, this is the impression that I’m getting.

I think it’s best to go simpler, not more complex. Lets strip down all the port confusion; just use 80 for everything, all subdomains.

Try:

RunAsDaemon 1
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:80

And then use Caddy to differentiate by hostname.

http://conorblc245kc43q.onion {
  # Config for root domain
}

http://www.conorblc245kc43q.onion {
  # Config for www subdomain
}

http://pgp.conorblc245kc43q.onion {
  # Config for pgp subdomain
}

Ok great that works but why is caddy now able to listen on port 80 on 3 server blocks?

It was doing that in your earlier configurations, too. It’s generally referred to as virtual hosting, or vhosts. It combines all the sites that want to be served on the same port into one HTTP listener on port 80, and then when a client makes a request, Caddy uses the details of that request to determine which site to serve, much like other modern web servers.

Ahh now that is genius! And it’s not able to do that for different ports am I right?

I mean, you can certainly serve the same site on different ports!

For example, this would serve your site over HTTP on ports 80 as well as 8080:

http://example.com, http://example.com:8080 {
  # Site configuration
}

You can serve different site versions for the same hostname on different ports instead, if you like:

http://example.com {
  # Config for port 80
}

http://example.com:8080 {
  # Config for port 8080
}

You can even have Caddy serve a different site entirely depending on which path the client requested.

http://example.com {
  # This site gets served for most requests
}

http://example.com/foo {
  # This site gets served if the path starts with `/foo`
}

The four aspects of the request you can use to determine which site to serve are the hostname (e.g. example.com, or subdomain.example.com), the path (e.g. /foo), the scheme (i.e. HTTP or HTTPS), and the port.

One important caveat: Caddy can’t have multiple schemes on the same port. You can’t serve a HTTPS site on a port that already serves HTTP.

That’s great and if I want to serve
Http://Example.com:8080
Http://Sub.Example.com:8080
Http://Www.Example.com:8080
Would this still work with Tor or do I have to listen on 80 so caddy doesn’t complain that it’s not listening and 8080 so Tor can listen?

I’m not sure what ports Tor actually uses to communicate, but I’m assuming it’s treated as an additional interface of some kind.

Anyway, if you move all your sites to 8080, I think you’ll need to edit your .torrc.

Try HiddenServicePort 80 127.0.0.1:8080 if you’re going to have Caddy listen on port 8080.

Yeah that’s what I would love to do bit if I remember correctly caddy has to listen on 80 too so it doesn’t complain about not listening on that interface