CLI Companion

  • Hugging Face CLI
    • login
    • whoami
    • repo create
    • upload
    • download
    • lfs-enable-largefiles
    • scan-cache
    • delete-cache
  • Hapi CLI
    • new
    • start
    • build
    • test
    • plugin create
    • route add
  • Cloudflared
    • tunnel
    • tunnel run
    • tunnel list
    • tunnel delete
    • access
    • access tcp
    • update

    The `cloudflared access tcp` command is used to establish secure TCP connections to services protected by Cloudflare Access. It acts as a proxy, authenticating your request through Cloudflare Access and then forwarding your local TCP traffic to the specified remote service.

    Syntax

    bash
    cloudflared access tcp [--hostname <hostname>] [--url <URL>] [--service <service-name>] [--destination <host:port>] [--bastion] [--idp-url <URL>] [--app-jwt <JWT>] [--provider <provider-name>]

    Alternatively, you can specify the service by its hostname and port directly:

    bash
    cloudflared access tcp <hostname>:<port>

    Key Arguments and Flags

    * **`<hostname>:<port>` (positional argument)**: The specific hostname and port of the service you want to access. This is often the most straightforward way to use the command.

    * **`--hostname <hostname>`**: The hostname of the application you want to reach. This should match a hostname configured in your Cloudflare Access policies.

    * **`--url <URL>`**: The full URL of the application. Cloudflare recommends using `--hostname` instead.

    * **`--service <service-name>`**: If your `cloudflared` tunnel has multiple services defined (e.g., in `config.yml`), you can specify the name of the service to connect to directly, rather than using `hostname:port`.

    * **`--destination <host:port>`**: The local address and port `cloudflared` will listen on. By default, `cloudflared` will pick an available local port and print it to the console. You can specify `localhost:1234` to listen on port 1234 locally.

    * **`--bastion`**: When connecting to a private network via a bastion host (SSH jump host), this flag indicates that `cloudflared` should act as the entry point to that network. This allows you to chain `ssh -o ProxyCommand='cloudflared access tcp --bastion %h:%p'` for SSH access.

    * **`--idp-url <URL>`**: The URL of your Identity Provider (IdP) if you need to explicitly specify it for authentication. Rarely needed as `cloudflared` usually discovers this automatically.

    * **`--app-jwt <JWT>`**: A pre-obtained Cloudflare Access JWT. If provided, `cloudflared` will skip the interactive browser login.

    * **`--provider <provider-name>`**: Specifies the name of the access provider if you have multiple configured (e.g., `google`, `azuread`).

    Usage Examples

    **1. Basic Access to a Service:**

    Connect to a service running on `my-internal-app.example.com` on port 80. `cloudflared` will open a local port (e.g., `localhost:45678`) that forwards traffic to the remote service.

    bash
    cloudflared access tcp my-internal-app.example.com:80

    Output will typically look like:

    Proxying to my-internal-app.example.com:80 on 127.0.0.1:45678

    You can then access the service via `localhost:45678` in your local applications.

    **2. Specifying a Local Destination Port:**

    Connect to `my-db.example.com` on port 3306, and have `cloudflared` listen on local port 9900.

    bash
    cloudflared access tcp --destination localhost:9900 my-db.example.com:3306

    Now, your local database client can connect to `localhost:9900`.

    **3. Using with SSH (Bastion Host):**

    To SSH into a machine `my-server.example.com` via Cloudflare Access, you can combine `cloudflared access tcp` with `ssh -o ProxyCommand`:

    bash
    ssh -o ProxyCommand='cloudflared access tcp --hostname %h --bastion' my-server.example.com

    This command tells SSH to use `cloudflared access tcp` as a proxy. `cloudflared` will handle the Access authentication and then establish the TCP tunnel for SSH traffic.

    **4. Accessing a Service Defined in `cloudflared` Config:**

    If your `cloudflared` tunnel's `config.yml` defines services like this:

    yaml
    tunnel: <tunnel-uuid>
    credentials-file: /path/to/credentials.json
    
    ingress:
      - hostname: my-web-service.example.com
        service: http://localhost:8080
        originRequest:
          noTLSVerify: true
      - service: ssh://localhost:22
        hostname: my-ssh-server.example.com

    You can access the SSH service using its defined hostname:

    bash
    cloudflared access tcp my-ssh-server.example.com:22

    Explanation

    When you run `cloudflared access tcp <hostname>:<port>`, the following steps occur:

    1. **Authentication**: `cloudflared` first attempts to authenticate you with Cloudflare Access. If you don't have an active session, it will typically open a browser window for you to log in with your configured Identity Provider (e.g., Okta, Google, Azure AD).

    2. **JWT Acquisition**: Upon successful authentication, `cloudflared` obtains a JSON Web Token (JWT) from Cloudflare Access.

    3. **Tunnel Establishment**: `cloudflared` then opens a local TCP port on your machine (either a random ephemeral port or one you specify with `--destination`).

    4. **Secure Proxying**: Any TCP connection made to this local port by your applications (e.g., `ssh` client, `psql` client, web browser) is securely wrapped and sent through `cloudflared`. `cloudflared` uses the obtained JWT to establish a secure WebSocket or HTTP/2 connection to the Cloudflare edge network.

    5. **Service Access**: The Cloudflare edge, after validating the JWT against your Access policies, forwards the TCP traffic through the `cloudflared` tunnel (running on your private network) to the specified internal service (`<hostname>:<port>`).

    This process allows you to securely access internal TCP services (like SSH, RDP, databases, internal web applications) without exposing them directly to the public internet, leveraging Cloudflare's global network and Access policies for authentication and authorization.