> ## Documentation Index
> Fetch the complete documentation index at: https://ngrok.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Restrict IPs Action

> Allow or deny traffic based on the source IP address of connections to your ngrok endpoints.

export const ConfigChildren = ({children}) => {
  return <Accordion title="Show Child Properties">
      {children}
    </Accordion>;
};

export const ConfigField = ({title, type, cel = false, defaultValue = false, required = false, children}) => {
  const id = `config-${title.replace(/\.|\s|\*/g, "_")}`;
  return <div className="field pt-2.5 pb-5 my-2.5 border-gray-50 dark:border-gray-800/50 border-b" style={{
    scrollMarginTop: '120px'
  }} id={id}>
      <div className="flex font-mono group/param-head param-head break-all relative">
        <div className="flex-1 flex content-start py-0.5 mr-5">
          <div className="flex items-center flex-wrap gap-2">
            <div class="absolute -top-1.5">
              <a href={`#${id}`} className="-ml-10 flex items-center opacity-0 border-0 group-hover/param-head:opacity-100 py-2 [.expandable-content_&]:-ml-[2.1rem]" aria-label="Navigate to header">
                ​<div className="w-6 h-6 rounded-md flex items-center justify-center shadow-sm text-gray-400 dark:text-white/50 dark:bg-background-dark dark:brightness-[1.35] dark:ring-1 dark:hover::rightness-150 bg-white ring-1 ring-gray-400/30 dark:ring-gray-700/25 hover:ring-gray-400/60 dark:hover:ring-white/20">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="gray" height="12px" viewBox="0 0 576 512"><path d="M0 256C0 167.6 71.6 96 160 96h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C98.1 144 48 194.1 48 256s50.1 112 112 112h72c13.3 0 24 10.7 24 24s-10.7 24-24 24H160C71.6 416 0 344.4 0 256zm576 0c0 88.4-71.6 160-160 160H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c61.9 0 112-50.1 112-112s-50.1-112-112-112H344c-13.3 0-24-10.7-24-24s10.7-24 24-24h72c88.4 0 160 71.6 160 160zM184 232H392c13.3 0 24 10.7 24 24s-10.7 24-24 24H184c-13.3 0-24-10.7-24-24s10.7-24 24-24z"></path></svg>
                </div>
              </a>
            </div>
            <div className="font-semibold text-primary dark:text-primary-light overflow-wrap-anywhere">{title}</div>
            <div className="inline items-center gap-2 text-xs font-medium [&_div]:inline [&_div]:mr-2 [&_div]:leading-5 [&_a]:inline [&_a]:mr-2 [&_a]:leading-5">
              {type && <div className="flex items-center px-2 py-0.5 rounded-md bg-gray-100/50 dark:bg-white/5 break-all">
                <span className="text-gray-600 dark:text-gray-200 !font-medium">{type}</span>
              </div>}
              {defaultValue && <div className="flex items-center px-2 py-0.5 rounded-md bg-gray-100/50 dark:bg-white/5 break-all">
                  <span class="text-gray-400 dark:text-gray-500">default:</span>
                  <span className="text-gray-600 dark:text-gray-200 !font-medium">{defaultValue}</span>
                </div>}
              {required && <div className="px-2 py-0.5 rounded-md bg-red-100/50 dark:bg-red-400/10 whitespace-nowrap">
                <span className="text-red-600 dark:text-red-300 !font-medium">Required</span>
              </div>}
              {cel && <a className="px-2 py-0.5 rounded-md !border-none bg-blue-100/50 dark:bg-blue-400/10 whitespace-nowrap" href="/traffic-policy/concepts/cel-interpolation">
                <span className="text-blue-600 dark:text-blue-300 !font-medium">Supports CEL</span>
              </a>}
            </div>
          </div>
        </div>
      </div>
      <div className="mt-4 prose-sm prose-gray dark:prose-invert [&_.prose>p:first-child]:mt-0 [&_.prose>p:last-child]:mb-0">
        {children}
      </div>
    </div>;
};

The **Restrict IPs** Traffic Policy action allows you to allow or deny traffic based on the source IP address of connections to your ngrok endpoints.

You can define rules using either **Allow and Deny lists**, or **Reference IDs** to existing ngrok [IP Policies](/api-reference/ippolicies/list).

