It’s simple! I create a wildcard domain (something like *.xxx.solovyov.net, xxx is for “real domain is none of your business” 😁), and then reverse-proxy everything through an SSH tunnel from a server to my laptop.
(…)
The first problem is that handling *.xxx.solovyov.net in Server-Caddy makes Caddy request a wildcard certificate.
You and many others likely know this, but for anyone who doesn’t, every request for a TLS certificate in the past several years follows this workflow:
Your certificate authority validates your right to get a signed certificate for the given domain (TXT records, email, whatever)
Your CA issues a precertificate – a standard TLS certificate with a special “poison extension” that essentially says “no way in hell can you use this in a browser!”
The CA sends this to a certificate transparency server (or several)
The CT server returns a signed certificate timestamp – basically a blob of data that says “I see that you plan to issue this TLS certificate with the following parameters, I saw it at this time, and I’m signing it with my key”
Your CA revokes the precertificate and issues a leaf cert, almost always including the SCT as an extension
This allows any user to take a TLS certificate, go to a CT search system, and look up the precert. This is an essential part of the security model of CAs; you can guarantee that a given TLS cert was not issued in advance, and you can guarantee that your CA issued exactly what it told the CT servers it would.
This also means that your security model must not depend on hiding your DNS. Looking up a domain in CT logs is a cheap, easy way to turn bugs into bounty dollars.
Another way to do this is Tailscale. If you want to share your laptop server generally, you put Caddy and Tailscale on the server and then put Tailscale on your laptop and tell Caddy to reverse proxy to your laptop’s Tailscale address. You can also connect directly to your laptop from your phone on LAN if you put Tailscale on the phone.
That’s true, it’s a replacement for ssh tunnel + local Caddy, but you’ll need to run your projects on 0.0.0.0 on your laptop (or on Tailscale’s ip). Plus there is still a need to map domain name to port, so instead of wildcard DNS on the server there is a need for imports (like import tmpl dev 8000).
I used to use ssh tunnels in the past, but I am now just using wireguard. It is a lot more robust and also a lot faster. No crazy ssh invocation magic, just use IP:port. You could even have DNS entries for the IPs.
I personally found Wireguard incredibly hard to get running. Between the client and server configurations and the relevant firewall/port configuration it was just too much for me to be willing to use on an ongoing basis.
I hear it’s gotten better and I know a lot of people use it but Tailscale is such incredible secret sauce I can’t see myself ever doing anything else :)
I don’t see myself throwing out Tailscale for my personal stuff because it’s just sooo convenient and works across mobile and everything with zero extra work on my end, but there are certainly places where stock Wireguard probably makes more sense and having a way to implement that without my head exploding is a definite win :)
One of the things that keeps me gravitating back to Tailscale is the fact that it’s more than just a point to point VPN link. It creates a virtual network layer that bridges all my infrastructure - mobile, desktop, cloud, home VMs/containers together into one seamless whole that I can access from anywhere.
I can understand why folks run away from the commercial aspect (although as a pragmatist I’m NOT personally averse to throwing money at someone to solve problems for me).
However I do appreciate the desire for a 100% FLOSS infrastructure setup, so I plan to look into Headscale in the future. The project has legs and in fact has contributions from Tailscale employees.
I don’t really understand where the difference is supposed to be. On my wireguard network all hosts can reach each other too, so it is a network, not a point-to-point connection. My server in another country can ping my raspi at home, my phone can ping my laptop etc. It is a real network. I also have DNS names for the hosts. I never bothered to look into tailscale too deeply as it is closed source, so I may be missing something obvious here.
I paid for ngrok back in the day, but for years now they’ve moved to this subscription model and the upgraded account I paid for gives me no credit. Doesn’t make me want to pay again. I do still use it sometimes, but without the custom domains I had before
Another really good open-source one is sish. I’ve had it running for ages with no problems and so only just discovered that it recently added SNI name-based proxying to multiple backends, which is super nice.
I recently learned about ngrok from John Hammond’s videos on solving CTF challenges - if you managed to get remote code execution, then opening up a port using grok back to you machine, and having nectar (or for useful, pwncat) listening means you get a full, nice to use shell on the remote machine.
You can see how it works on https://youtu.be/g2CnIgjHeX8?t=2121 (worth watching the full video but this is about where the reverse shell stuff starts)
I really appreciate it when people take the time to write up their builds. Looking at someone else’s decision tree can be very helpful in coming to your own conclusions for building solutions like this.
Also related there’s this IMO pretty good list of alternatives to ngrok in this and similar spaces - awesome tunneling on Github.
(…)
You and many others likely know this, but for anyone who doesn’t, every request for a TLS certificate in the past several years follows this workflow:
TXT
records, email, whatever)This allows any user to take a TLS certificate, go to a CT search system, and look up the precert. This is an essential part of the security model of CAs; you can guarantee that a given TLS cert was not issued in advance, and you can guarantee that your CA issued exactly what it told the CT servers it would.
This also means that your security model must not depend on hiding your DNS. Looking up a domain in CT logs is a cheap, easy way to turn bugs into bounty dollars.
Right, it’s not a security model, it’s just I don’t want my wildcard domain published on the internet. :)
Another way to do this is Tailscale. If you want to share your laptop server generally, you put Caddy and Tailscale on the server and then put Tailscale on your laptop and tell Caddy to reverse proxy to your laptop’s Tailscale address. You can also connect directly to your laptop from your phone on LAN if you put Tailscale on the phone.
That’s true, it’s a replacement for ssh tunnel + local Caddy, but you’ll need to run your projects on 0.0.0.0 on your laptop (or on Tailscale’s ip). Plus there is still a need to map domain name to port, so instead of wildcard DNS on the server there is a need for imports (like
import tmpl dev 8000
).So the general theme is still applicable. :)
I used to use ssh tunnels in the past, but I am now just using wireguard. It is a lot more robust and also a lot faster. No crazy ssh invocation magic, just use IP:port. You could even have DNS entries for the IPs.
I personally found Wireguard incredibly hard to get running. Between the client and server configurations and the relevant firewall/port configuration it was just too much for me to be willing to use on an ongoing basis.
I hear it’s gotten better and I know a lot of people use it but Tailscale is such incredible secret sauce I can’t see myself ever doing anything else :)
I use https://github.com/naggie/dsnet/ to set it up. Super easy to use.
That’s REALLY great to know about. Thank you!
I don’t see myself throwing out Tailscale for my personal stuff because it’s just sooo convenient and works across mobile and everything with zero extra work on my end, but there are certainly places where stock Wireguard probably makes more sense and having a way to implement that without my head exploding is a definite win :)
This has also been on my radar for a while as an alternative to dsnet https://github.com/freifunkMUC/wg-access-server
One of the things that keeps me gravitating back to Tailscale is the fact that it’s more than just a point to point VPN link. It creates a virtual network layer that bridges all my infrastructure - mobile, desktop, cloud, home VMs/containers together into one seamless whole that I can access from anywhere.
I can understand why folks run away from the commercial aspect (although as a pragmatist I’m NOT personally averse to throwing money at someone to solve problems for me).
However I do appreciate the desire for a 100% FLOSS infrastructure setup, so I plan to look into Headscale in the future. The project has legs and in fact has contributions from Tailscale employees.
I don’t really understand where the difference is supposed to be. On my wireguard network all hosts can reach each other too, so it is a network, not a point-to-point connection. My server in another country can ping my raspi at home, my phone can ping my laptop etc. It is a real network. I also have DNS names for the hosts. I never bothered to look into tailscale too deeply as it is closed source, so I may be missing something obvious here.
One difference I see is that Tailscale does automatic NAT traversal so I don’t need to poke holes in my firewall/NAT to make it work.
I have to try replacing ssh with wireguard (or tailscale fwiw)!
I paid for ngrok back in the day, but for years now they’ve moved to this subscription model and the upgraded account I paid for gives me no credit. Doesn’t make me want to pay again. I do still use it sometimes, but without the custom domains I had before
Another really good open-source one is sish. I’ve had it running for ages with no problems and so only just discovered that it recently added SNI name-based proxying to multiple backends, which is super nice.
I use frp. Easy to setup.
I recently learned about ngrok from John Hammond’s videos on solving CTF challenges - if you managed to get remote code execution, then opening up a port using grok back to you machine, and having nectar (or for useful, pwncat) listening means you get a full, nice to use shell on the remote machine.
You can see how it works on https://youtu.be/g2CnIgjHeX8?t=2121 (worth watching the full video but this is about where the reverse shell stuff starts)
I scrolled over the website and couldn’t find out why exactly I’d need them ?!
Great article!
I really appreciate it when people take the time to write up their builds. Looking at someone else’s decision tree can be very helpful in coming to your own conclusions for building solutions like this.
Also related there’s this IMO pretty good list of alternatives to ngrok in this and similar spaces - awesome tunneling on Github.
I should add to article that this list was where I started :)
That’s a great idea. I think it would help people who wanted to dig a bit deeper and understand the other options.