cloudflared — sing-box
The cloudflared inbound runs an embedded Cloudflare Tunnel connector. Instead of listening on a local port, it dials out to the Cloudflare edge with a tunnel token and hands every connection the tunnel delivers — TCP, UDP and ICMP — to sing-box's routing engine, tagged with this inbound.
No local listener
cloudflared has no listen address: the listen fields (listen, listen_port, …) described on Inbounds do not apply. Everything arrives through the outbound tunnel connections.
Inbound options
type: "cloudflared" under inbounds[]:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
token | string | (required) | <base64 tunnel token> | Tunnel token from the Cloudflare Zero Trust dashboard (Networks → Tunnels → Install connector). Startup fails without it. |
ha_connections | int | 4 | <int> | Number of high-availability connections to the Cloudflare edge. 0 or unset means 4; capped by the number of discovered edge addresses. |
protocol | string | auto | auto | quic | http2 | h2mux | Edge transport. auto (or empty) starts with QUIC and falls back to HTTP/2 after repeated failures or when QUIC looks blocked. h2mux is accepted but treated as http2 with a warning. |
post_quantum | bool | false | true | false | Use post-quantum key exchange. QUIC only: it pins the transport to QUIC (no HTTP/2 fallback) and is rejected together with protocol: http2. |
edge_ip_version | int | 0 | 0 | 4 | 6 | IP version used to reach the Cloudflare edge; 0 selects automatically. |
datagram_version | string | (remote) | v2 | v3 | Datagram protocol version for UDP over QUIC. Unset follows the account's remote Cloudflare feature setting (starting from v2). Only meaningful with QUIC. |
grace_period | badoption.Duration | 30s | <duration> | Graceful-shutdown window for in-flight edge connections. |
region | string | (from token) | <region> | Cloudflare edge region selector. Rejected when the token already embeds an endpoint. |
control_dialer | DialerOptions | (direct) | Dial Fields | Dial fields used for connections to the Cloudflare control plane. Hostnames are resolved through sing-box's DNS router. |
tunnel_dialer | DialerOptions | (direct) | Dial Fields | Dial fields used for connections to the Cloudflare edge data plane. |
Source: option/cloudflared.go:5-16 · pinned at v1.14.2 (af6e64c)
Examples
Accept everything the tunnel delivers and send it out directly:
json
{
"inbounds": [
{
"type": "cloudflared",
"tag": "cf-in",
"token": "<tunnel token>"
}
],
"outbounds": [
{ "type": "direct", "tag": "direct" }
],
"route": {
"rules": [
{ "inbound": ["cf-in"], "outbound": "direct" }
]
}
}Notes
- The type is only compiled in with the
with_cloudflaredbuild tag; other builds fail at startup with a rebuild hint. - Which public hostnames and private networks the tunnel serves is configured in the Cloudflare dashboard, not in sing-box. The origin addresses those ingress rules point to become the destinations that sing-box routes, so a rule on
inbound: ["<tag>"]decides which outbound reaches them. - With the default
protocolthe connector starts on QUIC and falls back to HTTP/2 after five failed attempts, or immediately when QUIC looks blocked. Setquicorhttp2to pin one transport. post_quantumonly works over QUIC; combined withprotocol: http2the inbound fails at startup.regionconflicts with tokens that already embed an endpoint.control_dialerandtunnel_dialertake the usual dial fields, so the tunnel itself can be dialed through another outbound (detour) or bound to an interface.
Cross-core notes
- Xray-core and mihomo have no embedded Cloudflare Tunnel connector; with them you run the standalone
cloudflareddaemon next to the core.
Source: option/cloudflared.go:5-16 · v1.14.2 (af6e64c)