<Tip>
  Need to allow or block traffic from a specific service (like GitHub, AWS, or OpenAI) without managing hundreds of CIDRs by hand?
  Use [IP Categories](/traffic-policy/variables/ip-intel) with a Traffic Policy expression instead.
  ngrok maintains up-to-date IP ranges for [dozens of services and threat categories](/traffic-policy/variables/ip-intel#ip-categories), so you can write rules like `'com.github' in conn.client_ip.categories` or `'proxy.anonymous.tor' in conn.client_ip.categories`.
  See [Filter Traffic by IP Category](/traffic-policy/examples/filter-by-ip-category) for examples.
</Tip>

## Configuration reference

The [Traffic Policy](/traffic-policy/) configuration
reference for this action.

### Supported phases

`on_http_request`, `on_http_response`, `on_tcp_connect`

### Type

`restrict-ips`

### Configuration fields

<ConfigField title="enforce" type="boolean" required={true}>
  Default true. If false, continue to the next action even if the IP is not permitted.
</ConfigField>

<ConfigField title="allow" type="array of strings" required={false} cel={true}>
  A list of CIDRs that are allowed.
</ConfigField>

<ConfigField title="deny" type="array of strings" required={false} cel={true}>
  A list of CIDRs that are denied.
</ConfigField>

<ConfigField title="ip_policies" type="array of refs" required={false}>
  List of [IP Policy](/api-reference/ippolicies/list) identifiers to be checked if the source IP is allowed access.
</ConfigField>

## Behavior

### Evaluation of rules

This action evaluates the configured rules against the layer 4 source IP
(`conn.client_ip`) of a connection.

HTTP headers like `X-Forwarded-For` are never used.

### Allow and deny conditions

A connection is allowed only if its source IP matches at least one of the
allowed CIDRs and does not match any of the denied CIDRs.

### Building CIDR sets

The set of allowed and denied CIDRs are built from:

* The CIDRs specified in the `allow` and `deny` fields.
* The CIDRs belonging to the ngrok [IP Policies](/api-reference/ippolicies/list)
  specified in the `ip_policies` field.

### Denied connection handling

If this action denies the connection:

* When used on the `on_tcp_connect` phase:
  * The connection is closed.
* When used on the `on_http_request` or `on_http_response` phase:
  * An `HTTP 403` response is returned.
* The upstream server is never reached.
* No further rules or actions in the Traffic Policy will be executed.

### IPv6 support

This action supports IPv6 addresses for all IP rules. You may use standard
abbreviated notations such as `"::/0"`.

Don't forget to create IPv6 rules. It is easy to test with only IPv4 and then
suddenly things don't work as expected because you forgot to create IPv6 rules.

### Non-terminating action

This is a **Non-terminating action**. It does not return a response, and will allow Traffic Policy processing to continue to the next Action in the chain. All **Cloud Endpoint** Traffic Policies must end with a terminating action. This requirement does not apply to **Agent Endpoints**.

## Examples `on_tcp_connect`

### Restricting access with allow and deny lists

The following [Traffic Policy](/traffic-policy)
configuration demonstrates how to restrict access to specific IP addresses
using the `restrict-ips` action.

#### Example Traffic Policy document

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_tcp_connect:
    - actions:
        - type: restrict-ips
          config:
            enforce: true
            allow:
              - 1.1.1.1/32
            deny:
              - 110.0.0.0/8
  ```

  ```json policy.json theme={null}
  {
    "on_tcp_connect": [
      {
        "actions": [
          {
            "type": "restrict-ips",
            "config": {
              "enforce": true,
              "allow": [
                "1.1.1.1/32"
              ],
              "deny": [
                "110.0.0.0/8"
              ]
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

This configuration will ensure that only requests from the IP `1.1.1.1` are
allowed, while requests from the IP `110.0.0.0`
are denied.

#### Example request

If the request comes from an allowed IP, the response will proceed as normal. If
the request comes from a denied IP, the connection will be closed:

```bash theme={null}
$ telnet 5.tcp.ngrok.io 22984

Trying...
Connected to 5.tcp.ngrok.io.
Connection closed by foreign host.
```

### Restricting access with IP Policies

The following [Traffic Policy](/traffic-policy)
configuration demonstrates how to restrict access using the `restrict-ips`
action with [IP Policies](/api-reference/ippolicies/list).

#### Example Traffic Policy document

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_tcp_connect:
    - actions:
        - type: restrict-ips
          config:
            enforce: true
            ip_policies:
              - ipp_1yjqdrIBwgciY2I9zH2EelgBbJF
  ```

  ```json policy.json theme={null}
  {
    "on_tcp_connect": [
      {
        "actions": [
          {
            "type": "restrict-ips",
            "config": {
              "enforce": true,
              "ip_policies": [
                "ipp_1yjqdrIBwgciY2I9zH2EelgBbJF"
              ]
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

This configuration will ensure that the [IP Policies](/api-reference/ippolicies/list)
specified `ipp_1yjqdrIBwgciY2I9zH2EelgBbJF` are enforced against incoming
traffic.

#### Example request

If the request comes from an allowed IP, the response will proceed as normal. If
the request comes from a denied IP, you will receive an HTTP `403` response:

```bash theme={null}
$ telnet 5.tcp.ngrok.io 22984

Trying...
Connected to 5.tcp.ngrok.io.
Connection closed by foreign host.
```

snippets/traffic-policy/actions/restrict-ips/tcp/examples/3-testing-traffic

## Examples `on_http_request`

### Restricting access with allow and deny lists

The following [Traffic Policy](/traffic-policy/)
configuration demonstrates how to restrict access to specific IP addresses
using the `restrict-ips` action.

#### Example Traffic Policy document

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_http_request:
    - actions:
        - type: restrict-ips
          config:
            enforce: true
            allow:
              - 1.1.1.1/32
            deny:
              - e680:5791:be4c:5739:d959:7b94:6d54:d4b4/128
  ```

  ```json policy.json theme={null}
  {
    "on_http_request": [
      {
        "actions": [
          {
            "type": "restrict-ips",
            "config": {
              "enforce": true,
              "allow": [
                "1.1.1.1/32"
              ],
              "deny": [
                "e680:5791:be4c:5739:d959:7b94:6d54:d4b4/128"
              ]
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

This configuration will ensure that only requests from the IP `1.1.1.1` are
allowed, while requests from the IP `e680:5791:be4c:5739:d959:7b94:6d54:d4b4`
are denied.

#### Example request

If the request comes from an allowed IP, the response will proceed as normal. If
the request comes from a denied IP, you will receive an HTTP `403` response:

```bash theme={null}
$ curl -i https://example.ngrok.app
```

```http theme={null}
HTTP/2 403
```

### Restricting access with IP Policies

The following [Traffic Policy](/traffic-policy/)
configuration demonstrates how to restrict access using the `restrict-ips`
action with [IP Policies](/api-reference/ippolicies/list).

#### Example Traffic Policy document

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_http_request:
    - actions:
        - type: restrict-ips
          config:
            enforce: true
            ip_policies:
              - ipp_1yjqdrIBwgciY2I9zH2EelgBbJF
  ```

  ```json policy.json theme={null}
  {
    "on_http_request": [
      {
        "actions": [
          {
            "type": "restrict-ips",
            "config": {
              "enforce": true,
              "ip_policies": [
                "ipp_1yjqdrIBwgciY2I9zH2EelgBbJF"
              ]
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

This configuration will ensure that the [IP Policies](/api-reference/ippolicies/list)
specified `ipp_1yjqdrIBwgciY2I9zH2EelgBbJF` are enforced against incoming
traffic.

#### Example request

If the request comes from an allowed IP, the response will proceed as normal. If
the request comes from a denied IP, you will receive an HTTP `403` response:

```bash theme={null}
$ curl -i https://example.ngrok.app
```

```http theme={null}
HTTP/2 403
```

### Test restricting IPs

The following [Traffic Policy](/traffic-policy/)
configuration demonstrates how to test restricting IPs using the [`log`](/traffic-policy/actions/log/)
action with the `restrict-ips` action and [IP Policies](/api-reference/ippolicies/list).

#### Example Traffic Policy document

<CodeGroup>
  ```yaml policy.yml theme={null}
  on_http_request:
    - actions:
        - type: restrict-ips
          config:
            enforce: false
            ip_policies:
              - ipp_1yjqdrIBwgciY2I9zH2EelgBbJF
        - type: log
          config:
            metadata:
              message: Restrict IPs action would be ${actions.ngrok.restrict_ips.action} for ${conn.client_ip}.
              matched_cidr: ${actions.ngrok.restrict_ips.matched_cidr}
              error_code: ${actions.ngrok.restrict_ips.error.code}
              error_message: ${actions.ngrok.restrict_ips.error.message}
  ```

  ```json policy.json theme={null}
  {
    "on_http_request": [
      {
        "actions": [
          {
            "type": "restrict-ips",
            "config": {
              "enforce": false,
              "ip_policies": [
                "ipp_1yjqdrIBwgciY2I9zH2EelgBbJF"
              ]
            }
          },
          {
            "type": "log",
            "config": {
              "metadata": {
                "message": "Restrict IPs action would be ${actions.ngrok.restrict_ips.action} for ${conn.client_ip}.",
                "matched_cidr": "${actions.ngrok.restrict_ips.matched_cidr}",
                "error_code": "${actions.ngrok.restrict_ips.error.code}",
                "error_message": "${actions.ngrok.restrict_ips.error.message}"
              }
            }
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

This configuration will test the incoming client IP against the specified
[IP Policy](/api-reference/ippolicies/list) `ipp_1yjqdrIBwgciY2I9zH2EelgBbJF`
without enforcing it, then log the result using the [`log`](/traffic-policy/actions/log/)
action.

#### Example request

The following request will be allowed and an event will be logged:

```bash theme={null}
$ curl -i https://example.ngrok.app
```

```http theme={null}
HTTP/2 200
```

## Action result variables

The following variables are made available for use in subsequent expressions and
CEL interpolations after the action has run. Variable values will only apply
to the last action execution, results are not concatenated.

<ConfigField title="actions.ngrok.restrict_ips.action" type="string">
  The action taken for this request.

  <ConfigEnum label="Possible values">
    <ConfigEnumOption>`allow` - If the request was permitted.</ConfigEnumOption>
    <ConfigEnumOption>`deny` - If the request was denied.</ConfigEnumOption>
  </ConfigEnum>
</ConfigField>

<ConfigField title="actions.ngrok.restrict_ips.matched_cidr" type="string">
  The CIDR block that matched the incoming client's IP address. If no match was found, this value will be empty.
</ConfigField>

<ConfigField title="actions.ngrok.restrict_ips.error.code" type="string">
  A machine-readable code describing an error that occurred during the action's execution.
</ConfigField>

<ConfigField title="actions.ngrok.restrict_ips.error.message" type="string">
  A human-readable message providing details about an error that occurred during the action's execution.
</ConfigField>
