---
name: azion-block-tor-exit-nodes
description: >-
  Drop every request from a Tor exit node with one firewall rule on the Azion IP Tor Exit Nodes list, from Azion Console, Azion CLI, or the API.
---

# Block Tor exit nodes

You can drop requests from Tor exit nodes with one [firewall](/en/documentation/platform/firewall/) rule, from Azion Console, Azion CLI, or the API. To block addresses, networks, or countries you choose, refer to [Block requests by IP, ASN, or country](/en/documentation/guides/application-security/bots-and-network/blocklists-ip-addresses-edge/). To deploy a new firewall that also scores bots, refer to [Block bots and Tor exit nodes with a template](/en/documentation/guides/application-development/frameworks/bot-manager-lite-and-tor-block-starter-kit/).

A Tor exit node is the final point where the Tor network connects to the internet. Tor encryption ends at that node, so the node can see the data a request carries. Traffic from exit nodes can therefore raise security concerns, and it can be malicious.

Azion maintains the `Azion IP Tor Exit Nodes` [network list](/en/documentation/platform/firewall/network-shield/network-lists/) in every account, with the ID `2`. It holds the IP addresses of Tor exit nodes, Azion refreshes them, and no account can change the list. There is no list to create or keep current, only a rule to add. A rule in the [Rules Engine](/en/documentation/platform/firewall/rules-engine/) matches the list through the *Network* criterion. [Network Shield](/en/documentation/platform/firewall/#network-shield) makes that criterion available on a firewall. One rule or several can reference the list, and each rule matches the addresses the list holds after every refresh.

---

Select the interface you work in. The prerequisites and both tasks on this page follow that choice.

## 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/).
- Network Shield on for that firewall, which is the default for a new firewall. To check the setting, 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).
- The **Edit Firewall** permission to add the rule, and **View Network Lists** to read the Tor list. 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.

---

## Add the rule that drops the Tor list

The rule holds one criterion, true when the client address of a request is in list `2`. Its behavior, *Drop (Close Without Response)*, closes the connection without an HTTP response. *Deny (403 Forbidden)* answers with Azion's `403` error page instead. To choose between the two, refer to [Deny while you roll a block out, then drop](/en/documentation/platform/firewall/best-practices/#deny-while-you-roll-a-block-out-then-drop).

**Console**

To add the rule in Azion Console:

