Skip to content

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[]:

FieldTypeDefaultAllowed valuesDescription
tokenstring(required)<base64 tunnel token>Tunnel token from the Cloudflare Zero Trust dashboard (Networks → Tunnels → Install connector). Startup fails without it.
ha_connectionsint4<int>Number of high-availability connections to the Cloudflare edge. 0 or unset means 4; capped by the number of discovered edge addresses.
protocolstringautoauto | quic | http2 | h2muxEdge 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_quantumboolfalsetrue | falseUse 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_versionint00 | 4 | 6IP version used to reach the Cloudflare edge; 0 selects automatically.
datagram_versionstring(remote)v2 | v3Datagram protocol version for UDP over QUIC. Unset follows the account's remote Cloudflare feature setting (starting from v2). Only meaningful with QUIC.
grace_periodbadoption.Duration30s<duration>Graceful-shutdown window for in-flight edge connections.
regionstring(from token)<region>Cloudflare edge region selector. Rejected when the token already embeds an endpoint.
control_dialerDialerOptions(direct)Dial FieldsDial fields used for connections to the Cloudflare control plane. Hostnames are resolved through sing-box's DNS router.
tunnel_dialerDialerOptions(direct)Dial FieldsDial 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_cloudflared build 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 protocol the connector starts on QUIC and falls back to HTTP/2 after five failed attempts, or immediately when QUIC looks blocked. Set quic or http2 to pin one transport.
  • post_quantum only works over QUIC; combined with protocol: http2 the inbound fails at startup.
  • region conflicts with tokens that already embed an endpoint.
  • control_dialer and tunnel_dialer take 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 cloudflared daemon next to the core.

Source: option/cloudflared.go:5-16 · v1.14.2 (af6e64c)

Core Tutorial by Argsment