Skip to main content

Cloud Client IP Restrictions

Report an Issue

Client IP Restrictions restrict access to your Teleport Cloud cluster, allowing traffic only from the network ranges (CIDR blocks) you specify. You manage the allowlist with the client_ip_restriction resource, using tctl, the Teleport Terraform provider, or the Teleport Web UI.

Managing the allowlist with tctl and the Teleport Terraform provider is available starting with Teleport 18.12, as are draft mode and test runs. Managing the allowlist via the Web UI is available in earlier versions, but using this approach enforces the allowlist immediately: there is no draft stage or expiry safety net.

This guide covers how to:

  • Configure a Teleport role that can manage Client IP Restrictions.
  • Set the list of CIDR blocks allowed to connect to your Teleport Cloud cluster.
  • Test an allowlist in draft mode and enforce it with an expiry, so that a misconfigured allowlist cannot lock you out permanently.
  • Check whether the restrictions are enforced.
  • Disable the restrictions.

How it works

The following example shows a client_ip_restriction resource retrieved from a cluster with an enforced allowlist:

kind: client_ip_restriction
version: v1
metadata:
  name: client-ip-restriction
spec:
  allowed_cidrs:
    - "203.0.113.0/24"
    - "198.51.100.10/32"
  mode: enforced
  expires: "2026-09-30T22:00:00Z"
status:
  state: active

client_ip_restriction is a singleton resource: each Teleport Cloud cluster has exactly one, and its name is always client-ip-restriction. Its spec.allowed_cidrs field holds the list of CIDR blocks permitted to connect to the cluster. An empty list disables restrictions and allows all traffic.

Two more spec fields control how and when the allowlist is enforced:

  • mode sets your intent. enforced (the default when mode is empty or unset) tells Teleport Cloud to enforce the allowlist. draft saves the allowlist without enforcing it. Use draft to review a new allowlist without affecting live traffic, or to keep a vetted allowlist on standby so you can enforce it the moment you need to — for example, to lock the cluster down to trusted networks during a security incident.
  • expires is an optional RFC 3339 timestamp that bounds enforcement. Setting it together with mode: enforced starts a test run, in which Teleport Cloud enforces the allowlist until the timestamp and not after it. Use it as a safety net so that an allowlist that locks you out stops being enforced on its own instead of requiring a support ticket. An unset value never expires. Do not set expires together with mode: draft. Draft mode never enforces the allowlist, so the timestamp has no effect.

When expires passes, Teleport Cloud starts removing the allowlist from the ingress layer. Enforcement continues for a few minutes while the rules are removed; once the removal finishes, status.state becomes expired and all traffic is allowed again. Teleport Cloud does not rewrite spec: mode still reads enforced and expires still holds the time you set, so enforcing again always takes a new write.

When the allowlist is enforced, Teleport Cloud applies it at the cluster's ingress layer: only clients whose source IP falls within one of the allowed CIDR blocks can reach the cluster. Changes take 5-15 minutes to propagate and terminate existing connections that no longer match the allowlist. In draft mode the allowlist is stored but never applied, and all traffic is allowed.

The resource's status.state field reflects the current enforcement state:

StateMeaning
draftThe allowlist is saved but not enforced, because mode is draft. All IPs can reach the cluster.
pendingA change has been saved and is being propagated to the ingress layer. The previous enforcement state remains in effect until propagation finishes.
activeThe allowlist is fully enforced at the ingress layer. Only IPs matching the allowlist can reach the cluster.
expiredThe expires time has passed, so enforcement stopped. The allowlist is still saved and all IPs can reach the cluster.

Access to read and modify the allowlist is governed by Teleport's RBAC system through the client_ip_restriction resource kind, and every change is recorded in the audit log.

Prerequisites

Feature availability

Client IP Restrictions are available to Teleport Cloud customers and are opt-in. Contact your account executive or support at [email protected] to enable the feature for your tenant.

  • A Teleport Cloud cluster.
  • A Teleport user with a role that can read and write the client_ip_restriction resource. The preset editor role has this access. To grant it to another role, follow Step 1.
  • One of the following client tools for managing the client_ip_restriction resource: the tctl CLI or the Teleport Terraform provider. The Kubernetes Operator does not support the client_ip_restriction resource.

To confirm that you can run tctl against your cluster:

