找回密码
 注册
查看: 1|回复: 0

Exposing Multiple LAN Web Services via Cloudflare Tunnel (2025 Edition)

[复制链接]
发表于 昨天 19:11 | 显示全部楼层 |阅读模式
本帖最后由 Test 于 2026-10-9 19:31 编辑

There are often situations where you want to expose web services running on your office or home LAN to the outside world with HTTPS, without opening ports or using a static IP. You can achieve this for free using Cloudflare Tunnel (cloudflared).
This time, I created a configuration where two web services on a separate host (192.168.5.120) are exposed externally via separate subdomains from a single Ubuntu 22.04 machine. Ultimately, I built and set it up as a persistent service using the dashboard method (Web GUI management). I am leaving these notes, including the points where I actually got stuck.

Configuration Overview

smpl0001.example.com ──┐
                                            ├─ Cloudflare ─ Tunnel ─ Ubuntu22(cloudflared)
smpl0002.example.com ──┘                                              ├─→ 192.168.5.120:9000
                                                                                             └─→ 192.168.5.120:9001

Key Points:
  • No router port forwarding is required at all (cloudflared establishes an outbound connection from the inside)
  • HTTPS certificates are automatically issued and renewed by Cloudflare
  • The origin IP is hidden by Cloudflare, which is also great for security

Prerequisites

  • You own a custom domain and its nameservers are set to Cloudflare
  • A Cloudflare account (Free plan is fine)
  • One Ubuntu 22.04 machine that can reach the target services within the LAN

Subdomain Method vs. Subpath Method

I initially considered path separation like "service.example.com/direa/", but the conclusion is that the subdomain method is overwhelmingly easier.
Reasons:
  • Although cloudflared's ingress has a path matching feature, it does not rewrite (strip) the path
  • You end up needing to insert an extra layer of reverse proxy like nginx locally
  • Furthermore, the backend application also requires modifications to "run under a subpath" (absolute paths for CSS/JS, redirect destinations, Cookie Paths, WebSocket paths, etc.)

Retrofitting existing applications to support subpaths is difficult, so unless there is a special reason, you should use subdomains.

CLI Method vs. Dashboard Method

There are two ways to manage cloudflared tunnels.

Although I initially tried to proceed with the CLI method, the token command for "Install cloudflared connector" displayed on the dashboard was overwhelmingly easier, so I ultimately used the dashboard method to make it a resident service. It is a huge advantage that adding hostnames in the future can be completed entirely via the web without needing SSH login.

1. Install cloudflared

Install it from the official Cloudflare apt repository.
  1. sudo mkdir -p --mode=0755 /usr/share/keyrings
复制代码


At this point, the systemd service has not been registered yet. It will be registered using the token in the next step.

2. Create a tunnel in the Cloudflare dashboard

The Cloudflare screen layout was updated around 2024-2025, and it is currently located in the following place.

How to get to the dashboard (latest UI)

  • Access https://one.dash.cloudflare.com/ (Zero Trust dashboard)
  • Click on the left sidebar → Networks → Connectors
  • Create a new one with the "Create a tunnel" button

It is now referred to as "Connectors." Previously it was "Networks → Tunnels," but in the current UI, the tunnel concept is included within Connectors.

Tunnel creation

  • Select Tunnel type: Cloudflared
  • Tunnel name: Any name (e.g., lan-services)

Once created, the "Install and run a connector" screen appears, showing the installation command for Ubuntu. This contains a long token (starting with eyJhIjoi...).

3. Make the connector resident using the token

Since the cloudflared binary is already installed via apt, it is sufficient to execute only the latter part of the command displayed on the dashboard (from service install onwards).
  1. sudo cloudflared service install eyJhIjoiM2JlMzdmYW...(ダッシュボードの長いトークン)
复制代码


This automatically performs the following:
  • The token is saved under /etc/cloudflared/
  • The systemd service cloudflared.service is registered
  • Auto-start enabled & started immediately

Verification:
  1. [font=YakuHanJPs, Arial, Meiryo, sans-serif][size=16px]sudo systemctl status cloudflared[/size][/font]

  2. [font=YakuHanJPs, Arial, Meiryo, sans-serif][size=16px]sudo journalctl -u cloudflared -f[/size][/font]
复制代码


If the log shows 4 instances of 'Registered tunnel connection', the connection is successful (4 connections = for high availability).
To be sure, check if the service is running correctly using the token method:
  1. sudo systemctl cat cloudflared | grep ExecStart
复制代码
  1. ExecStart=/usr/bin/cloudflared --no-autoupdate tunnel run --token eyJ...
复制代码

If --token is included, it is running in dashboard mode.

4. Register the hostname to expose (The latest UI trap)

