---
name: azion-block-requests-by-ip-asn-or-country
description: >-
  Create a network list of IP addresses, ASNs, or countries and deny it in a firewall rule, from Azion Console, the Azion CLI, or the API.
---

# Block requests by IP, ASN, or country

You can block requests by IP address, Autonomous System Number (ASN), or country with [Network Shield](/en/documentation/platform/firewall/#network-shield), from Azion Console, the Azion CLI, or the API.

The block takes two objects. A [network list](/en/documentation/platform/firewall/network-shield/network-lists/) holds the entries to keep out. A rule in the [Rules Engine](/en/documentation/platform/firewall/rules-engine/) of a [firewall](/en/documentation/platform/firewall/) denies every request whose client the list covers. The list blocks nothing until a rule references it, and the rule acts only on a [workload](/en/documentation/platform/workloads/) bound to its firewall.

Tor exit nodes already have a list that Azion maintains. To block them, refer to [Block Tor exit nodes](/en/documentation/guides/application-security/bots-and-network/block-tor-networks/).

---

Select an interface. The prerequisites and each task on this page switch to it.

## Prerequisites

- A firewall bound to the workload that serves your application. To bind one, refer to [Bind a firewall to a workload](/en/documentation/guides/application-security/firewall-and-waf/firewall-protect-your-domain/), which covers both Workloads and the legacy [Domains](/en/documentation/platform/workloads/domains/) setting.
- Network Shield on for that firewall, which is the default for a firewall you create. To confirm it, refer to [Set a firewall's main settings](/en/documentation/guides/application-security/firewall-and-waf/firewall-configure-main-settings/#change-the-products-enabled-on-a-firewall).
- **Edit Network Lists** and **Edit Firewall** in your team permissions. For more information, refer to [Network Lists](/en/documentation/platform/firewall/network-shield/network-lists/#permissions).

**Console**

- Access to Azion Console. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**CLI**

- [Azion CLI](/en/documentation/devtools/cli/), installed and authorized. The commands on this page match Azion CLI 4.23.0.
- The ID of the firewall bound to your workload.

**API**

- A personal token and `curl`. To create a token, refer to [Personal Tokens](/en/documentation/fundamentals/personal-tokens/).
- The ID of the firewall bound to your workload.

---

## Create the network list

Every item in a network list has the type of the list, and the type decides how many clients one item covers. Pick the type by what you want to keep out:

| To keep out                             | Type        | Console label | Item format                                               | Example                                          |
| --------------------------------------- | ----------- | ------------- | --------------------------------------------------------- | ------------------------------------------------ |
| Specific addresses or ranges.           | `ip_cidr`   | *IP/CIDR*     | An IPv4 or IPv6 address, with or without a prefix length. | `192.0.2.10`, `198.51.100.0/24`, `2001:db8::/32` |
| Every address in one autonomous system. | `asn`       | *ASN*         | The ASN, digits only.                                     | `64496`                                          |
| Every address located in one country.   | `countries` | *Countries*   | An ISO 3166-1 alpha-2 code, in two uppercase letters.     | `BR`                                             |

A countries or ASN item covers every client in that country or network, legitimate clients included. For how Azion places a client in a country or an ASN, refer to [List matching](/en/documentation/platform/firewall/network-shield/list-matching/#list-matching).

The type never changes after you create the list, so a second kind of entry needs a second list. Exact duplicate items are removed without a warning. Equivalent notations are not duplicates, so `192.0.2.80` and `192.0.2.80/32` are both kept.

An `ip_cidr` item can also carry a `--LT` due date and a `#` comment. For the syntax, refer to [Network Lists](/en/documentation/platform/firewall/network-shield/network-lists/#item-annotations).

**Console**

To create the list in Azion Console:

1. **Open the Network Lists page**

   Access [Azion Console](https://console.azion.com/) > **Edge Libraries** > **Network Lists**.

2. **Start a list**

   Select **Network List**.

3. **Name the list**

   In the **General** section, enter a **Name**. For example: `blocked-addresses`. A rule's **Select a Network** dropdown offers the list by this name.

4. **Select the type**

   In the **Network List Settings** section, select *IP/CIDR*, *ASN*, or *Countries*. *ASN* is selected when the form opens.

5. **Enter the items**

   For *IP/CIDR* or *ASN*, enter one item per line in the **List** field. For example:

   ```text
   192.0.2.10
   198.51.100.0/24
   2001:db8::/32
   ```

   In this field, an ASN can also start with `AS`. For *Countries*, select one or more countries by name in the **Countries** field.

6. **Save the list**

   Select **Save**.

Azion Console confirms with `Your network list has been created`. The list appears in **Network Lists**, and its **List Type** column shows the type you selected.

**CLI**

To create the list with the Azion CLI:

1. **Run the create command for your type**

   Pass the items with `--items` or `--file`. Without either, the command asks for the items and fails when no terminal answers.

   For a `countries` list, pass the two-letter codes, separated by commas:

   ```bash
   azion create network-list --name "Blocked countries" --type countries --items "BR,US"
   ```

   For an `asn` list, pass the numbers, digits only:

   ```bash
   azion create network-list --name "Blocked networks" --type asn --items "64496"
   ```

   For an `ip_cidr` list, save the fields of the list in a file named `network-list.json`:

   ```json
   {"name":"Blocked addresses","type":"ip_cidr","items":["203.0.113.0/24","198.51.100.7"],"active":true}
   ```

   Then pass the file:

   ```bash
   azion create network-list --file network-list.json
   ```

2. **Read the output**

   Each command answers with the ID of the list:

   ```text
   Created Network List with ID <network-list-id>
   ```

The list holds the items you passed. Record its ID, which the firewall rule takes as its argument.

**API**

To create the list, send a `POST` request to `/v4/workspace/network_lists`:

1. **Send the create request for your type**

   Put your personal token in place of `[TOKEN VALUE]`. For an `ip_cidr` list, send the addresses and ranges:

   ```bash
   curl -X POST https://api.azion.com/v4/workspace/network_lists \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"name":"Blocked addresses","type":"ip_cidr","items":["192.0.2.10","198.51.100.0/24","2001:db8::/32"]}'
   ```

   For an `asn` list, send each number as a string of digits:

   ```bash
   curl -X POST https://api.azion.com/v4/workspace/network_lists \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"name":"Blocked networks","type":"asn","items":["64496"]}'
   ```

   For a `countries` list, send the two-letter codes:

   ```bash
   curl -X POST https://api.azion.com/v4/workspace/network_lists \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"name":"Blocked countries","type":"countries","items":["BR"]}'
   ```

2. **Read the response**

   The API stores the list at once, so the response carries `201` and a `state` of `executed`. The `ip_cidr` request returns:

   ```json
   {
     "state": "executed",
     "data": {
       "id": <network-list-id>,
       "name": "Blocked addresses",
       "type": "ip_cidr",
       "items": ["192.0.2.10", "198.51.100.0/24", "2001:db8::/32"],
       "last_editor": "<your-email>",
       "last_modified": "2026-01-01T12:00:00.000000Z",
       "created_at": "2026-01-01T12:00:00.000000Z",
       "active": true,
       "version_id": null,
       "version_state": null,
       "is_versioned": false,
       "version": null
     }
   }
   ```

   The `asn` and `countries` requests return the same object, with their own `type` and `items`:

   ```text
   {"state":"executed","data":{"id":<network-list-id>,"name":"Blocked networks","type":"asn","items":["64496"],…,"active":true,…}}
   {"state":"executed","data":{"id":<network-list-id>,"name":"Blocked countries","type":"countries","items":["BR"],…,"active":true,…}}
   ```

The list holds the items you sent. Record the value of `data.id`, which the firewall rule sends as a number.

---

## Deny the list in a firewall rule

The rule compares the client IP address of each request with your list through the *Network* criterion, `${network}` in the API. With the *matches* operator, `is_in_list` in the API, the criterion is true for a client in the list. The *Deny (403 Forbidden)* behavior, `deny` in the API, then refuses the request. The rule on this page has that one criterion, so it applies to every path of the workload.

Network Shield makes the *Network* criterion available on the firewall, while the behavior belongs to Firewall. To close the connection with no response instead of a `403`, use *Drop (Close Without Response)*, `drop` in the API. For every behavior a rule can run, refer to [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/#behaviors).

**Console**

To create the rule in Azion Console:

1. **Open the firewall**

   Access [Azion Console](https://console.azion.com/) > **Secure** > **Firewalls**, and select the firewall bound to your workload.

2. **Select the Rules Engine tab**

3. **Start a rule**

   Select **Rule** to open the **Create Rule** drawer.

4. **Name the rule**

   In the **General** section, enter a **Name**. For example: `Deny blocked addresses`.

5. **(Optional) Describe the rule**

   In the **General** section, enter a **Description**.

6. **Set the Network criterion**

   In the **Criteria** section, set the variable to *Network* and the operator to *matches*. The condition then reads *If* *Network* *matches*, and the next field takes the list.

   A variable that reads *Network - required Network Shield* means that Network Shield is off for the firewall. Turn Network Shield on in the **Main Settings** tab and select **Save**. The variable then becomes selectable.

7. **Select the list**

   Open the **Select a Network** dropdown and select your list. If the list does not exist yet, select **Create Network List** in the same dropdown, which opens the **Create Network** drawer.

8. **Add the Deny behavior**

   In the **Behaviors** section, select *Deny (403 Forbidden)*.

9. **Keep the rule active**

   In the **Status** section, keep **Active** turned on.

10. **Save the rule**

    Select **Save**.

Azion Console confirms with `Rule successfully created`. The **Rules Engine** tab lists the rule, and its **Status** column reads *Active*.

**CLI**

`azion create firewall-rule` reads the rule from a JSON file. To create the rule with the Azion CLI:

1. **Save the rule as JSON**

   Write this rule to a file named `rule.json`, with the ID of your list in place of `<network-list-id>`. The ID is a number, so leave it without quotes:

   ```json
   {
     "name": "Deny blocked addresses",
     "active": true,
     "criteria": [
       [
         { "variable": "${network}", "conditional": "if", "operator": "is_in_list", "argument": <network-list-id> }
       ]
     ],
     "behaviors": [ { "type": "deny" } ]
   }
   ```

2. **Run the create command**

   Pass the ID of your firewall in place of `<firewall-id>`:

   ```bash
   azion create firewall-rule --firewall-id <firewall-id> --file rule.json
   ```

3. **Read the output**

   The output names the ID of the rule:

   ```text
   Created Firewall Rule with ID <rule-id>
   ```

The firewall carries the rule, and the rule denies the clients in the list once it reaches traffic.

**API**

To create the rule, send a `POST` request to `/v4/workspace/firewalls/{firewall_id}/request_rules`:

1. **Send the create request**

   Put your personal token in place of `[TOKEN VALUE]` and the ID of your firewall in place of `<firewall-id>`. The ID of your list goes in place of `<network-list-id>`, as a number with no quotes:

   ```bash
   curl -X POST https://api.azion.com/v4/workspace/firewalls/<firewall-id>/request_rules \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"name":"Deny blocked addresses","active":true,
          "criteria":[[{"variable":"${network}","conditional":"if","operator":"is_in_list","argument":<network-list-id>}]],
          "behaviors":[{"type":"deny"}]}'
   ```

2. **Read the response**

   The response carries `202`, a `state` of `pending`, and the stored rule:

   ```json
   {
     "state": "pending",
     "data": {
       "id": <rule-id>,
       "name": "Deny blocked addresses",
       "active": true,
       "criteria": [[{"conditional": "if", "variable": "${network}", "operator": "is_in_list", "argument": <network-list-id>}]],
       "behaviors": [{"type": "deny"}],
       "description": "",
       "order": 0
     }
   }
   ```

The API refuses a rule that sends the `argument` as a string, with `25042 Invalid Operator Argument Type`. It refuses `matches`, the Console label, as the operator, with `25039 Invalid Operator`. On a firewall with Network Shield off, it refuses the rule with `25047 Missing Required Modules`.

One list can back rules on many firewalls, and a change to its items changes what every one of those rules matches. While a rule references the list, you cannot delete the list (`22018`) or turn off Network Shield on the firewall (`24005`). To do either, delete or change the rule first.

---

## Confirm the block

A rule you add takes several minutes to reach traffic across Azion's distributed infrastructure. A new rule takes effect 6 minutes 29 seconds to 9 minutes 18 seconds after you create it. Until then, clients in the list still reach your application. For more information, refer to [How Firewall works](/en/documentation/platform/firewall/how-it-works/#propagation).

One request checks the rule, whichever interface created it. From a client that the list covers, send a request to your workload's domain:

```bash
curl -i https://<your-workload-domain>/
```

The firewall refuses the request with `403`:

```text
HTTP/2 403
server: nginx
date: Thu, 01 Jan 2026 12:00:00 GMT
content-type: text/html; charset=utf-8
x-content-type-options: nosniff
x-azion-request-id: <request-id>
x-azion-edge-location: <edge-location>
alt-svc: h3=":443"; ma=86400

<title>Azion - Default error page</title>
...
<h1 class="error-header__title">Forbidden</h1>
...
Your IP         <your-ip>
Request ID      <request-id>
Status Code     403
Edge Location   <edge-location>
```

The response carries Azion's default error page, headed **Forbidden**. The Your IP row holds the client address that the firewall checked against the list. The response names no firewall, rule, or list, and the `x-azion-request-id` header identifies the request in [Real-Time Events](/en/documentation/platform/real-time-events/).

A client outside the list receives your application's response instead. A rule with *Drop (Close Without Response)* sends no HTTP response at all, so `curl` exits with an error:

```text
curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
```

To test a block on your own address and one path first, refer to [Network Shield quickstart](/en/documentation/platform/firewall/network-shield/quickstart/). If a listed client still reaches the application after that wait, refer to [Troubleshoot Firewall](/en/documentation/platform/firewall/troubleshooting/#a-listed-client-still-reaches-the-application).

The firewall refuses every request from the clients in your list, on every path of the workload.

---

## Next steps

- [Network Lists](/en/documentation/platform/firewall/network-shield/network-lists.md): Look up the fields, item formats, annotations, and errors of the list you created.
- [List matching](/en/documentation/platform/firewall/network-shield/list-matching.md): See how the rule matches a client, what each behavior returns, and how fast a list change applies.
- [Deny requests from a list of countries](/en/documentation/guides/application-security/bots-and-network/deny-countries.md): Build the countries version of this block, from the list to the refused request.
- [Allow only the addresses in a list](/en/documentation/guides/application-security/bots-and-network/allowlist.md): Reverse the rule with does not match, so it refuses every client outside the list.