Check that you can connect to your Teleport cluster and verify that you can run tctl and tsh commands using your current credentials.

  1. Assign teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and [email protected] to your Teleport username.

  2. Authenticate to your Teleport cluster. This depends on whether your shell is interactive or not.

    In an interactive shell: Run the following command. By default, this triggers a multi-factor authentication prompt:

    tsh login --proxy=teleport.example.com --user=[email protected]
    tctl status

    Cluster teleport.example.com

    Version 18.11.0

    CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

    On non-interactive environments: If you are running tsh and tctl as an AI agent, in a CI/CD environment, or similar, make sure the TELEPORT_IDENTITY_FILE environment variable is assigned to a valid file path with credentials for your cluster. tsh and tctl read the file path from the environment variable and do not require a separate authentication step. If there is no identity file available, we recommend that you set up Machine ID to provision one automatically.

    When executing tctl commands with an identity file, you must pass the --auth-server flag to provide the Teleport Auth Service address, which is not included in the identity file. If you provide the Proxy Service address, tctl connects to the Proxy Service, which forwards traffic to and from the Teleport Auth Service. Update 443 to 3025 if you are contacting the Auth Service directly with tctl:

    tctl status --auth-server=teleport.example.com:443

    For tsh commands that read an identity file, you must pass the --proxy flag, which points tsh to the address of the Teleport Proxy Service:

    tsh status --proxy=teleport.example.com

    Ensure client commands can access your identity file. Replace path/to/identity/file with the path to your identity file:

    export TELEPORT_IDENTITY_FILE="${TELEPORT_IDENTITY_FILE:-path/to/identity/file}"

    Add the --auth-server or --proxy flags to all subsequent tctl and tsh commands.

If you can connect to the cluster and run the tctl status command, you can use your current credentials to run subsequent tctl commands from your workstation. If you host your own Teleport cluster, you can also run tctl commands on the computer that hosts the Teleport Auth Service for full permissions.

Step 1/3. Configure RBAC

To read and modify Client IP Restrictions, a Teleport user needs permission to manage the client_ip_restriction resource. The preset editor role already has this access; if the user has the editor role, skip this step.

Create a file called client-ip-restriction-editor.yaml:

kind: role
version: v8
metadata:
  name: client-ip-restriction-editor
spec:
  allow:
    rules:
      - resources:
          - client_ip_restriction
        verbs:
          - list
          - read
          - create
          - update
          - delete

Use tctl to create the role:

tctl create -f client-ip-restriction-editor.yaml

Assign the role to a user. Open the user resource in your editor, replacing alice with the Teleport username:

tctl edit users/alice

Add client-ip-restriction-editor to spec.roles, then save and close the editor to apply the change:

  spec:
    roles:
      - access
+     - client-ip-restriction-editor

Step 2/3. Stage the allowlist in draft mode

Avoid locking yourself out

A misconfigured allowlist can block all access to your cluster.

To avoid locking yourself out, roll out the allowlist in two stages. Save it in draft mode first, then enforce it with an expiry. This way, a mistake stops enforcing itself instead of becoming a permanent lockout that requires a support ticket.

In this step, set mode: draft to save the allowlist without enforcing it. Teleport Cloud stores the CIDR blocks but continues to allow all traffic, so you can review the list with no risk of losing access.

Create a file called client-ip-restriction.yaml:

kind: client_ip_restriction
version: v1
metadata:
  name: client-ip-restriction
spec:
  mode: draft
  allowed_cidrs:
    - "203.0.113.0/24"
    - "198.51.100.10/32"

Replace the entries in allowed_cidrs with the CIDR blocks allowed to connect to your cluster. metadata.name must be client-ip-restriction; the resource is a singleton and no other name is accepted.

Apply the allowlist:

tctl create client-ip-restriction.yaml

client_ip_restriction has been created

If Client IP Restrictions already exist, tctl create reports an error. Use the -f flag to overwrite the current allowlist:

tctl create -f client-ip-restriction.yaml

client_ip_restriction has been created

You can also edit the allowlist interactively. tctl edit opens the current resource in your editor and applies your changes when you save and exit:

tctl edit client_ip_restriction

Read the resource back and confirm that status.state is draft:

tctl get client_ip_restriction

If the allowlist was already enforced, status.state reads pending for a few minutes while Teleport Cloud removes the rules from the ingress layer, and enforcement continues until that finishes. A first draft becomes draft immediately, since there is nothing to tear down.

While the state is draft, verify that allowed_cidrs includes the network you are currently connecting from, as well as any third-party services that need to reach your cluster (CI/CD systems, identity providers, and so on). Teleport does not add these ranges automatically.

You do not have to enforce the allowlist right away. You can leave it in draft indefinitely as a vetted, ready-to-go configuration, then enforce it the moment you need to — for example, to restrict access to trusted networks during a security incident — as shown in the next step.

Step 3/3. Enforce the allowlist with an expiry safety net

Enforcing with an expiry is called a test run. It enforces the allowlist exactly as a permanent rollout does, but only until expires. If the list is wrong and locks you out, you do not need to do anything: when the test run expires, Teleport Cloud starts removing the rules from the ingress layer, and a few minutes later status.state becomes expired, the cluster is reachable from any IP again, and your allowlist is still saved so you can correct it.

