[Solved] Running Subdomains on .onion services

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

You might be thinking of Automatic HTTPS.

When you’re letting Caddy manage your certificates, in order to requisition them, it needs to bind to ports 80 and/or 443. There’s ways of getting around that and still getting certificates (port detouring, DNS challenge, etc) but I don’t think they’ll be relevant to you; you’re only serving on HTTP, so Automatic HTTPS is disabled for those sites.

Unless you’re running another site in your Caddyfile that DOES quality for Automatic HTTPS, Caddy won’t complain about not getting port 80.

I actually run DNS challenge because I got the letsencrypt ratelimit:
https://github.com/Conor-Burns/caddy-conf/blob/master/Caddyfile

I also use wildcards for the smaller domains for the sake of simplicity.

Excellent! Caddy should then be quite happy to serve your sites on whatever port you like.

That’s great thank you so much for your help!

And is it possible to minify my caddyfile by serving some of the Subdomains that serve static content with labels?

Do you mean that they serve the same static content?

If you’re serving the same content, you can add multiple labels to a single site definition, just like the first example I gave earlier: [Solved] Running Subdomains on .onion services - #17 by Whitestrake

Like this:

https://*.conor-burns.com{
  include wc
  root /var/www/all # in that directory are the directories stats, pgp, dev, pw with their index.html
  rewrite {
    to /{label1}{uri}
  }
}

Ahh yeah, like the other thread we’ve been talking in :smiley:

You can do that. Based on that Caddyfile, when you browse to stats.conor-burns.com, it’ll serve content from /var/www/all/stats on your disk.

Yeah exactly I tried that when I saw it in the thread but I get this error cannot convert domain to a valid wildcard

There should be more to that error message.

Can you post the full line, as well as your full Caddyfile (in particular, the content of the wc snippet)?

Wildcarding with HTTP is simple; with HTTPS, things get a bit more complicated with LetsEncrypt, but you’re already aware of that if you’re already using wildcard certs.

Ok I pushed the config to GitHub and this is the error:

Main PID: 32140 (code=exited, status=1/FAILURE)

Mar 07 02:31:59 mail.conor-burns.com systemd[1]: Started Caddy HTTP/2 web server.
Mar 07 02:31:59 mail.conor-burns.com caddy[32140]: 2019/03/07 02:31:59 [INFO][FileStorage:/etc/ssl/caddy] Started certificate maintenance routine
Mar 07 02:31:59 mail.conor-burns.com caddy[32140]: 2019/03/07 02:31:59 /etc/caddy/Caddyfile:16 - Error during parsing: Cannot convert domain name '*.conor-burns.com' to a valid wildcard: already has a wildcard label
Mar 07 02:31:59 mail.conor-burns.com systemd[1]: caddy.service: Main process exited, code=exited, status=1/FAILURE
Mar 07 02:31:59 mail.conor-burns.com systemd[1]: caddy.service: Failed with result 'exit-code'.

What’s in the wc snippet?