---
name: azion-find-the-ips-behind-attack-traffic
description: >-
  List the IP addresses that send the most requests WAF flags as attacks, with the attack family of each, from the GraphQL API.
---

# Find the IPs behind attack traffic

You can list the five IP addresses that send the most requests [WAF](/en/documentation/platform/firewall/#waf) flags as attacks, with the attack family of each, from the `workloadEvents` dataset of the GraphQL API. The dataset holds one record per request, and the events endpoint serves it. To rank the same addresses from aggregated data, or in Azion Console, refer to [Find the top sources of WAF threats](/en/documentation/guides/platform/observability/find-top-waf-threat-sources/).

---

## Prerequisites

- A personal token. To create one, refer to [How to manage a personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/).
- WAF turned on in a firewall bound to the workload that receives the traffic. To set it up, refer to [WAF quickstart](/en/documentation/platform/firewall/waf/quickstart/).
- A way to send a GraphQL query, such as GraphiQL or `curl`. For both, refer to [First steps with the GraphQL API](/en/documentation/devtools/graphql/first-steps/).

---

## Query the top IPs

The query counts the records WAF matched, groups them by client address and attack family, and returns the five largest counts. The events endpoint keeps records for about 7 days, so set a window inside the last 7 days. For the retention of each endpoint, refer to [Limits](/en/documentation/devtools/graphql/limits/).

To find the top IPs:

1. **Send the query to the events endpoint**

   Send a `POST` request to `https://api.azion.com/v4/events/graphql` with the header `Authorization: Token [TOKEN VALUE]`. Replace the `begin` and `end` values with your window, in the format `YYYY-MM-DDTHH:mm:ss`:

   ```graphql
   query TOP5IPsWAFRequests {
     workloadEvents(
       limit: 5
       filter: {
         tsRange: {
           begin:"2026-09-26T14:00:00"
           end:"2026-10-03T14:00:00"
         },
         wafMatchNe: "-"
         wafAttackFamilyNe: "-"
       }
       aggregate: {
         count: rows
       }
       groupBy:[remoteAddress, wafAttackFamily]
       orderBy:[count_DESC]
     )
     {
       remoteAddress
       wafAttackFamily
       count
     }
   }
   ```

   Each argument sets one part of the ranking:

   | Argument                 | What it does                                                                                       |
   | ------------------------ | -------------------------------------------------------------------------------------------------- |
   | `limit`                  | Returns at most this number of rows, here `5`.                                                     |
   | `tsRange`                | Inside `filter`, sets the window with `begin` and `end`.                                           |
   | `wafMatchNe: "-"`        | Excludes the records whose `wafMatch` is `-`, the value of a request WAF found no infraction in.   |
   | `wafAttackFamilyNe: "-"` | Excludes the records whose `wafAttackFamily` is `-`, the value of a request with no attack family. |
   | `count: rows`            | Inside `aggregate`, counts the records in each group and returns the total in `count`.             |
   | `groupBy`                | Groups the records by client address, then by attack family.                                       |
   | `orderBy`                | Sorts the rows by `count`: `count_DESC` puts the highest first, and `count_ASC` the lowest.        |

2. **Read the rows**

   The response holds a `workloadEvents` array inside `data`, with one object per address and attack family:

   | Field             | Description                                                                                 |
   | ----------------- | ------------------------------------------------------------------------------------------- |
   | `remoteAddress`   | The IP address of the client that sent the requests.                                        |
   | `wafAttackFamily` | The attack family WAF detected, such as `$SQL`, `$XSS`, `$RFI`, `$TRAVERSAL`, or `$OTHERS`. |
   | `count`           | The number of requests from the address that WAF flagged as attacks of the family.          |

An address that sent attacks of several families returns one row per family. The rows come in the order `orderBy` sets, with the largest count first. For every field of the dataset, refer to [Real-Time Events fields](/en/documentation/devtools/graphql/gql-real-time-events-fields/).

---

## Next steps

- [Network lists](/en/documentation/platform/firewall/network-shield/network-lists.md): Put the addresses in a list that a firewall rule matches.
- [Find the top attacks with GraphQL](/en/documentation/guides/platform/observability/query-top-attacks-with-graphql.md): Rank the attack families by the threats WAF counted.
- [Real-Time Events fields](/en/documentation/devtools/graphql/gql-real-time-events-fields.md): Look up every field of workloadEvents, including the other WAF fields.
- [Tune a WAF rule set](/en/documentation/guides/application-security/firewall-and-waf/tune-waf.md): Adjust the rule set after you see which families reach your workload.