When the draft looks correct, set mode: enforced and an expires timestamp a short time in the future. expires uses RFC 3339 format and must be at least 20 minutes ahead. A numeric offset such as 2026-01-01T02:30:00+02:00 is accepted, but we recommend UTC (the trailing Z) to avoid time zone mistakes. Teleport Cloud enforces the allowlist, but if it locks you out, teardown starts at the expiry time and access is restored once status.state becomes expired, a few minutes later.

Compute a UTC timestamp 30 minutes from now:

date -u -d '+30 minutes' '+%Y-%m-%dT%H:%M:%SZ'

2026-01-01T00:30:00Z

Use the output as the expires value:

Update client-ip-restriction.yaml:

kind: client_ip_restriction
version: v1
metadata:
  name: client-ip-restriction
spec:
  mode: enforced
  # Use the UTC timestamp from the command above.
  expires: "2026-01-01T00:30:00Z"
  allowed_cidrs:
    - "203.0.113.0/24"
    - "198.51.100.10/32"

Apply the change:

tctl create -f client-ip-restriction.yaml

client_ip_restriction has been created

Each write replaces the whole resource

Every write replaces the entire resource, so when you edit the allowlist you must re-send a still-valid expires or clear it. An expires value you read earlier and send back unchanged is rejected once it is within 20 minutes of the current time.

Before you clear the safety timer, wait for status.state to become active and verify the allowlist: check that you can still reach the cluster and that every expected network (including third-party services) can too. Access is unchanged while the state is pending, so staying connected during the rollout does not prove the list is correct — an allowlist confirmed while still pending can lock you out for good once it takes effect.

Once verified, keep the allowlist enforced by removing expires (or extending it) and reapplying. In the Web UI, "Confirm" does the same thing and is only offered once the test run is active. With expires unset, enforcement never lapses:

kind: client_ip_restriction
version: v1
metadata:
  name: client-ip-restriction
spec:
  mode: enforced
  allowed_cidrs:
    - "203.0.113.0/24"
    - "198.51.100.10/32"

If you do not need the allowlist enforced yet, you can instead set mode: draft after the test run. Leave expires unset, since it has no effect in draft mode. The vetted allowlist stays saved and ready to enforce, but all traffic is allowed. You can also simply let the test run expire. Once status.state is expired, all traffic is allowed and the allowlist remains saved.

If you never set expires, the allowlist is enforced immediately and stays enforced until you change it — with no automatic safety net. This is why we recommend testing in draft mode first.

Check the enforcement status

Retrieve the resource to view the current allowlist and enforcement state:

tctl get client_ip_restriction

Example output:

kind: client_ip_restriction
version: v1
metadata:
  name: client-ip-restriction
spec:
  mode: enforced
  allowed_cidrs:
    - 203.0.113.0/24
    - 198.51.100.10/32
status:
  state: active

The allowlist is fully enforced when status.state is active. A pending state means the change is still propagating to the ingress layer, which can take up to 15 minutes. A draft state means the allowlist is saved but not enforced, because mode is draft. An expired state means an expires time has passed and enforcement stopped; the allowlist is still saved, but all IPs can reach the cluster until you enforce it again.

Disable Client IP Restrictions

To allow traffic from all IP ranges again, either apply an allowlist with an empty allowed_cidrs list or delete the resource:

tctl rm client_ip_restriction

client_ip_restriction has been deleted

With Terraform, remove the teleport_client_ip_restriction resource from your configuration and run terraform apply.

To stop enforcing the allowlist while keeping the CIDR list saved for later, set mode: draft instead of deleting the resource. Removing the rules from the ingress layer takes 5-15 minutes: status.state reads pending and enforcement continues until the teardown finishes. All traffic is allowed once status.state becomes draft.

Limitations

  • Third-party service ranges. Teleport does not add third-party service ranges automatically. Add allow rules for any third-party service that needs to access your Teleport cluster, such as CI/CD systems and identity providers.
  • Network security. The allowlist applies only to Teleport Cloud access. It does not replace your organization's network or firewall policies.
  • Sync time. Changes to the allowlist take 5-15 minutes to fully sync to the ingress layer.

FAQ

How do I test an allowlist without risking a lockout?

Stage it in draft mode first, confirm the list is correct, then enforce it as a test run with a short expires. If the list locks you out, enforcement stops on its own a few minutes after the test run expires. See Step 2 and Step 3.

What is the difference between draft mode and disabling restrictions?

draft mode keeps your CIDR list saved but stops enforcing it, so you can review or resume it later. Disabling restrictions (an empty allowed_cidrs list or deleting the resource) discards the list. Both allow all traffic.

How many CIDR blocks can I configure?

By default, up to 256 CIDR blocks. Contact your account executive or support to increase the limit.

Do you support a denylist?

Teleport Cloud Client IP Restrictions do not currently support a denylist.

Can I manage Client IP Restrictions with the Kubernetes Operator?

No. The Kubernetes Operator does not support the client_ip_restriction resource. Use tctl, the Terraform provider, or the Web UI instead.

Next steps