This was a point where it was easy to get lost due to UI changes.
How to get there (Latest UI)

  • Networks → Connectors and click the relevant Connector
  • Open the 'Published application routes' tab on the Connector details screen
  • Add using the '+ Add a published application route' button

It used to be a tab named 'Public Hostnames', but in the current UI, it has been renamed to 'Published application routes'. If you are looking at old articles and wandering around looking for 'Public Hostnames', look here.
Input details

[/url][url=https://assets.st-note.com/img/1777967672-zfw3snmkArB8lygSR01Q72GP.png?width=2000&height=2000&fit=bounds&quality=85]
Restarting the server side is not required. It is reflected immediately.

5. Operation check

Query the authoritative DNS directly to check if the record can be resolved.
  1. dig @1.1.1.1 smpl0001.example.com
复制代码

Expected result:
  1. ;; ANSWER SECTION:
  2. smpl0001.example.com.  300  IN  A  104.21.x.x
  3. smpl0001.example.com.  300  IN  A  172.67.x.x
复制代码


The 104.21.x.x / 172.67.x.x range are Cloudflare edge IPs, so this is proof that Proxied (orange cloud) is working. The actual origin (home/office IP) remains hidden and is delivered via the tunnel.
Once done, access https://smpl0001.example.com / https://smpl0002.example.com in your browser; if both load, you are finished.

Notes on common pitfalls


1. DNS_PROBE_FINISHED_NXDOMAIN error occurs
Common causes:
  • Typo in the subdomain (I wasted time on this. I was querying smple0001 instead of smpl0001, and I kept running dig until I noticed the extra 'e')
  • Missing registration in Published application routes
  • Domain name servers are not yet set to Cloudflare (verify with dig NS example.com +short)
  • Local/router DNS cache is stale

To isolate the issue, querying the authoritative server directly using dig @1.1.1.1 is the quickest way. If only the SOA is returned and there is no ANSWER, it means the record does not exist.

2. Output returns only SOA

  1. example.com.  1800  IN  SOA  adele.ns.cloudflare.com. ...
复制代码

3. Browser/OS DNS cache
If you cannot open the site even though DNS should have propagated:
  • Mac: sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder
  • Windows: ipconfig /flushdns
  • Chrome: Clear host cache at chrome://net-internals/#dns
  • Switching your phone to 4G/5G allows you to quickly determine if it is a router/ISP cache issue

4. Terminology differences between old articles and current UI
Since the terminology differs from older articles found via Google, if you get lost in the UI, look for "Connectors" or "Published application routes".

5. On the Node.js application side

Since access is via Cloudflare, if you are using Express, you should include the following so that req.ip and req.protocol are retrieved correctly.
  1. app.set('trust proxy', true);
  2. // CF-Connecting-IP / X-Forwarded-Proto を見るようになる
复制代码


Convenient operational aspects

  • Adding hostnames → Click "+ Add" and Save in the web dashboard. No SSH login required
  • Removing hostnames → Delete on the same screen. DNS records are also automatically cleaned up.
  • HTTPS certificates → Cloudflare is fully automated. No need to worry about Let's Encrypt renewals.
  • Access restrictions → You can retroactively apply Google login enforcement, etc., via Zero Trust → Access. Perfect for internal tools.
  • Connecting from a new location → Create a new Connector on the Connectors screen and install it on another machine using the token.

Since you can attach multiple hostnames to a single tunnel (connector), unless you have very specific requirements, one tunnel + multiple hostnames is all you need for operation.

Recommended Cloudflare settings

It is recommended to enable the following in the dashboard.
  • SSL/TLS → Overview to Full (Flexible often causes mixed content or redirect loops).
  • SSL/TLS → Edge Certificates → Always Use HTTPS to ON.

Summary

  • If you want to expose multiple web services within your LAN, Cloudflare Tunnel + subdomains is the gold standard.
  • With the dashboard method, you just need to run 'service install ' on the server to complete the setup as a resident service.
  • Adding or removing hostnames is completed entirely via the Web GUI; no SSH required.
  • No port forwarding required, HTTPS is automatic, origin is hidden, and it works within the free tier.
  • The UI names have changed, so remember "Connectors" and "Published application routes".
  • If you get stuck, troubleshoot with 'dig @1.1.1.1' and be careful with the spelling of your subdomains (a lesson learned).

Sub-path routing (/direa/) is theoretically possible, but it requires local nginx + app base path support, which is a hassle. Simply creating subdomains was the right choice.
I hope this is helpful to someone.
2026年5月5日 01:03

来自圈子: Demo俱乐部

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )

GMT-8, 2026-10-10 14:37 , Processed in 0.017057 second(s), 24 queries .

Supported by BestDeal Online X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表