Tunnl.gg

2 months ago (tunnl.gg)

This is nice and for those who's asking, it's different from ngrok and the others in that you don't need a separate client, (almost) everyone has ssh installed.

To the author, I wish you best of luck with this but be aware (if you aren't) this will attract all kind of bad and malicious users who want nothing more than a "clean" IP to funnel their badness through.

serveo.net [2] tried it 8 years ago, but when I wanted to use it I at some point I found it was no longer working, as I remember the author said there was too much abuse for him to maintain it as a free service

I ended up self-hosting sish https://news.ycombinator.com/item?id=14842951

  • Thanks for the kind words. I hope I won't have to close this service in a few days due to abuse but its a weird world we live in.

  • Random thoughts: one can get user's ssh public keys from GitHub on the fly (from `https://github.com/<username>.keys`), so that it requires a valid GitHub account to use this service, without (extra) auth process.

  • It would be nice to have an open-source version that you can self-host. That would solve the abuse problem. Maybe with a service to create API keys.

    • Yeah, this is the next step. I first wanted to understand if this gets any traction. I think I will provide a dockerized version for the server part that you can just run with a simple command and maybe some interface to create api keys and distribute them to your users.

      4 replies →

    • We're using pgrok for that in our organization. A small EC2 instance serves as the public endpoint.

  • OpenSSH is preinstalled on Windows as well, so I think it's not a stretch to say everyone has ssh now.

If you keep this up you'll want to add yourself to the public suffix list:

https://publicsuffix.org/

You should also consider grouping your random hostnames under a dedicated subdomain. e.g. "xxx-xxx-xxx.users.tunnl.gg", that separates out cookies and suchlike.

  • I run a similar site (https://pico.sh) with public urls and thought the same thing for us. The public suffix has some fuzzy limits on usage size before they will add domains (e.g. on the scale of thousands of active users).

    I don’t have tunnl.gg usage numbers but I’m going to guess they are no where near the threshold — we were also rejected.

I used ngrok when it was the to-go answer for serving localhost (temporarily, not permanent) to the public, but the last time I searched for alternatives I stumbled upon the following jewel.

   > tailscale funnel 3000

   Available on the internet:

   https://some-device-name.tail12345.ts.net/
   |-- proxy http://127.0.0.1:3000

   Press Ctrl+C to exit.

I've tailscale installed on my machine anyway for some connected devices. But even without this would convince me using it, because it's part of the free tier, dead simple and with tailscale it's coming from kind of a trusted entity.

  • Hey really recommend using a big long random string in that URL, because as you will have read above TAILNET NAMES ARE PUBLIC. You can find them here: https://crt.sh/?Identity=ts.net [warning, this will probably crash browser if you leave it open too long -- but you can see it's full of tailnet domains].

    So anyway try it like:

    tailscale funnel --set-path=/A8200B0F-6E0E-4FE2-9135-8A440DB9469D http://127.0.0.1:8001 or whatever

    I use uuidgen and voila.

  • I am also using tailscale for a few projects as well. Feel free to use whatever you trust more or works for you.

    • Hey, I didn't mean to sell another tool over yours! It's just an experience that popped into my mind and I wanted to share. I appreciate your work and contributing to the problem space of exposing a local service. Thank you.

"We cooperate with law enforcement agencies when required by law. While we do not inspect traffic content, we will provide connection logs and IP address information in response to valid legal process (such as a subpoena or court order) to assist in investigations regarding illegal activity."

https://tunnl.gg/assets/index-Bjpn0hFX.js

If the requesting party knows it's possible they might ask for traffic to be logged

  • I can also deny, if I don't consider the case valid or shutdown the hosted service if I want to. I plan to open source it anyway within the next days.

    • > I can also deny if I don't consider the case valid

      It wouldn't take much for law enforcement or a judge to force cooperation.

This is a great idea but I'm a bit concerned about your bandwidth costs and illegal/malicious content being hosted used under your domain.

For the second point, you might want to implement some kind of browser warning similar to what Ngrok does.

  • Thats a fair point, there are some protections in place for abuse already. I will have a look at what ngrok does for browser warnings. Thanks a lot for the suggestions.

    • Be aware of threat actors, too: you're giving them an easy data exfil route without the hassle and risk of them having to set up their own infrastructure.

      Back in the day you could have stood up something like this and worried about abuse later. Unfortunately, now, a decent proportion early users of services like this do tend to be those looking to misuse it.

      6 replies →

Shell function;

``` tunnl() { if [ -z "$1" ]; then echo "Usage: tunnl <local-port>" return 1 fi

  ssh -t -R 80:localhost:"$1" proxy.tunnl.gg

} ```

There's also https://tunnelmole.com but requires binary or npm install

Built another localhost tunneling tool because I kept forgetting my ngrok auth token.

What it does:

- Expose localhost to the internet (HTTP/TCP/WebSockets) - Zero signup – just works immediately - Free

Nothing groundbreaking, just scratching my own itch for a no-friction tunnel service. Written in Go.

Link: https://tunnl.gg

Happy to answer questions or hear how you'd improve it.

  • Since it uses websockets you could host a website from inside a website? How will you handle pricing for this to keep the service running?

Interesting! How do you handle port conflicts? What ports for public exposure are available?

  • On the VPS we use: - 80 (standard http) - 443 (standard https) - 22 (obv for standard ssh) - 9090 (metrics / internal so I can have an idea of the generic usage like reqs/s and active connections)

    Client-Side: The -R 80:localhost:8080 Explained The 80 in -R 80:localhost:8080 is not a real port on the server. It's a virtual bind port that tells the SSH client what port to "pretend" it's listening on.

    No port conflicts - The server doesn't actually bind to port 80 per tunnel. Each tunnel gets an internal listener on 127.0.0.1:random (ephemeral port). The 80 is just metadata passed in the SSH forwarded-tcpip channel. All public traffic comes through single port 443 (HTTPS), routed by subdomain.

    So What Ports Are "Available" to Users?

    Any port - because it doesn't matter! Users can specify any port in -R: ssh -t -R 80:localhost:3000 proxy.tunnl.gg # Works ssh -t -R 8080:localhost:3000 proxy.tunnl.gg # Also works ssh -t -R 3000:localhost:3000 proxy.tunnl.gg # Also works ssh -t -R 1:localhost:3000 proxy.tunnl.gg # Even this works!

    The number is just passed to the SSH client so it knows which forwarded-tcpip requests to accept. The actual routing is done by subdomain, not port.

    Why Use 80 Convention?

    It's just convention - many SSH clients expect port 80 for HTTP forwarding. But functionally, any number works because:

    - Server extracts BindPort from the SSH request - Stores it in the tunnel struct - Sends it back in forwarded-tcpip channel payload - Client matches on this to forward to correct local port - The "magic" is that all 1000 possible tunnels share the same public ports (22, 80, 443) and are differentiated by subdomain.

Seemingly lacking IPv6 support?

Not that you'd usually need this if you have IPv6 but might still be useful to bypass firewalls or forward access for IPv4 clients from your newer IPv6-only resources.

How are you able to host it for free?

  • I am paying for it out of pocket. Its free for you to use, but not for me to host it :)

    • The question is, how is it sustainable? Nobody likes being rug pulled. Why not charge money for it?

      I'd rather pay a few dollars for a service that will be around 5 years from now, than pay nothing and have to deal with churn.

      1 reply →

    • Good luck with your future mim data sniffing or selective takeovers, I guess? Not sure what the business model would be, unless you’re planning on injecting ads, which would be funny.

      7 replies →

Love the approach, simplicity and concept. SPA works fine if entry point is / if /terms /privacy greated with 404.

  • Hey, thanks for the comment. I am having a look with my own apps and it seems to work with pages and nextjs middleware as well.

You are mentioning it's encrypted end-to-end; please explain how your server is unable to read the contents of the stream?

  • That is wrong (and I need to update any docs that mention this), the traffic is not encrypted end to end, we do TLS termination on our side. From that point on traffic is forwarded back as plain HTTP. However I would in any case not suggest to host any production applications using this service. It is mostly for local dev testing.

It's bit less convenient, but I have access to a vps and a dns with a custom domain.

I can create any subdomain I want and tunnel the connexion to any port on my computer.

=> I can spinup a new subdomain in seconds, no data leakage, url that doesn't change, and it's cost nothing.

How does this compare to cloudflare or even a self-hosted tailscale tunnel?

Also do you collect any data? Privacy says

> We do not collect, store, or sell your personal data.

But I guess personal data is a bit ambiguous. You're at the very least collecting my IP (which is fine, I'm just curious)

  • Yes that is true (the IP is collected), what I meant is that we don't explicitly collect data on purpose.

    • If you’re in the EU or have users in the EU, that distinction matters, and you should be more precise. You likely have a solid legitimate use case for collecting IPs under the GDPR, but only if you’re fully transparent.

      1 reply →

I'm running the similar but different, protocol-agnostic service: https:/ssh-j.com/

Only regular SSH to serve, regular SSH to connect. No public URLs though (it's not for web services).

I love the concept, but I have one gripe: the subscription email is coming from a Gmail address, so I have no trust. I'd love to see it coming from the same domain. Also, it went to spam.

That's really cool. I guess this is an alternative to ngrok (which I like but hate due to having to sign in).

Periodic reminder that just because Go having an easy to use SSH package made these easy to write, connecting to SSH servers and doing TOFU all the time with the keys is far far less safe than webpki, and this service could be relatively easily mitm'd in key scenarios like people being tricked at conferences. It's not as terrifying as the coffee shop taking payments over SSH, but still, this isn't doing E2EE, it's terminating TLS upstream.

There's no SSHFP record (not that openssh uses it by default, and you'd need DNSSEC to make it actually useful), and no public keys documented anywhere to help people avoid MITM/TOFU events.

I get the UX, but it saddens me to see more SSH products that don't understand the SSH security model.