Roll your own Ngrok with Nginx, Letsencrypt, and SSH reverse tunnelling
jerrington.me
jerrington.me
sish implements a web front end for inspecting web traffic on tunnels as well, albeit not as nice as Ngrok :)
Very very useful for handling webhooks and making working with them including locally a pleasure.
There is extra authentication/authorization as part of the web server itself, but it is nice that I don’t have open IP ports on the shared server.
That said, for the use case from the article, if you have a more permanent setup, using something like wireguard would be more robust than an ssh reverse tunnel. But the ssh tunnel is great for more ephemeral connections.
It is really nice if you are already a cloudflare customer and is cheaper last I looked.
https://developers.cloudflare.com/cloudflare-one/connections...
the server needs to connect to the client (server has ports open but the client doesn't), so the client connects to the server and then the connection is like... flipped? flippable?
basically when I try to connect to 127.0.0.1:4500 as the server, I want it to go to the client (which has a bound server listening on a socket, but is closed port/firewall wise). Is this what "reverse tunneling" is?
While you're reading the man page, also check out -L, which allows you to connect to a remote server through the encrypted tunnel. This is the most common usage.
For example, let's say that you have a webserver running remotely that is only listening on localhost. Why would you do this? Let's say that you are running some sort of server management dashboard, but you're not sure how secure it is and you want to only connect to it yourself. Even though it is only listening on localhost, you can still connect to it remotely.
From your workstation,
ssh -L 9000:localhost:8000 remoteserver
This will allow you to open up http://localhost:9000 in your browser and access the remote web server that's listening only on its localhost on port 8000.Just one SSH command, and you're done.
And "a server in the public cloud".
Or even assign random unique public IPv6 address to your computer per individual customer, and listen on that address. That way, other customers will not accidentally hit the endpoints you don't want them to when demoing an app.
The same can be done for any other exposure of services on your LAN.
Then, if you want to use IPv4 NAT, set up SNAT and DNAT. I'm taking Linux's iptables for an example: on the VPS:
iptables -t nat -A PREROUTING -d <VPS Public IP>/32 -p tcp --dport port -j DNAT --to-destination <IP of another side of the WireGuard tunnel> iptables -t nat -A POSTROUTING -o <VPS Internet facing NIC> -j MASQUERADE
The first statement sets SNAT on IPv4 TCP (UDP is also possible) on a specified port. All packets going into this machine (dst = VPS public IP) will go into the other side of your WireGuard tunnel. -d <VPS Public IP>/32 makes sure that the packets forwarding to the VPN side won't get NATed. If you need multiple ports or protocols, just duplicate this line.
The second statement sets DNAT on the VPS. It makes the packets from your VPN side goes to the outside (sorry I'm not an expert in networking principals so that's my understanding).
On your local side, you just set up the tunnel and set your machine's default gateway to your VPS's tunnel IP address. Make sure you add a static route to your VPS's public address (WireGuard Endpoint) if you are connecting WireGuard using an IPv4 endpoint or it will get routed to your tunnel and you will disconnect.
I also sometimes setup IPv6 tunnels without NAT. On the VPS I just setup a WireGuard interface with /64 and assign each peer a /128. No NAT is needed for this case.
https://github.com/tweedegolf/henk
It has a very similar approach, but uses about a hundred lines of Go instead of nginx. It's based on unix sockets created by SSH reverse tunneling, whose names are used to select the desired subdomain. This makes it possible to add more reverse proxies with just an ssh command, without changing anything on the server. It's also small enough that it's easy to add custom logic such as request logging.
In the past, I used to spend so much time on infrastructure, like setting up databases, HTTPS/SSL, network ports and security rules. Didn't understand back then that solutions I can buy with money are the cheapest solutions, because I should be focusing on problems I cannot solve with money (but rather with my time and skills).
But as soon as someone needs to set up even the simplest SSL set up (which may take an inexperienced dev anywhere from 1 hour to multiple hours), I'd say that's not the problem to focus on.
I meant, say you want to ship [any new software product]. There are parts that are common to everyone, and parts that are unique to your product. Whatever is common to others, see what you can leverage (i.e. buy with money), so that you can make time to focus on what is unique to your problem.
I can even buy time from people who will develop the description of the problem well enough from my wague idea to make it comprehesible/implementable by programmers, and who will lead those programmers for me.
My point is that it's not important whether something is common or unique to my product. For some "rolling their own" even if it's a common solution may be a good and comparatively cheeper proposition, if that will end up costing less as a result and will leave more resources to devote to their product overall.
Already, most are not able to put together these systems from semiconductor design. Or writing the OS. Or programming languages. And that is fine.
I envision that in a decade, we (the humankind) will have way more devs, creating way more apps, and not knowing a thing about NodeJS or PostgreSQL or such things that you and I take as "minimum requirements".
(or one of the many public VPNs - though I'm wary of those, if I want a VPN I want to set it up myself and not have my traffic pass through someone else's control)