---
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/).

> **Tip**
>
> This page carries separate instructions for API v4 and API v3. To find out which apply to your account, refer to [Verify your account migration](/en/documentation/guides/application-security/access-and-compliance/verify-account-migration/).

---

## Prerequisites

### Console

- 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).
- 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

- 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).
- [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 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).
- 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.

In the [Protect web applications from OWASP Top 10 and zero-day attacks](/en/documentation/use-cases/secure-applications-and-networks/protect-web-applications-from-owasp-top-10-and-zero-day-attacks/) use case, this section takes these values:

| Setting      | Value                                                                                                                              |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| Network list | `webapp-blocked-addresses`, of the *IP/CIDR* type, with one address per line, such as `198.51.100.7 #blocked by the security team` |

---

## 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.

In the [Protect web applications from OWASP Top 10 and zero-day attacks](/en/documentation/use-cases/secure-applications-and-networks/protect-web-applications-from-owasp-top-10-and-zero-day-attacks/) use case, this section takes these values:

| Setting                              | Value                                                                                                                                                     |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Rule                                 | `webapp - deny listed networks`                                                                                                                           |
| Criteria, one block joined by **Or** | *Network* *matches* `webapp-blocked-addresses`, and *Network* *matches* `Azion IP Tor Exit Nodes`, list `2`. The API sends each list ID as a JSON integer |
| Behavior                             | *Deny (403 Forbidden)*                                                                                                                                    |
| Position                             | First on the firewall, created before the WAF and Bot Manager rules                                                                                       |

A client in either list receives `403` once the rule propagates, which takes 6 to 10 minutes for a new rule. A later change to the items of `webapp-blocked-addresses` reaches traffic in about 100 seconds, with no change to the rule.

---

## 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.

In the [Protect web applications from OWASP Top 10 and zero-day attacks](/en/documentation/use-cases/secure-applications-and-networks/protect-web-applications-from-owasp-top-10-and-zero-day-attacks/) use case, expect:

- **A listed source is refused before inspection.** From an address in `webapp-blocked-addresses`, a request for the home page receives `403`.

In the [Screen file uploads for malicious content](/en/documentation/use-cases/secure-applications-and-networks/screen-file-uploads-for-malicious-content/) use case, expect:

- **A flagged sender is refused everywhere.** From an address in `upload-senders`, a request for the home page receives `403`.

---

## Bind the firewall on a v3 domain

The rule needs the firewall to inspect the requests of your hostnames. An account that runs on API v3 has Domains in place of workloads, and binds the firewall on the domain itself rather than on a deployment. To find out which model your account runs on, refer to [Verify your account migration](/en/documentation/guides/application-security/access-and-compliance/verify-account-migration/).

To bind the firewall to a domain in Azion Console:

1. **Open the domain**

   Access [Azion Console](https://console.azion.com/) > **Domains** > **the domain whose requests the firewall inspects**.

2. **Choose the firewall**

   In the **Settings** section, open the **Firewall** selector and choose the firewall that holds the rule.

3. **Save the domain**

   Select **Save**.

The network list, the rule, and the confirmation are the same on both models: only the binding changes.

---

## 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.
- [Protect web applications from OWASP Top 10 and zero-day attacks](/en/documentation/use-cases/secure-applications-and-networks/protect-web-applications-from-owasp-top-10-and-zero-day-attacks.md): A deny rule on two network lists that runs first on the firewall, ahead of the WAF and Bot Manager rules.
- [Screen file uploads for malicious content](/en/documentation/use-cases/secure-applications-and-networks/screen-file-uploads-for-malicious-content.md): A sender list that blocks the addresses whose files a model flagged.