1. **Open the Firewalls page**

   Access [Azion Console](https://console.azion.com/) > **Secure** > **Firewalls**.

2. **Select the firewall bound to your workload**

3. **Select the Rules Engine tab**

4. **Start a rule**

   Select **Rule**. The **Create Rule** drawer opens.

5. **Name the rule**

   In the **General** section, enter a **Name**. For example: `Block Tor Exit Nodes`.

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

   In the **Description** field, enter a short comment on the rule.

7. **Set the Network criterion**

   In the **Criteria** section, select the *Network* variable and the *matches* operator.

   If the variable reads *Network - required Network Shield*, the firewall has Network Shield off. Turn it on in **Main Settings** and save, and the variable becomes selectable.

8. **Select the Tor list**

   In the **Select a Network** dropdown, select *Azion IP Tor Exit Nodes*.

9. **Add the Drop behavior**

   In the **Behaviors** section, select *Drop (Close Without Response)*.

10. **Save the rule**

    Select **Save**.

Azion Console shows the message `Rule successfully created`, and the rule appears in the **Rules Engine** tab.

**CLI**

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

1. **Confirm the ID of the Tor list**

   List the network lists in your account:

   ```bash
   azion list network-list
   ```

   The table shows the Tor list with the ID `2`. The lists your account created appear as more rows:

   ```text
   ID     NAME                              ACTIVE
   2      Azion IP Tor Exit Nodes           true
   ```

2. **Write the rule to a file**

   Save the following as `rule.json`. The `argument` is `2`, the ID of the Tor list, as a number without quotes:

   ```json
   {
     "name": "Block Tor Exit Nodes",
     "active": true,
     "criteria": [
       [
         { "variable": "${network}", "conditional": "if", "operator": "is_in_list", "argument": 2 }
       ]
     ],
     "behaviors": [
       { "type": "drop" }
     ]
   }
   ```

3. **Create the rule**

   Replace `<firewall-id>` with the ID of your firewall:

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

4. **Read the output**

   The command prints the ID of the new rule:

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

The firewall holds the rule. Record its ID to read the rule back.

**API**

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

1. **Confirm the ID of the Tor list**

   Replace `[TOKEN VALUE]` with your personal token, and read list `2`:

   ```bash
   curl "https://api.azion.com/v4/workspace/network_lists/2?fields=id,name,type,active,last_editor,last_modified" \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json"
   ```

   The read answers `200`. A `last_editor` of `Azion` marks a list that Azion maintains, and `last_modified` changes each time Azion refreshes the items:

   ```json
   {
     "data": {
       "id": 2,
       "name": "Azion IP Tor Exit Nodes",
       "type": "ip_cidr",
       "last_editor": "Azion",
       "last_modified": "2026-01-01T12:00:00.000000Z",
       "active": true,
       "is_versioned": false,
       "version": null
     }
   }
   ```

2. **Send the create request**

   Replace `<firewall-id>` with the ID of your firewall. In the body, `name` names the rule, `criteria` holds its conditions, and `behaviors` holds what it does on a match. The `argument` is `2`, as a number without 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": "Block Tor Exit Nodes",
     "active": true,
     "criteria": [
       [
         { "variable": "${network}", "conditional": "if", "operator": "is_in_list", "argument": 2 }
       ]
     ],
     "behaviors": [
       { "type": "drop" }
     ]
   }'
   ```

3. **Read the response**

   A create answers `202`, and a `state` of `pending` means the API accepted the rule. The `order` field counts the rule's position on the firewall from `0`:

   ```json
   {
     "state": "pending",
     "data": {
       "id": <rule-id>,
       "name": "Block Tor Exit Nodes",
       "active": true,
       "criteria": [
         [
           { "conditional": "if", "variable": "${network}", "operator": "is_in_list", "argument": 2 }
         ]
       ],
       "behaviors": [{ "type": "drop" }],
       "description": "",
       "order": 0
     }
   }
   ```

Record the value of `data.id`, the ID of the rule. An `argument` sent as a string is refused with `400` and `25042 Invalid Operator Argument Type`. On a firewall with Network Shield off, the rule is refused with `25047 Missing Required Modules`. For every criterion and behavior a rule can hold, refer to [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/#criteria).

Once the rule reaches Azion's distributed infrastructure, the firewall drops every request from an address in the Tor list. The client receives no status line and no body. A rule you add takes several minutes to get there. For the propagation times, refer to [How Firewall works](/en/documentation/platform/firewall/how-it-works/#propagation).

---

## Confirm the rule is saved

A request from your own connection does not test the Tor rule. Your address is not in the Tor list, and any write that would add it is refused with `22004`. Read the rule back instead, and check that it names list `2` and the drop behavior.

**Console**

To read the rule in Azion Console:

1. **Open the Firewalls page**

   Access [Azion Console](https://console.azion.com/) > **Secure** > **Firewalls**.

2. **Select the firewall bound to your workload**

3. **Select the Rules Engine tab**

   The rule appears in the list of rules, with *Active* in the **Status** column.

4. **Open the rule**

   Select the rule. The **Edit Rule** drawer opens.

5. **Read the criterion**

   In the **Criteria** section, the rule reads *Network*, *matches*, and *Azion IP Tor Exit Nodes*.

6. **Read the behavior**

   In the **Behaviors** section, the rule reads *Drop (Close Without Response)*.

The rule is saved on the firewall with the Tor list as its criterion and the drop behavior.

**CLI**

To read the rule with Azion CLI:

1. **List the rules of the firewall**

   Replace `<firewall-id>` with the ID of your firewall:

   ```bash
   azion list firewall-rule --firewall-id <firewall-id>
   ```

   The rule appears in the table, with `true` in the `ACTIVE` column:

   ```text
   ID         NAME                   ACTIVE  DESCRIPTION
   <rule-id>  Block Tor Exit Nodes   true
   ```

2. **Print the full rule**

   Replace `<rule-id>` with the ID of the rule:

   ```bash
   azion describe firewall-rule --firewall-id <firewall-id> --rule-id <rule-id> --format json
   ```

   The command prints the full record of the rule, with `argument` as the integer `2`.

The rule is saved on the firewall with the criteria and behavior in `rule.json`.

**API**

To read the rule, send a `GET` request to `/v4/workspace/firewalls/{firewall_id}/request_rules/{request_rule_id}`:

1. **Send the read request**

   Replace `<firewall-id>` with the ID of your firewall and `<rule-id>` with the ID of the rule:

   ```bash
   curl https://api.azion.com/v4/workspace/firewalls/<firewall-id>/request_rules/<rule-id> \
     -H "Authorization: Token [TOKEN VALUE]" \
     -H "Accept: application/json"
   ```

2. **Read the response**

   A read answers `200` with the rule as stored:

   ```json
   {
     "data": {
       "id": <rule-id>,
       "name": "Block Tor Exit Nodes",
       "last_editor": "<your-email>",
       "last_modified": "2026-01-01T12:00:00.000000Z",
       "created_at": "2026-01-01T12:00:00.000000Z",
       "active": true,
       "criteria": [
         [
           { "conditional": "if", "variable": "${network}", "operator": "is_in_list", "argument": 2 }
         ]
       ],
       "behaviors": [{ "type": "drop" }],
       "description": "",
       "order": 0
     }
   }
   ```

The rule reads back as you sent it, with `argument` as the integer `2`. The platform fills in `last_editor`, `last_modified`, `created_at`, and `order`.

To see the rule act on traffic, turn on **Debug Rules** in the firewall's **Main Settings**. The firewall then logs the rules that run, and [Real-Time Events](/en/documentation/platform/real-time-events/) shows them. For the setting, refer to [Set a firewall's main settings](/en/documentation/guides/application-security/firewall-and-waf/firewall-configure-main-settings/#log-the-rules-a-firewall-runs).

---

## Next steps

- [Azion-maintained lists](/en/documentation/platform/firewall/network-shield/network-lists.md#azion-maintained-lists): The lists Azion keeps in every account, their IDs, and why a write to one is refused.
- [List matching](/en/documentation/platform/firewall/network-shield/list-matching.md): What a dropped client receives, and how long a rule takes to reach traffic.
- [Block bots and Tor exit nodes with a template](/en/documentation/guides/application-development/frameworks/bot-manager-lite-and-tor-block-starter-kit.md): Deploy a firewall that scores bots with Bot Manager Lite and denies the Tor list.
- [Firewall best practices](/en/documentation/platform/firewall/best-practices.md#network-shield): When to deny rather than drop, and why a rule references list 2 rather than a copy.
