
Research note
A Cloudflare Tunnel inside my Zyxel firewall
I added Cloudflare Tunnel to the custom firmware I run on my own USG FLEX 100H, as a native feature in the GUI. It works end to end. The firmware stays private; the question is whether the feature would be useful in uOS.
Simplicity is prerequisite for reliability.
For a long time now I have been building a custom firmware for my own Zyxel USG FLEX 100H. It is a personal research project: it runs on my hardware, it is not distributed, nobody else can obtain or test it, and this post is not a guide to building one. It is about one feature I wanted and an open question: would it be useful as a native uOS feature?
The feature I missed
Publishing something from behind a firewall usually means a port forward and a hole in the WAN. Cloudflare Tunnel turns that around: a small connector opens outbound connections to the Cloudflare edge, and requests for a public hostname come back through them. Nothing listens on the WAN. It works behind CGNAT, it does not care about dynamic IPs, and Cloudflare Access can ask for a login before a single packet reaches the LAN.
uOS already talks to Cloudflare for DDNS. It has Tailscale. It does not have Tunnel. So I added it.
What it looks like
I wanted it to feel like a Zyxel feature, not like a script I run over SSH. It sits in the VPN menu next to IPsec, SSL VPN and Tailscale:
The USG FLEX 100H web interface with the VPN menu open, listing IPSec VPN, SSL VPN, Tailscale and the new Cloudflare Tunnel entry; serial number and MAC addresses are blacked out
The page has three things: an enable switch, the tunnel token, and the connector status. You create a tunnel in the Cloudflare dashboard, copy its token, paste it here, press Apply.
The VPN, Cloudflare Tunnel page: Enable switched on, the tunnel token stored and masked, and Connector Status showing Connected
A few seconds later Cloudflare shows the tunnel Healthy, and the replica is the firewall itself, reported as linux_arm64 with four connections to the edge in Rome and Milan.
The Cloudflare Tunnels list with the tunnel flex100h-test in state Healthy, one replica, connector version 2026.10.0; the account name is blacked out
The tunnel overview in Cloudflare: one active replica whose host name is the firewall, architecture linux_arm64, edge locations fco01, mxp02 and mxp05; replica ID, origin IP and tunnel ID are blacked out
The CLI picked it up without a single line of extra code, because the CLI is generated from the same data model:
The firewall CLI: show state vrf main cftunneld reports enabled true and connected true, and show config vrf main cftunnel shows the feature enabled with the encrypted token blacked out
How it fits
Without going into how the image is put together, the feature itself is small and uses only what uOS already has:
- a YANG model with two settings,
enabledandtoken, plus a state container withenabledandconnected; - a configuration service that decrypts the token, writes it to a root-only file and restarts the connector;
- the official
cloudflaredconnector as a sandboxed service running asnobody, about 22 MB of RAM; - a GUI page built like the other VPN pages.
The token is stored encrypted exactly like the Cloudflare DDNS API token, so it never sits in the configuration in clear text.
Testing it from the outside
I added a published route in the Cloudflare dashboard pointing a test hostname at the connector's own readiness endpoint, limited to one path. The route reached the firewall in seconds, with nothing to change on the box:
The Cloudflare dialog to add a published application: subdomain flex100h-test on a blacked-out domain, path ^/ready$ and service URL http://localhost:20241
From the Internet:
bashrainpwn@0xdeadspace:~$ curl https://flex100h-test.<redacted>/ready HTTP 200 {"status":200,"readyConnections":4,...} rainpwn@0xdeadspace:~$ curl https://flex100h-test.<redacted>/metrics HTTP 404
One path answered, everything else got a 404, and no inbound port was ever opened. I removed the route afterwards.
An open question
None of this should need a custom firmware. Cloudflare Tunnel is a small, well understood piece of software, and uOS already has every building block it needs. The firmware itself stays private; what I want to share is the use case.
If you run a FLEX H, I would like to know whether you would find this useful, and why or why not.
If this writeup saved you an evening, you can buy me a coffee.
Buy me a coffee