Cloudflare Tunnels
Every now and then I need to expose a service running on a local machine to the internet, usually just temporarily. Rather than opening ports on a router or mucking about with firewall rules, a reverse tunnel does the job nicely.
There are a number of providers offering this kind of reverse tunnel, including:
I've been playing around with Cloudflare Tunnel recently. Its client, cloudflared, supports a couple of different modes: anonymous quick tunnels (transient, randomly-named URLs) and named tunnels, which are tied to a Cloudflare account and give you stable, predictable hostnames.
Quick tunnels
If you just want to throw something onto a public URL for an hour, TryCloudflare needs no account and nothing more than the cloudflared binary. For example, to share a local web server listening on port 8080:
cloudflared tunnel --url http://localhost:8080cloudflared connects out to Cloudflare's edge and prints a randomly generated URL:
https://some-random-words-here.trycloudflare.comAnyone with that URL can now reach your local server through Cloudflare's network.
A few caveats worth knowing before you rely on these:
- The tunnel and its URL live only as long as the
cloudflaredprocess runs. HitCtrl-Cand it's gone, and you'll get a fresh random URL next time you start one. - They're intended for testing and development only.
Named tunnels
For anything longer-lived, named tunnels give you a stable hostname of your choosing. These require a Cloudflare login, and a domain served by Cloudflare DNS.
First, authenticate and create the tunnel:
# Opens a browser window to authenticate
cloudflared tunnel login
# Creates the tunnel and a credentials file (~/.cloudflared/<UUID>.json)
cloudflared tunnel create my-tunnel
# Confirm it exists
cloudflared tunnel listNext, create a configuration file at ~/.cloudflared/config.yml mapping hostnames to local services:
tunnel: <UUID>
credentials-file: /home/you/.cloudflared/<UUID>.json
ingress:
# Map a public hostname to a local service
- hostname: app.my-site.com
service: http://127.0.0.1:8080
# Required catch-all rule; anything unmatched gets a 404
- service: http_status:404Ingress rules are evaluated from top to bottom, and the last rule must be a catch-all. Services can be more than plain HTTP: SSH, RDP, arbitrary TCP, Unix sockets and more are supported. Other top-level options (like protocol and edge-ip-version) can tune how cloudflared connects to the edge.
Then route a DNS record to the tunnel and start it up:
# Creates a CNAME for app.my-site.com
cloudflared tunnel route dns my-tunnel app.my-site.com
# Start serving traffic
cloudflared tunnel run my-tunnelA couple of additional commands that may be useful for debugging:
# Sanity-check the ingress rules in your config
cloudflared tunnel ingress validate
# Check which rule a given URL would match
cloudflared tunnel ingress rule https://app.my-site.com
# See connection status for a running tunnel
cloudflared tunnel info my-tunnelAll in all, these commands provide a quick and convenient way to expose tools and services from your local machine to the internet. Especially if you already use Cloudflare as your site's DNS.